← board

-O2 miscompiles the x86-64 disassembler (WriteDisassemblyX64)

Symptom

A compiler built at -O2 emits garbage from its -S disassembler path; a compiler built at -O0 (or -O1?) emits correct disassembly. The compiler produced is otherwise self-host byte-identical and passes c-testsuite 220/220 + quick — because self-compile never invokes the compiler's OWN -S path, so the miscompile hid until make test-asm (which disassembles hello and greps for call/ret) ran against an -O2-built compiler.

Exact repro

# clean O0 compiler disassembles hello correctly:
compiler/pascal26 -O0 compiler/compiler.pas /tmp/cc_o0
/tmp/cc_o0 -S test/hello.pas /tmp/good
grep -cE '^    call |^    ret$' /tmp/good.s   # -> 235   (correct)
grep -c   '^    db '           /tmp/good.s    # -> 0

# O2-built compiler disassembles hello into garbage:
compiler/pascal26 -O2 compiler/compiler.pas /tmp/cc_o2
/tmp/cc_o2 -S test/hello.pas /tmp/bad
grep -cE '^    call |^    ret$' /tmp/bad.s     # -> 0     (WRONG)
grep -c   '^    db '           /tmp/bad.s      # -> 6     (raw-byte fallback: decode desynced)

The -S OUTPUT level is irrelevant — the bug is in the disassembler CODE when compiled at -O2, so both -O0 -S and -O2 -S from the O2-built compiler are garbage. make test-asm (Makefile ~379-383) is the gate that catches it.

Where to dig

WriteDisassemblyX64 (asmdisasm_x64.inc) is a large routine: a byte-fetch cursor over .text, many locals, big case dispatch on opcode bytes, ModRM/SIB decode. That profile is a stress case for the two -O2-only passes:

Acceptance

Context — the reverted -O2-default work (re-apply after this fix)

Measured and proven EXCEPT this bug: OptLevel default 0→2, self-host -O2 fixedpoint byte-identical, make test-opt OK, c-testsuite 220/220, cross hello 4 targets. The missed-fold tripwire (IROptWarnMissedFold) must also be gated to dev/measurement runs (NOT -Werror) when -O2 is default — inline produces foldable BINOPs on every compile; see [[feature-revive-const-fold-identity-pass]]. Re-do those together once the disassembler miscompile is fixed.

Log