fix(opt): ir_to_arm returns Result — panic-free optimized path, fuzz re-gated#132
Merged
Conversation
`ir_to_arm`'s `get_arm_reg` closure panicked ("synth internal compiler
error: vreg vN has no assigned ARM register...") when an IR vreg had no
mapping and no spill slot. PR #101 introduced that panic — correct then
(a loud crash beats a silent R0-fallback miscompilation), but it was the
last remaining panic site in the optimized lowering path.
Convert the `panic!` into `Err(Error::synthesis(...))` carrying the same
issue-#93 diagnostic, and change `ir_to_arm`'s signature from
`Vec<ArmOp>` to `Result<Vec<ArmOp>>`. All 166 `get_arm_reg` call sites
propagate via `?`. The defensive check is preserved — a genuine
`wasm_to_ir` bug still surfaces as a rich typed error, it just no longer
kills the process.
Callers updated: `arm_backend.rs` folds the `ir_to_arm` step into the
existing `optimize_full` fallback so an `Err` falls back to the direct
selector (honest degradation, same as the issue-#120 float path); the
`wasm_ops_lower_or_error` fuzz harness skips on `Err`. New regression
test `regression_ir_to_arm_panic_free` confirms a hand-built IR with an
unmapped src vreg now yields `Err` (not a panic) and that the error
keeps its issue-#93 diagnostic content.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The harness was demoted to `gating: false` in PR #117 pending the issue-#121 slot_stack refactor. That refactor landed, and the last panic site in the optimized path — `ir_to_arm`'s defensive `get_arm_reg` — now returns `Result` instead of `panic!`-ing. The whole `optimize_full` + `ir_to_arm` path is panic-free, so the harness (contract: "lower or Err, never panic") gates again. Update the matrix comment accordingly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Sibling fix to the panic-free `ir_to_arm` work in this PR: the `pop_i32_unary!` macro inside `wasm_to_ir` still used `.expect(...)`, which the earlier slot_stack Result conversion missed because the `.expect(...)` ended with `,` (the macro pattern) rather than `;` (the statement pattern the original sed targeted). The re-gated `wasm_ops_lower_or_error` fuzz harness — re-promoted to gating in this PR — found a malformed input that slips past the pre-flight check and reaches an i32 unary op via `pop_i32_unary!`, triggering the leftover `.expect()` panic. Converted to `.ok_or_else(...)?` matching `pop_i32_binary!`'s shape so the function-level `Result` propagates instead of panicking. This is exactly the bug class re-gating the harness exists to catch — the gating fuzz did its job here.
The catch-all comment still described downstream consumers failing 'loudly via slot_stack.pop().expect(...)'. After the Result conversion and the pop_i32_unary! macro fix in this PR, no .expect() remains; unknown-op back-references now surface as a typed Err via .ok_or_else(...)?. Same bug-finder semantics, different failure mode. The comment now matches the code.
Contributor
Author
|
Two follow-ups pushed: b47eaae fixes the leftover |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes synth's optimized ARM lowering path (
ir_to_arm) panic-free on malformed input — the last remaining panic site in that pipeline — and re-promotes thewasm_ops_lower_or_errorfuzz harness to gating. Closes debt open since v0.3.1.Background
wasm_to_irwas hardened across v0.3.1/v0.4.0 (returnsResult, pre-flightwasm_stack_check). Butir_to_arm'sget_arm_regclosure stillpanic!'d on an unmapped vreg (the PR #101 defensive panic). Because of that,wasm_ops_lower_or_errorwas demoted togating: falsein PR #117 and never re-promoted.Part 1 —
ir_to_armpanic-freeir_to_arm(...) -> Vec<ArmOp>→-> Result<Vec<ArmOp>>.get_arm_reg: thepanic!becameErr(Error::synthesis(...)), preserving the exact issue-memset/memcpy/memmove i64-codegen produces non-terminating loop on Cortex-M (silicon-blocking) #93 diagnostic. The mapped / spilled branches returnOk.?through all 166get_arm_regcall sites inir_to_arm.arm_backend.rsfoldsir_to_arminto the existingoptimize_full().and_then(...)chain — anErrfalls back to the direct selector (honest degradation, same shape as the issue-wasm_to_ir: unmapped vreg panic still trips on compiler_builtins (float::div) and gale_compute_ipi_mask after v0.2.1's #97 memset fix #120 float fallback, not a silent R0 swallow). The fuzz harness skips onErr.The defensive check is not removed — it's converted panic→Err. A malformed-input case and a genuine internal bug both now yield a typed
Errwith the rich diagnostic. The harness contract ("lower or Err, never panic") is satisfied.Part 2 — fuzz re-gated
.github/workflows/fuzz-smoke.yml:wasm_ops_lower_or_errorflippedgating: false→gating: true; the issue-#121/PR-#117 demote comment replaced with a note thatir_to_armnow returnsResult.Part 3 — regression test
New
crates/synth-synthesis/tests/regression_ir_to_arm_panic_free.rs, 5 tests: mixed i32 arith/shift, type-mismatched i64, i64-extend-into-shift, well-formed-program-lowers-to-Ok, and a hand-built IR instruction (Addwith unproduced src vregs) that reachesget_arm_reg's defensive branch directly and confirms it yieldsErr(with a diagnostic-content assertion) rather than panicking.Note: the
optimize_fullpre-flight catches WASM-op-level malformed shapes beforeir_to_arm; the hand-built-IR test is what exercises the now-Errpath directly.Validation
cargo test --workspace --exclude synth-verify— 0 regressions (+5 tests).cargo clippy --workspace --exclude synth-verify --all-targets -- -D warnings— clean.cargo fmt --check— clean.Test plan
wasm_ops_lower_or_errorfuzz harness🤖 Generated with Claude Code