Skip to content

i64.rotl/rotr/div_u/rem_u silently compile to 0 on ARM (self-contained, input-independent; i64.rotl-by-0 identity returns 0) — should implement or honestly reject #610

Description

@avrabe

Filed by the PulseEngine challenge harness (synth v0.29.0). Found by executing synth's Cortex-M thumb output under qemu-system-arm and differencing vs wasmtime.

Defect: i64.rotl / i64.rotr / i64.div_u / i64.rem_u silently compile to code that returns 0

These four i64 ops compile without error and produce 0 for every input — a silent miscompile. i64.and/or/xor/shl/add are correct (same harness), so this is not a harness/ABI issue. The generated code is self-contained (no external helper call, no relocations — ruled out a missing __aeabi_uldivmod), so the wrong result is synth's, not a link artifact.

Executed on Cortex-M3 (qemu lm3s6965evb, semihosting); i64 param in r0:r1; result via i32.wrap_i64. Oracle = wasmtime.

op (i64 param -> i32 result)         input      synth   wasmtime
i64.rotl by 8                        1          0       256      DIVERGE
i64.rotl by 0  (identity!)           123        0       123      DIVERGE
i64.rotr by 8                        256        0       1        DIVERGE
i64.div_u by 7                       100        0       14       DIVERGE
i64.div_u by 7                       700        0       100      DIVERGE
i64.rem_u by 7                       100        0       2        DIVERGE
-- controls (CORRECT) --
i64.and / or / xor                   ...        ==      ==       OK
i64.shl by 4 / i64.add +1            ...        ==      ==       OK

i64.rotl by 0 is the clearest tell: it is the identity (must return the operand) yet returns 0, and rotate needs no runtime helper — so this is a genuine lowering bug, not "unimplemented, needs a libcall."

Repro

(module (func (export "f") (param i64) (result i32)
  (i32.wrap_i64 (i64.rotl (local.get 0) (i64.const 8)))))
synth compile f.wat -t cortex-m3 -n f --relocatable -o f.o   # self-contained, no undefined symbols
# link f (as synth_f) with a semihosting runner calling synth_f(low, high); run under
# qemu-system-arm -M lm3s6965evb -nographic -semihosting  ->  prints 0 for any input
# wasmtime --invoke f (arg=(high<<32)|low) prints the correct rotate/quotient.

Expected

Either implement these i64 ops correctly, or — following the #554 precedent (dropped-at-decode ops now raise an explicit error rather than emit a silent miscompile) — honestly reject them. Silently returning 0 for a 64-bit rotate/divide on a shipping target is the worst outcome. (The i64 op-class work in the closed #587/#242 was about regalloc skipping functions; these ops are not skipped — they compile and return 0.)

Note

Found with the thumb-execution differential probe (harness/synth_thumb_exec_probe.sh); these i64 ops are now tracked there.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions