You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Context — synth's defensive panic from #101 is now catching new wasm_to_ir bugs
After v0.2.1 fixed the silicon-blocking memset miscompile (#97), the defensive panic on unmapped vreg instead of silent R0 fallback (#101) replaced silent miscompiles with explicit panics. Excellent change — it surfaces a class of bugs that would otherwise have produced broken binaries.
We're now hitting those panics on the same merged.wasm from the wasm-cross-LTO silicon-anchor experiment (pulseengine/gale@a4beaeb, branch feat/silicon-smart-data, PR #40, see benches/engine_control/silicon/boards/nucleo_g474re/NOTES-wasm-cross-lto-spike.md for full pipeline context).
What synth v0.3.0 does on the merged wasm
Reproducer (commands from /tmp/wasm-shim-poc, gale-ffi as wasm32 staticlib + a small shim, wasm-ld merged):
# rebuild gale-ffi as wasm32 staticlib (--no-default-features --features sem# reduces the surface but doesn't avoid the panic — see below)
( cd /Volumes/Home/git/pulseengine/gale-smart-data/ffi && \
cargo rustc --release --target wasm32-unknown-unknown \
--crate-type=staticlib --no-default-features --features sem )
# wasm-ld merge with the shim (compiles its host of z_impl_k_sem_give)
clang --target=wasm32-unknown-unknown -O2 -nostdlib \
-c wasm_host_shim.c -o shim.wasm.o
wasm-ld --no-entry --export-all --allow-undefined \
--whole-archive .../libgale_ffi.a --no-whole-archive shim.wasm.o \
-o merged-sem-only.wasm
synth compile merged-sem-only.wasm \
--target cortex-m4f --all-exports --relocatable \
-o merged.o
Observed panics, three different cases
Case 1 — gale-ffi with all features (full surface)
INFO Compiling function 'gale_compute_ipi_mask' via backend 'arm'...
thread 'main' panicked at crates/synth-synthesis/src/optimizer_bridge.rs:1617:21:
synth internal compiler error: vreg v47 has no assigned ARM register and no spill slot.
This is a wasm_to_ir bug — likely a wasm op whose result is unmapped (see issue #93).
Case 2 — gale-ffi with --features sem only (~30% fewer functions)
INFO Compiling function 'gale_sem_validate_v2' via backend 'arm'... ← OK, 80 bytes
INFO Compiling function '_ZN17compiler_builtins5float3div3div17h3f008815e51f3f21E' via backend 'arm'...
thread 'main' panicked at crates/synth-synthesis/src/optimizer_bridge.rs:1617:21:
synth internal compiler error: vreg v721 has no assigned ARM register and no spill slot.
(I haven't isolated Case 3 yet but suspect there are more — the panic catches a class of bugs, not one specific function.)
What this is NOT
This is not the same as #93. #93 was about i64 codegen for memset's loop counter producing non-terminating code. #97 fixed that specific instance. The defensive panic added by #101 catches a broader class of "wasm op whose result is unmapped during ir lowering" — and there are evidently several different wasm-op patterns in compiler_builtins (float div, gale's cpu_mask helper, possibly others) that still trip it.
The message text in the panic references#93 because that's the class label, but each specific function panicking is a separate underlying lowering gap.
Recommended fix path
This connects directly to the existing strategy work in #74 (zero semantic tests verify compiled code) and #76 (validator-based i64/f32/f64 proof coverage). Concrete suggestions:
Triage the panicking functions — collect the list of unique (panic location, wasm op pattern) tuples that the defensive panic from fix(opt): defensive panic on unmapped vreg instead of silent R0 fallback #101 has caught since landing. Each tuple is a distinct wasm_to_ir gap, even though they share an error message.
Per-function regression tests — for each panicking function, capture the wasm bytes that trigger it and add a compiles_without_panic test. Trivial harness, catches future regressions cheaply.
PulseEngine's positioning for safety-critical (ASIL-D / DO-178C) deployment leans on the meld→loom→synth chain being a verified-construction path. For gale silicon-anchor users today this means: rustc-direct compiles cleanly, LLVM-LTO compiles cleanly, but the verified-construction wasm chain panics. The defensive panic is the right behavior compared to silent miscompile, but it's a concrete blocker for "use synth instead of LLVM-LTO on real silicon."
Marking bug because the panicking input is valid wasm produced by rustc with default codegen — synth should compile it or, if it genuinely can't, refuse it with a more actionable diagnostic (e.g. listing the specific wasm opcode whose lowering is unimplemented).
Context — synth's defensive panic from #101 is now catching new wasm_to_ir bugs
After v0.2.1 fixed the silicon-blocking memset miscompile (#97), the
defensive panic on unmapped vreg instead of silent R0 fallback(#101) replaced silent miscompiles with explicit panics. Excellent change — it surfaces a class of bugs that would otherwise have produced broken binaries.We're now hitting those panics on the same
merged.wasmfrom the wasm-cross-LTO silicon-anchor experiment (pulseengine/gale@a4beaeb, branchfeat/silicon-smart-data, PR #40, seebenches/engine_control/silicon/boards/nucleo_g474re/NOTES-wasm-cross-lto-spike.mdfor full pipeline context).What synth v0.3.0 does on the merged wasm
Reproducer (commands from
/tmp/wasm-shim-poc, gale-ffi as wasm32 staticlib + a small shim, wasm-ld merged):Observed panics, three different cases
Case 1 — gale-ffi with all features (full surface)
Case 2 — gale-ffi with
--features semonly (~30% fewer functions)(I haven't isolated Case 3 yet but suspect there are more — the panic catches a class of bugs, not one specific function.)
What this is NOT
This is not the same as #93. #93 was about i64 codegen for memset's loop counter producing non-terminating code. #97 fixed that specific instance. The defensive panic added by #101 catches a broader class of "wasm op whose result is unmapped during ir lowering" — and there are evidently several different wasm-op patterns in compiler_builtins (float div, gale's cpu_mask helper, possibly others) that still trip it.
The message text in the panic references #93 because that's the class label, but each specific function panicking is a separate underlying lowering gap.
Recommended fix path
This connects directly to the existing strategy work in #74 (zero semantic tests verify compiled code) and #76 (validator-based i64/f32/f64 proof coverage). Concrete suggestions:
Triage the panicking functions — collect the list of unique (panic location, wasm op pattern) tuples that the defensive panic from fix(opt): defensive panic on unmapped vreg instead of silent R0 fallback #101 has caught since landing. Each tuple is a distinct wasm_to_ir gap, even though they share an error message.
Per-function regression tests — for each panicking function, capture the wasm bytes that trigger it and add a
compiles_without_panictest. Trivial harness, catches future regressions cheaply.Validator coverage — the Adopt validator-based verification strategy (CompCert pattern) for i64/f32/f64 proof coverage #76 validator pattern would let synth emit a result-vreg-or-spill for every wasm op without needing per-op Rocq proofs, and verify the assignment post-codegen. That closes the underlying class without requiring synth-team to enumerate every wasm op.
Side note — affects safety claim chain
PulseEngine's positioning for safety-critical (ASIL-D / DO-178C) deployment leans on the meld→loom→synth chain being a verified-construction path. For gale silicon-anchor users today this means: rustc-direct compiles cleanly, LLVM-LTO compiles cleanly, but the verified-construction wasm chain panics. The defensive panic is the right behavior compared to silent miscompile, but it's a concrete blocker for "use synth instead of LLVM-LTO on real silicon."
Cross-references
Marking
bugbecause the panicking input is valid wasm produced by rustc with default codegen — synth should compile it or, if it genuinely can't, refuse it with a more actionable diagnostic (e.g. listing the specific wasm opcode whose lowering is unimplemented).