After spending some time on implementing an arm32 backend (primarily cortex-m) out of tree I would like to start the discussion about the conditions of a potential inclusion. I tried to keep the functionality of the initial patch minimal (with the exception of the ABI implementation, I didn't shrink that one back to the minimum, yet).
See https://github.com/bytecodealliance/wasmtime/pull/13815 for details, for now only three instructions and one filetest is added and passes.
Furthermore I would like to get ideas for a more realistic testing environment as runtime filetests are only executed on the host architecture - and setting up an arm32 host feels unrealistic. Are there any runtime tests which work with pulley32?
Update: I was able to get rustc_cg_cranelift working with my extended* backend. It creates mostly correct machine code - with the exception of the mixing of push and pop order (preamble). Also r12 is scratch (no need to save it) and the constant is unnecessarily wide (32 bits while 6 would be enough).
To me this is mostly encouraging (for a first output) ...
#![no_std]
#[unsafe(no_mangle)]
pub fn add(left: u32, right: u32) -> u32 {
42 + left + right
}
00000000 <add>:
0: e92d 4800 push.w {r11, lr}
4: e92d 1000 stmdb sp!, {r12}
8: f240 0c2a movw r12, #0x2a
c: f2c0 0c00 movt r12, #0x0
10: eb10 0c0c adds.w r12, r0, r12
14: eb1c 0001 adds.w r0, r12, r1
18: e8bd 9000 pop.w {r12, pc}
1c: e8bd 4800 pop.w {r11, lr}
*) Most necessary instructions are not part of above's initial pull request.
Would you be able to join this week's meeting? It might be best to go over some bits synchronously to start out with and then go from there async?
That will be possible, see you then.
I'd also be interested in joining as I'm messing around with codegen backends for SSA-shaped IRs, that may or may not be upstreamed eventually
Please do! The doc I think has instructions of how to join.
For myself personally, some thoughts/questions I'd have about adding an arm32 backend, and no need to answer them all here we can discuss them during the meeting:
ValueRegs only has 2 slots, not the 4 that'd be needed.Alex Crichton said:
- This'd be the first genuine 32-bit backend (pulley32 kind of doesn't count), so I suspect there's going to be some significant complexities due to that. For example all 64-bit integer operations are going to be more complicated than they are on all other platforms. Additionally I'm not sure how 128-bit integers are going to be supported as right now
ValueRegsonly has 2 slots, not the 4 that'd be needed.
To be honest I think that 128-bit integers don't need to work (seamlessly) on a 32-bit platform with typically far less than 16MB of memory (some come with <=8kB). But nevertheless I think 128 could be made to work if necessary, but even official aarch64 compilers don't support it and I don't think there is an ABI (like written in the AAPCS document) standard for it (likely for arm32 it should either live in register quads like R0..R3, R4..R7, R8..R11 or at an 16 byte (8 byte would be ok, but feels incompatible to other archictures) aligned memory location). In theory you could support passing (int64_t, int128_t) as the lower half in R2+R3 and the upper half on stack, but this feels more like compiler madness.
I have another patch ready which increases VALUE_REGS_PARTS to four. But I didn't want to impose that on the world unless someone needs it.
Alex Crichton said:
- Testing-wise we'd expect everything to go through qemu userspace emulation. I thought we already did that for the fiber crate but looks like no, we don't actually do that just yet. Shouldn't be too too hard to do so, though.
I fear about wiring the user space to the test harness, I guess the component model ABI or WAVE or component model value definition encoding come as a natural way - with Linux stdin and stdout hardwired in some assembly (or pre-compiled by llvm) form. Let's talk about this on Wednesday.
Christof Petig said:
To be honest I think that 128-bit integers don't need to work (seamlessly) on a 32-bit platform ...
I have another patch ready which increases VALUE_REGS_PARTS to four...
Part of this touches on goals a bit -- wide-arithmetic requires i128 to be supported a little bit in the backends right now, but if your goal is a lime1 and/or MVP-compatible implementation then i128 should be fine to omit.
For VALUE_REGS_PARTS, I'd mostly be worried about the perf impact of inreasing the 2 to 4
Alex Crichton said:
- To confirm: what's the goal here? For example is it to get a wasm-MVP compatible backend? lime1? Wasm-complete? Cg_cilf complete? (for examples of the spectrum of completeness that you may want to shoot for)
Basically enabling wasmtime/no_std (AoT ?) running on Zephyr/Cortex-M4F is my goal. But I hope that additional people have additional needs and would contribute code once the troublesome initial framework is in place. Cg_clif is more of a cool testing tool for me, but I would love to see an all Rust compiler for thumb2 (perhaps as a wasm binary in the browser?).
Alex Crichton said:
- I'm at least myself pretty naive about arm32 as a platform, so the rest of this question may be obvious/naive for those familiar with the platform. I know there's things like armv6, armv7, armvNN, thumb, thumb2 (?), and various revisions/ABIs that are out there for 32-bit arm. Basically my impression is that it's a pretty fractured target unlike aarch64 where my impression is that there's one broad baseline. Does this target have a particular baseline it's targetting? For example are some things explicitly in-scope vs some things explicitly out-of-scope? As someone pretty unfamiliar with arm32 this may be a nonsensical question, I'm not sure.
The question is spot on, I always refer to the nice Wikipedia table on this. Having both Cortex-M0+ and M7F support should be good enough for 99% of users (if you keep the variations in separate flags you can support everything in between as well). I personally don't want to spend time on supporting ARM7 to ARMv7-A (or v8 AArch32) - but other people involved with older Android systems might find this valuable still. (There is a good reason why the first triplet is different, although these CPUs support both of armv7a-none-eabihf vs thumbv7em-none-eabihf, the instruction encoding is totally different, the assembly got unified).
Thumb2 and ARM32 should be able to share 80% of cranelift infrastructure, but optimizing ARM32 for speed is out of scope for me.
(I'm still on PTO this week and traveling-for-work next week, so this is my ghost appearing briefly)
I have lots of thoughts on this topic as well; @Christof Petig you may be aware we previously had half of an arm32 (not thumb) backend that we deleted because the original contributor disappeared and never finished the work, it was not usable for any real use-case, and was becoming a maintenance burden. Because of that experience, in later backend contributions (specifically riscv64) I set a pretty high bar for completeness: I wanted to see Wasm working before committing to accepting the backend. If a contributor is around and committed to continuing, that doesn't necessarily mean we need one atomic mega-PR; but it does mean that we should reach that goal on a reasonable timeline (and have a plan to do so).
The other usual thing that we say to folks wanting to contribute a new backend is: the expectation is that the maintainer will stick around and attend Cranelift meetings on an ongoing basis, especially as the backend is "ramping up" with real users starting to use it. There are sometimes random things that come up that an active maintainer is needed for, e.g. the recent qemu s390x stuff, or questions that require ABI expertise, or ... I don't expect that'll be an issue as you're already a regular member of the community -- just noting this from the perspective of Cranelift, it's an ongoing commitment of sorts.
Bumping the number of slots in ValueRegs is reasonable and it used to be 4 (due to the above) -- I don't recall a significant perf cost when we switched either way. We should of course measure...
Another historical note to add (one of the first design decisions from the new backends in 2020 actually!): one may be tempted to do mid-end legalizations for 64-to-32-bit to avoid open-coding all of the 64-bit forms of instructions (and even moreso, 128-bit forms); that requires instructions that have carry-in/out which makes isel+regalloc very hard so we've removed those over time. So instead I'd expect that we have these open-coded sequences, which is tedious but manageable. Pulley32 doesn't deal with this fwiw because its registers and operators are still 64-bit for arithmetic.
(Logistical: I'll see if I can join the Cranelift meeting this week to discuss more but no guarantees)
Chris Fallin said:
I set a pretty high bar for completeness: I wanted to see Wasm working before committing to accepting the backend.
Thank you for this clarification of expectations. I think that this bar should be possible to achieve before actually merging the first patch.
To explain a bit further, that was the bar for a random new contributor, to avoid the repeat of "dump half the patch then disappear" -- a regular such as yourself could also do it in smaller patches as long as there were a commitment to finish the work :-) The main concern is that we don't grow a partial backend that isn't useful for "real things" (run Wasmtime tests is a good proxy for that) but costs us maintenance cycles
To be honest, and given that I use AI to help me code it, I prefer to have a minimal working test before committing to maintain the backend. And I should be cautious as I already have plenty of projects I would like to spend more time on than I have available.
But with cg_clif and hopefully a wasm test runner soon I am confident enough that the backend is useful. Checking Assembly code by hand is possible but error prone.
someone else just opened a PR for an arm32 backend as well: https://github.com/bytecodealliance/wasmtime/pull/13854
Hi, I am the person who opened the PR.
Sorry I did not see that there is opened PR for Arm32.
Cool, this one is more complete and orthogonal to my PR in that it implements the arm32 instruction encoding (old + cortex-R+A) while mine implements thumb2 (cortex-M). So it would make sense to combine the patch sets. I am currently implementing a testing harness for the wast tests using qemu, so this could automatically test both implementations.
I guess now the same questions about willingness to maintain for an extended period of time come up... What is your position? (I would be happy to pass the subtree responsibility to someone else and still contribute and maintain thumb2 and qemu testing after arm32 got merged :grinning_face_with_smiling_eyes:)
I refer to these questions: https://bytecodealliance.zulipchat.com/#narrow/channel/217117-cranelift/topic/Arm32.20backend.20.28for.20now.20thumb-2.20only.29.20started/near/608503349
@Obei Sideg we're going to discuss the new arm32 backends at our next Cranelift meeting, next Wednesday (Jul 22): https://github.com/bytecodealliance/meetings/blob/main/cranelift/2026/cranelift-07-22.md
It'd be great if you could join to discuss the above and how we might be able to merge efforts! (FWIW as mentioned above we'd expect a newly contributed backend to be actively maintained, and for that active maintainer to attend the meeting on a semi-regular basis and be reachable otherwise -- let us know if that will be an issue)
I'll be attending the meetings and am happy to take on maintenance. See you on 22 July.
Could someone please send me the meeting invitation?
my email: obei.sideg@gmail.com
cc @fitzgen (he/him) who manages the calendar invite
My qemu test is working with Obei's branch, but I need to clean it up a bit more and f32 tests don't work right now. Either the parsing or passing is wrong at the moment, see https://github.com/cpetig/wasmtime-adapter/tree/obeis_qemu for the draft.
See you tomorrow in the call.
Obei Sideg said:
Could someone please send me the meeting invitation?
my email:obei.sideg@gmail.com
sent!
Last updated: Jul 29 2026 at 05:03 UTC