Conversation
guybedford
left a comment
There was a problem hiding this comment.
Review: feat: wide arithmetic proposal
CI: All checks pass (stable, beta, nightly, fuzz, rustfmt)
Summary
This PR adds support for the Wide Arithmetic WebAssembly proposal (currently Phase 3), implementing four new instructions:
i64.add128— 128-bit addition (4 × i64 → 2 × i64)i64.sub128— 128-bit subtraction (4 × i64 → 2 × i64)i64.mul_wide_s— signed widening multiply (2 × i64 → 2 × i64)i64.mul_wide_u— unsigned widening multiply (2 × i64 → 2 × i64)
Positive aspects
- Clean, minimal implementation. The pattern matches exactly how prior instructions (e.g.
AnyConvertExtern,ExternConvertAny) were added. - Feature-gated correctly. The proposal is Phase 3, and it's gated behind
only_stable_features = falseinconfig.rs. This is the right call. - Spec tests enabled.
spec-tests.rswas updated fromreturn Ok(())(skip) to&[](run with no expected failures), and the CI confirms they pass. - Round-trip test included.
wide-arithmetic.watcovers all four instructions with a tidyCHECK-ALLsnapshot. - All test snapshots updated. The mass-update to
.watsnapshots is caused by thewasmprinterupgrade changing output ordering (exports before function bodies,@producerssection now emitted). This is expected churn from the dep bump, not a logic change.
Issues and concerns
1. Doc comment describes operand order ambiguously for i64.add128 / i64.sub128
In src/ir/mod.rs:
/// Pops four i64 values (lo1, hi1, lo2, hi2), computes (lo1:hi1) + (lo2:hi2)
The spec uses lhs_lo, lhs_hi, rhs_lo, rhs_hi terminology — naming them lo1/hi1/lo2/hi2 makes it unclear which value is the low vs high half of each operand. A small wording fix would improve clarity for future readers.
2. Confirm exhaustive match coverage
The is_barrier() method was correctly updated, but walrus has other sites that match on Instr (passes, analysis, dot graph, etc.). Since the compiler enforces exhaustiveness these should all be caught at compile time — but any _ => {} catch-alls would silently swallow the new variants. Worth a quick audit to confirm no silent gaps.
3. wasmprinter version bump drops a pinned exact version (0.2.78 → 0.245)
The old "=0.2.78" pin suggests there was a deliberate reason for it at some point. Worth confirming that dropping the pin doesn't reintroduce whatever caused it to be pinned originally.
4. wasmparser bump is only in fuzz-utils, not the root crate
fuzz-utils/Cargo.toml bumps wasmparser from 0.212 to 0.245, but the root crate's dependency doesn't appear in the diff. CI passes so this is presumably fine, but it's worth explicitly noting that the Operator::I64Add128 etc. variants come from the root crate's wasmparser version.
5. Minor: loop2.wat snapshot change
The change from br_if 1 (;@0;) to br_if 1 (dropping the inline label comment) is a cosmetic output change from the wasmprinter upgrade, not a semantic change. Fine, but worth calling out so it isn't mistaken for a logic regression.
Verdict
The core implementation is correct and follows established patterns in the codebase. CI is fully green. The main items above are minor — the doc comment clarity and confirming the wasmprinter pin drop are the most worth addressing before merge. Overall this is a solid Phase 3 proposal integration.
|
The previous pinned wasmprinter (0.2.78) did not support wide arithmetic opcodes. Upgrade to 0.245 which supports all current proposals and regenerate round-trip test CHECK patterns to match the new printer output format (section reordering, symbolic type names).
be5a14b to
9715173
Compare
Add support for the wide arithmetic proposal. Added 4 new instructions:
Enabled existing spec tests for the proposal. Bumped
wasmprinterandwasmparserto versions which support wide arithmetic. I gated the new instructions behindonly_stable_features = falsesince the prop is currently phase 3.