Summary
select_with_stack's Call lowering emits BL + push(R0) but does not move the call's stack arguments into r0–r3 per AAPCS. So a call with arguments invokes the callee with whatever happens to be in r0–r3 — the callee reads garbage. This is gale's "lock addr 0x400 is in r5, not passed in r0" observation; it blocks z_impl_k_sem_give (which calls k_spin_lock(lock)), even after #188 fixed caller-saved preservation.
Reproducer (synth v0.11.8-pre, after the #188 preservation fix)
(module
(memory 1)
(func $use (param i32) (result i32) local.get 0)
(func $g (export "g") (param i32) (result i32)
(drop (call $use (i32.const 42))) ;; 42 should be passed in r0
(i32.load (local.get 0))))
Compiled --target cortex-m4f --all-exports --relocatable, function g (#188 preservation now present):
c: str.w r1, [sp]
10: str.w r0, [sp, #4] ; param0 preserved (good, #188)
14: bl use ; <-- NO `mov r0, #42` before this — arg not passed
18: mov r4, r0
...
The constant 42 (the call argument) is never loaded into r0.
What to fix
At Call/CallIndirect lowering: the top N operand-stack values are the call's N arguments and must be moved into r0..r(N-1) (AAPCS; >4 args spill to the stack) before the BL, AFTER caller-saved preservation. This requires the callee's argument count (and ideally types for i64/f64 pair/stack handling), which the selector does not currently have — it only knows num_imports. Func signatures must be plumbed from the frontend through the Backend trait into the selector.
Done when
Split from #188 (preservation, fixed in v0.11.8). This is the remaining gale blocker for hot-path kernel primitives.
Summary
select_with_stack'sCalllowering emitsBL+push(R0)but does not move the call's stack arguments into r0–r3 per AAPCS. So a call with arguments invokes the callee with whatever happens to be in r0–r3 — the callee reads garbage. This is gale's "lock addr 0x400 is in r5, not passed in r0" observation; it blocksz_impl_k_sem_give(which callsk_spin_lock(lock)), even after #188 fixed caller-saved preservation.Reproducer (synth v0.11.8-pre, after the #188 preservation fix)
Compiled
--target cortex-m4f --all-exports --relocatable, functiong(#188 preservation now present):The constant 42 (the call argument) is never loaded into r0.
What to fix
At
Call/CallIndirectlowering: the top N operand-stack values are the call's N arguments and must be moved into r0..r(N-1) (AAPCS; >4 args spill to the stack) before theBL, AFTER caller-saved preservation. This requires the callee's argument count (and ideally types for i64/f64 pair/stack handling), which the selector does not currently have — it only knowsnum_imports. Func signatures must be plumbed from the frontend through theBackendtrait into the selector.Done when
(call $use (i32.const 42))emitsmov r0, #42before thebl).>4args spill to the stack per AAPCS.z_impl_k_sem_give-style pattern (value live across a call WITH args) is correct end-to-end.Split from #188 (preservation, fixed in v0.11.8). This is the remaining gale blocker for hot-path kernel primitives.