Surfaced by
Dissolving the gust maximal-wasm mini-RTOS kernel (kiln-async scheduler) wasm→loom→synth. 9/10 functions compiled cleanly to ARM (cortex-m4f), including the scheduler hot path gust_poll (840 B). One function skipped:
skipping function 'gust_boot': backend 'arm' failed: compilation failed:
branch-resolve size probe failed: Synthesis failed:
load/store immediate offset > 0xFFF (4095) — materialize the offset into a register
gust_boot initializes a large static Scheduler<6,6,4,2,2> (a few hundred bytes); a field store lands at an offset beyond Thumb's 12-bit immediate load/store range (> 4095), and the arm backend bails instead of materializing the offset into a register (add rN, base, #hi; str rX, [rN, #lo] or a movw/movt into a scratch reg).
Evidence it's backend-specific
The same gust.loom.wasm compiles all 10 functions via synth compile --target riscv32 (rv32 has wider/again-materialized offsets) — so this is purely the ARM backend's immediate-offset handling, not a frontend/IR issue.
Impact
- Blocks dissolving init/boot paths that touch large structs at high offsets. Hot paths are unaffected (they use small offsets).
- Workaround today: keep boot/init in the native TCB shim (fine for gust — boot is one-time). But for "the whole kernel is wasm" the backend should materialize the offset.
Kill-criterion
Fixed when synth compile --target cortex-m4f emits gust_boot (offset materialized into a register) instead of skipping it — i.e. 10/10 functions compiled, matching the rv32 backend.
🤖 Generated with Claude Code
Surfaced by
Dissolving the gust maximal-wasm mini-RTOS kernel (kiln-async scheduler) wasm→loom→synth. 9/10 functions compiled cleanly to ARM (cortex-m4f), including the scheduler hot path
gust_poll(840 B). One function skipped:gust_bootinitializes a large staticScheduler<6,6,4,2,2>(a few hundred bytes); a field store lands at an offset beyond Thumb's 12-bit immediate load/store range (> 4095), and the arm backend bails instead of materializing the offset into a register (add rN, base, #hi; str rX, [rN, #lo]or a movw/movt into a scratch reg).Evidence it's backend-specific
The same
gust.loom.wasmcompiles all 10 functions viasynth compile --target riscv32(rv32 has wider/again-materialized offsets) — so this is purely the ARM backend's immediate-offset handling, not a frontend/IR issue.Impact
Kill-criterion
Fixed when
synth compile --target cortex-m4femitsgust_boot(offset materialized into a register) instead of skipping it — i.e. 10/10 functions compiled, matching the rv32 backend.🤖 Generated with Claude Code