Skip to content

fix(#372): i64.load/i64.store correctness + v0.11.47#373

Merged
avrabe merged 3 commits into
mainfrom
fix/372-i64-load-store
Jun 18, 2026
Merged

fix(#372): i64.load/i64.store correctness + v0.11.47#373
avrabe merged 3 commits into
mainfrom
fix/372-i64-load-store

Conversation

@avrabe

@avrabe avrabe commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Fixes #372 — full-width i64.load/i64.store. jess: 39 falcon sites. Ships as v0.11.47.

The bug was 3 layers (deeper than "wire the decoder")

Verification

  • ld64(16)=mem[16], st64 writes mem[addr] on both optimized and direct paths (i64_load_store_372_differential.py).
  • Frozen oracles bit-identical (control_step 0x00210A55 13/13, flight_seam 0x07FDF307, div_const 338/338); i64-frame fixtures byte-identical (u64_unpack).
  • Unit test test_372_i64_ldr_indexed_materializes_address; 39 suites green; fmt + clippy clean.
  • Release: pin sweep 0.11.46→0.11.47, CHANGELOG falsification, rivet GI-MEM-001→implemented + GI-MEM-VER-001.

Falsification: i64.load/i64.store read/write the addressed location instead of mem[0]; pure-integer + i64-frame modules byte-identical.

Closes #372.

🤖 Generated with Claude Code

avrabe and others added 3 commits June 18, 2026 00:56
…+ decoder WIP

NOT a fix (partial WIP). Diagnosed why falcon loud-skips 39 i64.load/store sites
on v0.11.46. It's THREE layers, worse than the issue assumed (gale thought the
lowering was ready):
 L1 DECODER GAP: convert_operator decodes the narrow i64 loads (I64Load8..32)
    and I32Load/Store but has NO arm for full-width I64Load/I64Store -> _ => None
    -> dropped -> loud-skipped since v0.11.46 (GI-FPU-001). (decoder arm added
    here as WIP — INSUFFICIENT alone: see L2.)
 L2 OPTIMIZED-PATH STUB: with the op decoded, the default optimized path drops
    it -> stub (ld64 -> `bx lr`, st64 -> `mov r0,r1`). So the decoder arm ALONE
    is net-negative (turns the honest loud-skip into a silent stub again). Needs
    an optimizer decline -> direct-selector fallback (mirror #120/#188).
 L3 ENCODER DROPS THE ADDRESS: arm_encoder.rs:5303 I64Ldr/I64Str use addr.base
    + addr.offset but IGNORE addr.index (the address register). Emits
    [R11+offset]/[R11+offset+4], dropping the operand -> reads the WRONG location.
    Proven numerically: ld64(16) returns mem[0] (0xaa..), not mem[16]
    (i64_load_store_372_differential.py). Same class as #206 indexed-load drop.

Fix (next block): decoder arm + optimizer decline + I64Ldr/I64Str encoder index
(materialize ip = addr_reg + offset; ldr/str [R11, ip] {,+4}, like #206), gated
on the numeric differential. Frozen fixtures use no i64.load/store.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…coder index)

falcon loud-skipped 39 i64.load/store sites on v0.11.46. The gap was 3 layers,
and the lowering itself was broken (not just unwired):

 L1 DECODER: convert_operator decoded the narrow i64 loads (I64Load8..32) and
    I32Load/Store but had NO arm for full-width I64Load/I64Store -> _ => None ->
    dropped -> loud-skipped. Added the two arms.
 L2 OPTIMIZER: the default optimized path has no IR opcode for them and dropped
    them to a stub (ld64 -> `bx lr`). optimize_full now DECLINES i64.load/store
    -> falls back to the direct selector (the #120/#188 pattern).
 L3 ENCODER (the real bug): arm_encoder.rs I64Ldr/I64Str used addr.base+offset
    and IGNORED addr.offset_reg -> emitted [R11+offset], dropping the address.
    Proven: ld64(16) returned mem[0], not mem[16]. New i64_effective_base()
    materializes `ADD.W ip, base, index` (byte-verified) then loads/stores via
    [ip,#off]/[ip,#off+4]; non-indexed frame access (offset_reg=None) is
    unchanged -> byte-identical. Same class as #206.

Verified: ld64(16)=mem[16] and st64 use the address on BOTH the optimized and
direct paths (i64_load_store_372_differential.py); frozen oracles byte-identical
(control_step 0x00210A55 13/13, flight_seam 0x07FDF307, div_const 338/338);
i64-FRAME fixtures byte-identical (u64_unpack); unit test
test_372_i64_ldr_indexed_materializes_address; 39 suites green; fmt+clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pin sweep 0.11.46 -> 0.11.47 (workspace + 10 path-deps + MODULE.bazel +
Cargo.lock). CHANGELOG v0.11.47 with falsification. rivet GI-MEM-001 ->
implemented + GI-MEM-VER-001.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe avrabe merged commit b8cfd03 into main Jun 18, 2026
13 checks passed
@avrabe avrabe deleted the fix/372-i64-load-store branch June 18, 2026 05:06
@codecov

codecov Bot commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/synth-core/src/wasm_decoder.rs 0.00% 8 Missing ⚠️
crates/synth-synthesis/src/optimizer_bridge.rs 50.00% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

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.

arm backend cannot lower i64.load/i64.store (unsupported decoder op) — 39 sites block falcon on-target

1 participant