cranelift-codegen 0.112.2

Low-level code generator library
Documentation
;; Pulley instruction selection and CLIF-to-MachInst lowering.

;; The main lowering constructor term: takes a clif `Inst` and returns the
;; register(s) within which the lowered instruction's result values live.
(decl partial lower (Inst) InstOutput)

;;;; Rules for Control Flow ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The main control-flow-lowering term: takes a control-flow instruction and
;; target(s) and emits the necessary instructions.
(decl partial lower_branch (Inst MachLabelSlice) Unit)

;; Unconditional jumps.
(rule (lower_branch (jump _) (single_target label))
      (emit_side_effect (pulley_jump label)))

;; Generic case for conditional branches.
(rule -1 (lower_branch (brif (maybe_uextend c) _ _) (two_targets then else))
      (emit_side_effect (pulley_br_if c then else)))

;; Conditional branches on `icmp`s.
(rule (lower_branch (brif (maybe_uextend (icmp cc a b @ (value_type $I32))) _ _)
                    (two_targets then else))
      (emit_side_effect (lower_brif_of_icmp32 cc a b then else)))

(decl lower_brif_of_icmp32 (IntCC Value Value MachLabel MachLabel) SideEffectNoResult)
(rule (lower_brif_of_icmp32 (IntCC.Equal) a b then else)
      (pulley_br_if_xeq32 a b then else))
(rule (lower_brif_of_icmp32 (IntCC.NotEqual) a b then else)
      (pulley_br_if_xneq32 a b then else))
(rule (lower_brif_of_icmp32 (IntCC.SignedLessThan) a b then else)
      (pulley_br_if_xslt32 a b then else))
(rule (lower_brif_of_icmp32 (IntCC.SignedLessThanOrEqual) a b then else)
      (pulley_br_if_xslteq32 a b then else))
(rule (lower_brif_of_icmp32 (IntCC.UnsignedLessThan) a b then else)
      (pulley_br_if_xult32 a b then else))
(rule (lower_brif_of_icmp32 (IntCC.UnsignedLessThanOrEqual) a b then else)
      (pulley_br_if_xulteq32 a b then else))

;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the
;; operation.
(rule (lower_brif_of_icmp32 (IntCC.SignedGreaterThan) a b then else)
      (lower_brif_of_icmp32 (IntCC.SignedLessThan) b a then else))
(rule (lower_brif_of_icmp32 (IntCC.SignedGreaterThanOrEqual) a b then else)
      (lower_brif_of_icmp32 (IntCC.SignedLessThanOrEqual) b a then else))
(rule (lower_brif_of_icmp32 (IntCC.UnsignedGreaterThan) a b then else)
      (lower_brif_of_icmp32 (IntCC.UnsignedLessThan) b a then else))
(rule (lower_brif_of_icmp32 (IntCC.UnsignedGreaterThanOrEqual) a b then else)
      (lower_brif_of_icmp32 (IntCC.UnsignedLessThanOrEqual) b a then else))

;; Branch tables.
(decl lower_br_table (Reg MachLabelSlice) Unit)
(extern constructor lower_br_table lower_br_table)
(rule (lower_branch (br_table index _) targets)
      (lower_br_table index targets))

;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (trap code))
      (side_effect (pulley_trap code)))

;;;; Rules for `get_stack_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (get_stack_pointer))
      (pulley_get_sp))

;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; N.B.: the `ret` itself is generated by the ABI.
(rule (lower (return args))
      (lower_return args))

;;;; Rules for calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (call (func_ref_data sig_ref extname dist) inputs))
      (gen_call sig_ref extname dist inputs))

(rule (lower (call_indirect sig_ref val inputs))
      (gen_call_indirect sig_ref val inputs))

;;;; Rules for `return_call` and `return_call_indirect` ;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (return_call (func_ref_data sig_ref extname dist) args))
      (gen_return_call sig_ref extname dist args))

(rule (lower (return_call_indirect sig_ref callee args))
      (gen_return_call_indirect sig_ref callee args))

;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type ty (iconst (u64_from_imm64 n))))
      (imm ty n))

;;;; Rules for `iadd` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type $I8 (iadd a b)))
      (pulley_xadd32 a b))

(rule (lower (has_type $I16 (iadd a b)))
      (pulley_xadd32 a b))

(rule (lower (has_type $I32 (iadd a b)))
      (pulley_xadd32 a b))

(rule (lower (has_type $I64 (iadd a b)))
      (pulley_xadd64 a b))

;;;; Rules for `icmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule 1 (lower (icmp cc a b @ (value_type $I64)))
      (lower_icmp $I64 cc a b))
(rule (lower (icmp cc a b @ (value_type (fits_in_32 _))))
      (lower_icmp $I32 cc a b))

(decl lower_icmp (Type IntCC Value Value) XReg)

(rule (lower_icmp $I64 (IntCC.Equal) a b)
      (pulley_xeq64 a b))

(rule (lower_icmp $I64 (IntCC.NotEqual) a b)
      (pulley_xneq64 a b))

(rule (lower_icmp $I64 (IntCC.SignedLessThan) a b)
      (pulley_xslt64 a b))

(rule (lower_icmp $I64 (IntCC.SignedLessThanOrEqual) a b)
      (pulley_xslteq64 a b))

(rule (lower_icmp $I64 (IntCC.UnsignedLessThan) a b)
      (pulley_xult64 a b))

(rule (lower_icmp $I64 (IntCC.UnsignedLessThanOrEqual) a b)
      (pulley_xulteq64 a b))

(rule (lower_icmp $I32 (IntCC.Equal) a b)
      (pulley_xeq32 a b))

(rule (lower_icmp $I32 (IntCC.NotEqual) a b)
      (pulley_xneq32 a b))

(rule (lower_icmp $I32 (IntCC.SignedLessThan) a b)
      (pulley_xslt32 a b))

(rule (lower_icmp $I32 (IntCC.SignedLessThanOrEqual) a b)
      (pulley_xslteq32 a b))

(rule (lower_icmp $I32 (IntCC.UnsignedLessThan) a b)
      (pulley_xult32 a b))

(rule (lower_icmp $I32 (IntCC.UnsignedLessThanOrEqual) a b)
      (pulley_xulteq32 a b))

;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the
;; operation.
(rule (lower_icmp ty (IntCC.SignedGreaterThan) a b)
      (lower_icmp ty (IntCC.SignedLessThan) b a))
(rule (lower_icmp ty (IntCC.SignedGreaterThanOrEqual) a b)
      (lower_icmp ty (IntCC.SignedLessThanOrEqual) b a))
(rule (lower_icmp ty (IntCC.UnsignedGreaterThan) a b)
      (lower_icmp ty (IntCC.UnsignedLessThan) b a))
(rule (lower_icmp ty (IntCC.UnsignedGreaterThanOrEqual) a b)
      (lower_icmp ty (IntCC.UnsignedLessThanOrEqual) b a))

;;;; Rules for `load` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (has_type ty (load flags addr (offset32 offset))))
      (pulley_load (Amode.RegOffset addr (i32_as_i64 offset))
                   ty
                   flags
                   (ExtKind.Zero)))

;;;; Rules for `store` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(rule (lower (store flags src @ (value_type ty) addr (offset32 offset)))
      (side_effect (pulley_store (Amode.RegOffset addr (i32_as_i64 offset))
                                 src
                                 ty
                                 flags)))