Skip to content

cranelift: add arm32 backend - #13854

Open
obeis wants to merge 18 commits into
bytecodealliance:mainfrom
obeis:arm32-isa
Open

cranelift: add arm32 backend#13854
obeis wants to merge 18 commits into
bytecodealliance:mainfrom
obeis:arm32-isa

Conversation

@obeis

@obeis obeis commented Jul 9, 2026

Copy link
Copy Markdown

some features aren't implemented yet.

I added file tests for my code.

obeis added 12 commits July 9, 2026 16:13
First step towards a 32-bit ARM backend. This wires arm32 into the meta
build, the isa::lookup path, and the codegen crate, and adds just enough
of the MachInst/ABIMachineSpec plumbing to compile and emit a trivial
function.

An iconst.i32 followed by a return now lowers to real A32 (movw + bx lr)
and is covered by filetests/isa/arm32/iconst.clif. Everything off that
path is still a stub.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Enough of the common instructions to lower straight-line integer code:
mov/movw/movt/mvn, ldr/str and the sub-word and push/pop forms,
add/sub/rsb in register and rotated-immediate forms, cmp/cmn, and the
branch family (b, bl, bx, and conditional b<cond>). Each comes with its
A32 encoding, operand handling, and pretty-printing.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Rounds out the data-processing group: the logical ops (and/orr/eor/bic
and register mvn), the shifts and rotates in both immediate and register
forms, mul/mla/umull/smull, the flag-setting arithmetic (adds/subs/adcs/
sbcs, plus the adc/sbc opcodes), and the tst/teq tests.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
The remaining core integer operations: clz; sdiv/udiv behind a new
has_idiv ISA setting; the sxtb/sxth/uxtb/uxth extends; rev/rev16/rbit;
the mls/smlal/umlal fused multiplies; and a conditional-select pseudo
built from a mov plus a mov<cond>.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Adds encoders, operand handling, printing, and unit tests for the
scalar-integer instructions the backend was still missing: the bitfield
ops (bfc/bfi/sbfx/ubfx), the saturating arithmetic, sel/pkh/revsh/rrx/
udf, the full parallel add/sub family, the 16-bit and accumulating
extends, the DSP multiplies, ldm/stm, the exclusive and acquire/release
memory accesses, and the barriers.

Most of these have no CLIF opcode that maps to them yet; they are here so
the encoder is complete and the tests pin the bit patterns down.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
A direct call to a near/colocated callee becomes a bl with an Arm32Call
relocation; call_indirect becomes a blx through a register. The call and
indirect-call instructions record the safepoint and stack map, pop the
callee's stack arguments, and load any stack-returned values.

Both forms are treated as calls by call_type/is_safepoint so the frame is
set up and lr is preserved around them -- getting that wrong for the
indirect case corrupts the return address. Far calls, return_call, and
try_call are left for later.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
An i64 lives in a (lo, hi) pair of 32-bit registers. rc_for_type returns
two Int registers for I64, and the ABI passes 64-bit arguments in
even-aligned pairs (r0:r1 / r2:r3) per AAPCS, spilling to the 8-aligned
stack when they run out.

Lowers iconst, add/sub via the adds/adc and subs/sbc carry chains, the
bitwise ops per half, iconcat/isplit, the extends and reduce between i32
and i64, and 64-bit load/store as two word accesses. The i64 rules take
an explicit priority so ISLE doesn't have to prove them disjoint from the
fits_in_32 rules.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
imul.i64 expands to umull plus two mla for the low 64 bits of the
product. Constant-amount ishl/ushr/sshr use a funnel sequence: for
shifts below 32 an orr of two 32-bit shifts, and for shifts of 32 or
more a single shift with a zero or sign fill. Variable-amount i64 shifts
are still unimplemented.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
icmp on i64 operands, both as a value and fused into brif. eq/ne reduce
the halves with eor/eor/orrs; the ordering comparisons subtract the pair
with subs/sbcs and test a Z-independent condition, swapping operands for
the gt/le/hi/ls cases.

Also adds a standalone 32-bit icmp-to-bool lowering, which until now only
existed fused into brif or select. Note that icmp's controlling type is
its result type, so the rules match the operand width with value_type.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Introduces f32/f64 on the VFP unit. regalloc2 can't model the S/D
sub-register aliasing, so the float class is the D registers and an f32
lives in the low single half of its D register -- every value owns a
whole D register, which also keeps the encodings uniform (F32 vs F64 is
just the size bit).

