Skip to content

I64SetCond hardcodes R0..R3, clobbers param registers (found by #100 fuzz harness) #103

@avrabe

Description

@avrabe

Discovery

The cargo-fuzz harness i64_lowering_doesnt_clobber_params (PR #100, currently in CI) found this AAPCS-clobber regression as soon as it ran. Crash signature:

assertion left != right failed: AAPCS clobber: ARM instr at wasm line 1 writes
param reg R0 before LocalGet(0) at line 4.
Op: I64SetCond { rd: R0, rn_lo: R0, rn_hi: R1, rm_lo: R2, rm_hi: R3, cond: LT }

Reproduction

let wasm = vec![
    WasmOp::I64Const(0),                           // produces hi:lo
    // ... arrangement that synthesizes I64SetCond ...
    WasmOp::LocalGet(0),
];

When wasm pushes an i64 constant and an i64 comparison op runs before a LocalGet(0) that reads R0 (the first param under AAPCS), I64SetCond writes R0 with the comparison result — destroying the param.

Root cause hypothesis

I64SetCond { rn_lo: R0, rn_hi: R1, rm_lo: R2, rm_hi: R3 } is the legacy hardcoded-register pattern that the v0.1.1 #86 fix replaced for I64Const-in-i64-ops via the alloc_i64_pair helper. The fix wasn't applied to I64SetCond (and presumably I64Eqz, I64Cmp, etc — the other i64 ops that use R0..R3 directly).

Scope

Same shape as the v0.1.1 fix, different ops. The optimized lowering path in optimizer_bridge::ir_to_arm needs every i64 op that touches R0..R3 to go through alloc_i64_pair (or an equivalent helper that respects the AAPCS param reserved set).

Candidate ops to audit:

  • I64SetCond (confirmed by fuzz)
  • I64Eqz
  • All other I64Cmp variants
  • Anything else where ir_to_arm hardcodes R0:R1 / R2:R3

Relation to existing work

Recommended fix

Apply the alloc_i64_pair-style register allocation to every i64 op in optimizer_bridge::ir_to_arm. Audit, don't whack-a-mole.

Bug class flag

#bug #aapcs #i64 #regalloc

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions