Summary
synth compile --cortex-m --all-exports silently skips two functions of the falcon flight core because synth's component validator reports a wasm value-stack underflow — on a module that wasm-tools validate accepts as fully valid. The skipped functions are absent from the ELF (an on-target completeness gap, distinct from the regalloc skips tracked in #242 and the call_indirect dispatch gap in #275).
Reproduction (deterministic, from public assets)
# falcon-flight-v1.56.wasm — relay release asset, sha256 3fb275db…a41341
loom optimize falcon-flight-v1.56.wasm -o f.loom.wasm # loom v1.1.13
meld fuse f.loom.wasm -o f.fused.wasm # meld v0.30.0 (also repro's on v0.29.0)
wasm-tools validate f.fused.wasm # => VALID
synth compile f.fused.wasm --cortex-m --all-exports -o out.elf
Observed on both synth v0.11.39 and v0.11.40 (so not version-introduced):
warning: skipping function 'func_30': ... Component validation failed:
wasm value-stack underflow at op 21 (LocalSet(2)): would pop 1 from depth 0
warning: skipping function 'func_39': ... Component validation failed:
wasm value-stack underflow at op 2 (Select): would pop 3 from depth 2
Committed artifact for byte-exact repro: repro/synth-underflow/falcon-v1.56.fused.wasm in pulseengine/jess (sha256 bd946fb5…29713).
Analysis
The module is spec-valid (wasm-tools agrees), so this is synth's internal abstract-stack model under-counting, not a malformed input:
func_39, op 2 = Select: a select pops 3 (two operands + i32 condition), but synth's model believes depth is only 2 at op 2 — i.e. the two operands feeding the select aren't both on synth's tracked stack that early. Suggests block/control-flow results (or function params) not seeded onto the abstract stack.
func_30, op 21 = LocalSet(2): pops 1, synth thinks depth 0 — same family of under-count, here after ~20 ops.
Both failures are very early in the function, which points at stack initialization / block-result accounting rather than a deep-nesting edge. Possibly related to the (closed) #72 explicit-value-stack work, but that landed and this still reproduces.
Impact for jess
2 functions of the verified flight core are silently dropped from the Cortex-M ELF. Combined with #275 (dispatch) and the #242 regalloc skips, it's part of the on-target completeness picture jess tracks (recorded as AFD-017). Non-blocking for the wasm/kiln path (whole module present there); blocking for a complete self-contained firmware.
Suggested fix
Seed synth's abstract value stack from the function signature (params) and block/loop result types before instruction walk, and verify the Select lowering accounts for all three pops. A targeted fixture from func_39 (the Select case) would lock it. Happy to extract a minimal reproducer from the committed core if useful.
Summary
synth compile --cortex-m --all-exportssilently skips two functions of the falcon flight core because synth's component validator reports a wasm value-stack underflow — on a module thatwasm-tools validateaccepts as fully valid. The skipped functions are absent from the ELF (an on-target completeness gap, distinct from the regalloc skips tracked in #242 and the call_indirect dispatch gap in #275).Reproduction (deterministic, from public assets)
Observed on both synth v0.11.39 and v0.11.40 (so not version-introduced):
Committed artifact for byte-exact repro:
repro/synth-underflow/falcon-v1.56.fused.wasmin pulseengine/jess (sha256bd946fb5…29713).Analysis
The module is spec-valid (wasm-tools agrees), so this is synth's internal abstract-stack model under-counting, not a malformed input:
func_39, op 2 = Select: aselectpops 3 (two operands + i32 condition), but synth's model believes depth is only 2 at op 2 — i.e. the two operands feeding the select aren't both on synth's tracked stack that early. Suggests block/control-flow results (or function params) not seeded onto the abstract stack.func_30, op 21 = LocalSet(2): pops 1, synth thinks depth 0 — same family of under-count, here after ~20 ops.Both failures are very early in the function, which points at stack initialization / block-result accounting rather than a deep-nesting edge. Possibly related to the (closed) #72 explicit-value-stack work, but that landed and this still reproduces.
Impact for jess
2 functions of the verified flight core are silently dropped from the Cortex-M ELF. Combined with #275 (dispatch) and the #242 regalloc skips, it's part of the on-target completeness picture jess tracks (recorded as AFD-017). Non-blocking for the wasm/kiln path (whole module present there); blocking for a complete self-contained firmware.
Suggested fix
Seed synth's abstract value stack from the function signature (params) and block/loop result types before instruction walk, and verify the Select lowering accounts for all three pops. A targeted fixture from
func_39(the Select case) would lock it. Happy to extract a minimal reproducer from the committed core if useful.