Skip to content

fix(opt): defensive panic on unmapped vreg instead of silent R0 fallback#101

Merged
avrabe merged 1 commit into
mainfrom
fix/defensive-vreg-fallback
May 14, 2026
Merged

fix(opt): defensive panic on unmapped vreg instead of silent R0 fallback#101
avrabe merged 1 commit into
mainfrom
fix/defensive-vreg-fallback

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 11, 2026

Follow-up to PR #97 (which fixed the silicon-blocking #93 memset bug).

The root cause of #93 was that optimizer_bridge::wasm_to_ir silently dropped three wasm ops (I64ExtendI32U/S, I32WrapI64). The downstream lookup helper get_arm_reg returned Reg::R0 as a silent fallback when a vreg had no assignment — so subsequent i64 shifts read R0 as their rm_lo/rm_hi, destroying memset's destination pointer.

This PR replaces the silent fallback with a diagnostic panic naming the offending vreg. Any future "wasm op silently dropped" bugs of this class will surface as a compiler crash with a useful error message, instead of producing miscompiled firmware that boots-and-loops on real silicon.

A compiler crash is strictly better than a hung MCU.

Test plan

🤖 Generated with Claude Code

avrabe added a commit that referenced this pull request May 11, 2026
Unblocks every open PR (#96, #97, #99, #100, #101) that was failing on `No space left on device` during z3-sys's C++ build on smithy runners.
@avrabe avrabe force-pushed the fix/defensive-vreg-fallback branch from 3530719 to 37b9787 Compare May 11, 2026 05:30
@avrabe avrabe closed this May 11, 2026
@avrabe avrabe reopened this May 11, 2026
@avrabe avrabe force-pushed the fix/defensive-vreg-fallback branch from 37b9787 to 592fd27 Compare May 11, 2026 18:34
@avrabe avrabe force-pushed the fix/defensive-vreg-fallback branch from 592fd27 to d752201 Compare May 12, 2026 04:28
avrabe added a commit that referenced this pull request May 13, 2026
#101

The systematic AAPCS-clobber audit (47 sites + 27 tests) is shippable
on its own. The defensive panic in get_arm_reg fires on at least one
remaining wasm_to_ir gap (vreg v13 during simple_add.wat fib compile,
seen on Bazel CI for genrules test_add_elf / test_add_m7_elf /
test_add_riscv_elf). That panic belongs in #101 once the remaining
gap is closed.

Cargo workspace tests + clippy + fmt clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
avrabe added a commit that referenced this pull request May 13, 2026
… usages (#108)

Sweep of 47 hardcoded R0..R3 sites across the optimizer + selector. Closes the recurring class that PR #86 (i64 const), #97 (i64 extend/wrap), #106 (24 i64 ops), and #107 (CSE MemLoad/Store) each addressed one slice of.

Categories audited:
* wasm_to_ir slot accounting for i64 arith/extend ops (15 + 3 ops)
* wasm_to_ir op-handler gaps (10 wasm ops → 6 new Opcode variants)
* CSE pass: missing src-vreg resolution for all i64 opcodes + alias invalidation on re-def
* ir_to_arm hardcoded `Reg::R0` / `Reg::R3` destinations (24 handlers fixed via `alloc_i32_scratch`)
* select_with_stack i64 sub-word loads hardcoding `R0:R1` dest pair

27 regression tests added across 4 new test files. Defensive panic stays in PR #101 (one remaining v13 vreg case during simple_add.wat fib compilation is being tracked down — silent R0 fallback preserved in this PR).
@avrabe avrabe force-pushed the fix/defensive-vreg-fallback branch from d752201 to 5a2c798 Compare May 13, 2026 19:06
@avrabe avrabe changed the base branch from main to fix/wasm-to-ir-call-result-vreg May 13, 2026 19:06
@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 0% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/synth-synthesis/src/optimizer_bridge.rs 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

avrabe added a commit that referenced this pull request May 14, 2026
Closes the last latent unmapped-vreg gap surfaced by the systematic AAPCS audit (PR #108). `WasmOp::Call` had no wasm_to_ir handler, fell through to `Opcode::Nop`. The call's result vreg was never mapped, and any downstream consumer (`i32.add(call_result, ...)`) resolved its operand via `get_arm_reg`'s silent R0 fallback — miscompiling on every fib-style recursive WAT.

Fix: new `Opcode::Call { dest, func_idx }` in synth-opt, mapped in wasm_to_ir, lowered to `BL func_<idx>` with `dest → R0` in ir_to_arm.

Narrow scope (does not yet model R0..R3 invalidation across BL — broader call-boundary regalloc rework deferred).

+2 regression tests. Unblocks #101 (defensive panic ships next).
Base automatically changed from fix/wasm-to-ir-call-result-vreg to main May 14, 2026 04:50
Follow-up to issue #93 (silicon-blocking memset bug). The root cause was
optimizer_bridge::wasm_to_ir silently dropping three wasm ops
(I64ExtendI32U/S, I32WrapI64) — they produced vregs that never got mapped
to ARM registers. The downstream lookup in get_arm_reg returned Reg::R0
as a silent fallback, so subsequent i64 shifts read R0 as rm_lo/rm_hi,
destroying memset's destination pointer on real silicon.

Replace the silent fallback with a panic that names the vreg. Future
"wasm op silently dropped" bugs of this class will surface at the
boundary instead of producing miscompiled firmware. A compiler crash is
strictly better than a hung MCU.

Verified:
* cargo test --workspace — all pass (no path legitimately hits the
  fallback — the post-#97 codebase produces mappings for every wasm op
  it emits IR for)
* cargo clippy --workspace --all-targets -- -D warnings — clean
* cargo fmt --check — clean

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe avrabe force-pushed the fix/defensive-vreg-fallback branch from 5a2c798 to 534735a Compare May 14, 2026 04:55
@avrabe avrabe merged commit b4c8780 into main May 14, 2026
6 of 7 checks passed
@avrabe avrabe deleted the fix/defensive-vreg-fallback branch May 14, 2026 05:29
avrabe added a commit that referenced this pull request May 14, 2026
Two harnesses (i64_lowering_doesnt_clobber_params, encoder_no_panic)
keep finding new AAPCS-class bugs at a rate faster than we close them
in a single release cycle. Mark them as non-gating (continue-on-error)
so the harness infrastructure can ship as part of #100 while the
bug-hunting continues in v0.3.x patches.

Promotion criteria for moving a harness from exploration → gating: 60s
smoke runs report zero findings on main for 2 consecutive weeks.

Open bugs tracked: #103 (fixed via #106), #104 (fixed via #107), the
class-wide sweep #108, the WasmOp::Call gap #109/#101, the I32WrapI64
preassign #111, and the new #112 (i64-extend chain + Movw R0).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant