synth compile --cortex-m panics (exit 101) on a multi-value if — a block type that takes
parameters. The same construct is detected and cleanly declined on aarch64 and rv32, so the guard
exists in the codebase; the ARM selector just lacks it.
The input is params from if.wast in the official spec suite — which v0.60.0 now vendors as
tests/spec-testsuite, so it is already in the tree.
Verified on v0.60.0 (4e7a179).
Minimal repro
(module
(func (export "params") (param i32) (result i32)
(i32.const 1)
(i32.const 2)
(if (param i32 i32) (result i32) (local.get 0)
(then (i32.add))
(else (i32.sub)))))
Valid module; wasmtime gives params(1) = 3.
$ synth compile mv.wat --cortex-m --all-exports -o /tmp/m.o
thread 'main' panicked at crates/synth-synthesis/src/instruction_selector/select_with_stack.rs:3674:65:
`at` split index (is 2) should be <= len (is 1)
$ echo $?
101
Two values are pushed before the if, and the if (param i32 i32) consumes them as block
parameters. The selector tries to split 2 values off a stack it believes holds 1, so the block
parameters are not being accounted for when the block is entered.
The other two backends already handle it
| backend |
exit |
behaviour |
--cortex-m |
101 |
panic |
-b aarch64 |
1 |
clean decline |
-b riscv -t rv32imac |
1 |
clean decline |
aarch64 even names the exact condition:
aarch64 selector: if #0 has type (2, 1) — a PARAMETER-taking block type (multi-value)
is not lowered on aarch64
So this is not a missing capability question — it is one backend reaching an unhandled state
through split_off instead of the (params, results) arity check the other two perform.
--no-optimize does not avoid it
tests/spec/run_supported.sh documents the workaround:
--no-optimize # Bypass optimizer (avoids regalloc panics)
...
echo "Compile PANIC: $COMPILE_PANIC (optimizer regalloc — all pass with --no-optimize)"
That does not hold for this file:
$ synth compile if.wast --cortex-m --all-exports --no-optimize -o /tmp/if2.elf ; echo $?
101 # still panics
So the runner's summary line would under-report: a reader is told the panics are an optimizer
artifact that --no-optimize clears, when at least this one survives it and is in instruction
selection rather than regalloc. Worth correcting the message even independently of the fix.
Scope
Scanning all 257 spec-suite files on v0.60.0:
--cortex-m, optimizer on: 1 panic (if.wast) out of 257
-b aarch64, optimizer on: 0 panics out of 257
So the ARM backend is otherwise solid across the suite; this is one unhandled construct.
Suggested fix
Give the ARM selector the same arity check aarch64 performs at block entry — if the block type has
a non-zero parameter count that the path cannot lower, decline with a message naming the type
(params, results) rather than reaching the split_off. A bounds-checked split (split_off only
when len >= at, else an error) would also convert the whole class from panic to diagnostic.
Related
Same shape as #1013 but with the backends reversed — there aarch64 panicked while arm and riscv
exited cleanly. A sweep for split_off / direct indexing on the value stack across all three
selectors would likely find siblings of both.
synth compile --cortex-mpanics (exit 101) on a multi-valueif— a block type that takesparameters. The same construct is detected and cleanly declined on aarch64 and rv32, so the guard
exists in the codebase; the ARM selector just lacks it.
The input is
paramsfromif.wastin the official spec suite — which v0.60.0 now vendors astests/spec-testsuite, so it is already in the tree.Verified on v0.60.0 (4e7a179).
Minimal repro
Valid module; wasmtime gives
params(1) = 3.Two values are pushed before the
if, and theif (param i32 i32)consumes them as blockparameters. The selector tries to split 2 values off a stack it believes holds 1, so the block
parameters are not being accounted for when the block is entered.
The other two backends already handle it
--cortex-m-b aarch64-b riscv -t rv32imacaarch64 even names the exact condition:
So this is not a missing capability question — it is one backend reaching an unhandled state
through
split_offinstead of the(params, results)arity check the other two perform.--no-optimizedoes not avoid ittests/spec/run_supported.shdocuments the workaround:That does not hold for this file:
So the runner's summary line would under-report: a reader is told the panics are an optimizer
artifact that
--no-optimizeclears, when at least this one survives it and is in instructionselection rather than regalloc. Worth correcting the message even independently of the fix.
Scope
Scanning all 257 spec-suite files on v0.60.0:
--cortex-m, optimizer on: 1 panic (if.wast) out of 257-b aarch64, optimizer on: 0 panics out of 257So the ARM backend is otherwise solid across the suite; this is one unhandled construct.
Suggested fix
Give the ARM selector the same arity check aarch64 performs at block entry — if the block type has
a non-zero parameter count that the path cannot lower, decline with a message naming the type
(params, results)rather than reaching thesplit_off. A bounds-checked split (split_offonlywhen
len >= at, else an error) would also convert the whole class from panic to diagnostic.Related
Same shape as #1013 but with the backends reversed — there aarch64 panicked while arm and riscv
exited cleanly. A sweep for
split_off/ direct indexing on the value stack across all threeselectors would likely find siblings of both.