D0-D7 are caller-saved, D8-D15 callee-saved; moves and spills are
class-aware (vmov.f64, vldr/vstr). The ABI is a simplified hard-float
(args in D0-D7, return in D0). Lowers the arithmetic, negate/abs/sqrt,
loads and stores, and the const materialization through GPRs.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
fcmp emits vcmp followed by vmrs to get the flags into APSR, then tests
the mapped condition. fpromote/fdemote and the int<->float conversions
go through vcvt (only the saturating float-to-int, matching VCVT's
semantics). Bitcasts between float and integer of the same width use
vmov.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
fmin/fmax reuse the trick of picking vminnm/vmaxnm when the inputs are
ordered and x+y (the propagated NaN) when they aren't, which needs
ARMv8. copysign is done with GPR bit twiddling on the sign bit. A
scalar-float select becomes a cmp plus a conditional vmov.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
@obeis
obeis requested review from a team as code owners July 9, 2026 16:56
@obeis
obeis requested review from alexcrichton and removed request for a team July 9, 2026 16:56
obeis added 4 commits July 9, 2026 20:08
Emits a bounds check against the default target, then an
add pc, pc, index, lsl into an inline table of branches. Branch26
range covers the table so no islands are needed. br_table and the call
sequences are exempt from the per-instruction worst-case-size check.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
atomic_rmw and atomic_cas lower to ldaex/.../stlex retry loops emitted as
single pseudo-instructions, since the register allocator can't be allowed
to split the exclusive sequence. The rmw pseudo covers all of the
operations; cas branches out on a mismatch. atomic_load/store use
lda/stl, which give seq_cst ordering on ARMv8. Only i32 for now.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Direct calls to a non-colocated callee had no lowering. A new
LoadExtName pseudo materializes a symbol's absolute address inline
(ldr rd, [pc]; b .+8; .word <sym>) with an Abs4 relocation, and a far
call loads the target that way and calls it indirectly. The same helper
also lowers func_addr and symbol_value.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Threads an access size through the exclusive instructions so they encode
the byte and halfword forms. Sub-word rmw needs no operand extension for
the plain ops (the store truncates), but min/max and cas extend their
inputs before comparing.

64-bit is trickier: ldrexd/strexd need consecutive even/odd register
pairs, which regalloc2 can't express, so the paired atomics pin every
operand to a fixed register the way aarch64 does. rmw uses the
adds/adc/subs/sbc carry chains, with min/max selecting both halves on a
Z-independent condition.

Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
@alexcrichton

Copy link
Copy Markdown
Member

Before going too too much further on this, have you seen this discussion on Zulip and/or #13815?

@obeis

obeis commented Jul 9, 2026

Copy link
Copy Markdown
Author

I did not see them.

Comment thread cranelift/codegen/src/isa/arm32/inst/emit.rs Outdated
obeis added 2 commits July 9, 2026 20:51
Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
Signed-off-by: Obei Sideg <obei.sideg@gmail.com>
@github-actions github-actions Bot added cranelift Issues related to the Cranelift code generator cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:meta Everything related to the meta-language. labels Jul 9, 2026
@github-actions github-actions Bot added the isle Related to the ISLE domain-specific language label Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Subscribe to Label Action

cc @cfallin, @fitzgen

Details This issue or pull request has been labeled: "cranelift", "cranelift:area:machinst", "cranelift:meta", "isle"

Thus the following users have been cc'd because of the following labels:

  • cfallin: isle
  • fitzgen: isle

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@alexcrichton

Copy link
Copy Markdown
Member

Apologies @obeis I forgot this was assigned to me after this week's Cranelift meeting. For review of this I'm going to mostly defer to @cfallin and @fitzgen who are the primary maintainers of Cranelift's backends and probably have more insight into various pieces here than I do.

One thing I can provide some review on though is the CI infrastructure. Currently this doesn't add anything new which means that the filetests are executed but there aren't, for example, any runtests nor QEMU emulation. This means that we're never actually executing any of the generated code here which is a gap we'll either want to close in this PR or very shortly thereafter. Would you be interested in integrating the QEMU/execution side into this PR as well? For example enabling any runtests that this PR enables for arm32? I believe @cpetig's work could be a good starting point here.

@alexcrichton
alexcrichton requested review from cfallin and fitzgen and removed request for alexcrichton July 24, 2026 16:34
@obeis

obeis commented Jul 26, 2026

Copy link
Copy Markdown
Author

No problem, I will add the QEMU execution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cranelift:area:machinst Issues related to instruction selection and the new MachInst backend. cranelift:meta Everything related to the meta-language. cranelift Issues related to the Cranelift code generator isle Related to the ISLE domain-specific language

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants