Summary
synth compile defaults to --target arm (ARM32, IsaVariant::Arm32 → ArmEncoder::new_arm32()). For a WASM memory access whose address operand is a runtime register (MemAddr { base: R11, offset_reg: Some(rN), offset }), the ARM32 encoder emits a base-only ldr/str rd, [r11, #off], silently dropping the register index rN. The Thumb-2 encoder (new_thumb2_*) handles offset_reg correctly (encode_thumb32_ldr_reg etc., arm_encoder.rs:2053+).
Impact
Any iN.load*/iN.store* with a non-constant (register) address compiled for the default arm target addresses linear-memory offset 0 instead of [mem_base + addr] — a silent miscompile. Discovered while diagnosing #204: emulating the default-target build showed ldr r4, [r11] (index dropped) where the selector IR correctly had offset_reg: Some(R3). gale's path (cortex-m4 / Thumb-2) is unaffected — that's where #204 was actually fixed.
Evidence
- Selector IR (correct):
Ldr { rd: R4, addr: MemAddr { base: R11, offset: 0, offset_reg: Some(R3) } }
- ARM32-encoded bytes @ the load:
00 40 9b e5 = ARM ldr r4, [fp] (no index).
- Thumb-2 bytes for the same IR:
ldr.w r4, [r11, r3] (index present).
Fix
Make ArmEncoder::new_arm32()'s Ldr/Str (and sub-word/i64 variants) encode the register-offset addressing mode (LDR rd, [rn, rm], A32 encoding with bit25=1) when addr.offset_reg.is_some(), mirroring the Thumb-2 path. Add a verify-bytes-not-IR regression that asserts the encoded ARM32 bytes carry the index.
Lower priority than the Cortex-M path (real targets are Thumb-2), but it's a silent-miscompile footgun on the default target.
Summary
synth compiledefaults to--target arm(ARM32,IsaVariant::Arm32→ArmEncoder::new_arm32()). For a WASM memory access whose address operand is a runtime register (MemAddr { base: R11, offset_reg: Some(rN), offset }), the ARM32 encoder emits a base-onlyldr/str rd, [r11, #off], silently dropping the register indexrN. The Thumb-2 encoder (new_thumb2_*) handlesoffset_regcorrectly (encode_thumb32_ldr_regetc., arm_encoder.rs:2053+).Impact
Any
iN.load*/iN.store*with a non-constant (register) address compiled for the defaultarmtarget addresses linear-memory offset 0 instead of[mem_base + addr]— a silent miscompile. Discovered while diagnosing #204: emulating the default-target build showedldr r4, [r11](index dropped) where the selector IR correctly hadoffset_reg: Some(R3). gale's path (cortex-m4 / Thumb-2) is unaffected — that's where #204 was actually fixed.Evidence
Ldr { rd: R4, addr: MemAddr { base: R11, offset: 0, offset_reg: Some(R3) } }00 40 9b e5= ARMldr r4, [fp](no index).ldr.w r4, [r11, r3](index present).Fix
Make
ArmEncoder::new_arm32()'sLdr/Str(and sub-word/i64 variants) encode the register-offset addressing mode (LDR rd, [rn, rm], A32 encoding with bit25=1) whenaddr.offset_reg.is_some(), mirroring the Thumb-2 path. Add averify-bytes-not-IRregression that asserts the encoded ARM32 bytes carry the index.Lower priority than the Cortex-M path (real targets are Thumb-2), but it's a silent-miscompile footgun on the default target.