Skip to content

fix(z80): legal spill operands and emitted split labels — no invalid asm on fuzz2 (P8) - #64

Merged
oisee merged 3 commits into
mainfrom
fix/P8-invalid-asm
Oct 2, 2026
Merged

oisee merged 3 commits into
mainfrom
fix/P8-invalid-asm

Conversation

@oisee

@oisee oisee commented Oct 2, 2026

Copy link
Copy Markdown
Owner

P8: production Z80 no longer emits invalid assembly on fuzz2-shaped programs

Fixes the root-cause classes behind the assembly failures the differential fuzzer found on main:

  • a spill slot used as an ALU or immediate operand;
  • spill labels that were referenced but never emitted;
  • split labels that were never emitted;
  • wide (u24/u32) spill operands;
  • an accumulator on the right-hand side of an ALU op;
  • SBC through an index register;
  • conditional-call intrinsics.

Each fix routes the value through a legal register path. Wide staging and wide slot sizes now apply only to u24/u32 integers. A constant copied into a spilled block parameter is now stored at full width.

Numbers (base 6b8fc39)

  • Fuzzer, seeds 0–1099: assembly failures go from 683 to 0. All 1,100 programs assemble, and the Z80 result matches the MIR2 VM on all of them.
    • 5 seeds (56, 399, 784, 812, 967) disagree with the Python oracle. The oracle is right there; VM and Z80 share an older frontend bug: literal-only expressions are typed u8 in a u16 context.
  • Critic's independent fuzz, seeds 5000–5499:
    • main: 298 of 500 fail to assemble, and 61 compile to wrong VM values.
    • branch: 0 fail to assemble, 497 are correct, and the other 3 are the same oracle cases.
  • Per-assert matrix: 4,016 checks. Passes go from 3,070 to 3,072. 0 newly failing.
  • Corpus: assembly failures go from 65 to 61, with no new failures. These now assemble:
    • nanz/nc.nanz
    • nanz/rotozoomer.nanz
    • nanz/test_irc_minimal.nanz
    • glsl_sphere_demo.minz
  • Size: files that assemble on both builds grow from 141,594 to 141,630 bytes (+36).
  • Bonus fixes:
    • OpCallCond emitted CALL cc with no argument setup (a silent miscompile).
    • highByte(spill) wrote the low byte twice.

Honesty note

Correctness evidence covers fuzz2-shaped programs only. On the critic's second generator (globals, u8 temporaries), production Z80 is wrong on essentially every program, on main and on this branch alike. Bugs that already existed now show up as wrong values instead of assembly errors. The report lists them:

  • the memory-parameter ABI mismatch;
  • a byte XOR of truncated u16 values computing 0;
  • tail-call argument setup clobbering B;
  • literal typing;
  • shifts on IX/IY halves;
  • u32 spill-to-global stores;
  • u24 moves through emitMov32.

Those are the next correctness track.

Gate

  • Every regression test was seen failing without its fix.
  • Required Go gates: exit 0.
  • Cross-family critic: MERGE GO after two rounds.

Report: reports/2026-10-02-P8-Invalid-Asm.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Wrwo36SzxKRZYTgpDo7hzo

oisee and others added 3 commits October 2, 2026 13:17
Route byte and wide spills through legal register paths, preserve staging
values, size spill data correctly, and collect orphan TSMC stores before
data emission. Forward split return values and include nested dependencies;
lower conditional intrinsics through the shared call path.

Add red/green assembly and execution regressions and replace the recorded
u32 assembly limitation with a 65,636-case Z80 judge. Seeded assembly
failures fall from 683/1100 to zero; the corpus assertion matrix has zero
new failures. Retain source-oracle discrepancies and remaining corpus
classes in the measurement report.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wrwo36SzxKRZYTgpDo7hzo
Keep aggregate and pointer spill values in word slots, gate shadow-bank
staging on 24/32-bit integers, and reject insufficient staging pairs.
Store every byte of spilled constant block parameters and cache register
information per function. Add executed regressions and document remaining
correctness defects and final corpus/fuzzer/assertion measurements.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wrwo36SzxKRZYTgpDo7hzo
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wrwo36SzxKRZYTgpDo7hzo
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

PR tests: 🟢 pass

Commit: cb307f2b · Full test log

Check Result
Build mz, mza, mze, mzv 🟢 pass
Stable Go package tests 🟢 pass
Fibonacci compile + assemble 🟢 pass
Nanz language regressions 🟢 pass
Z3 West of House demo 🟢 pass
Z3 small conformance fixtures 🟢 pass

The external CZECH and full Zork I stories are not part of this PR gate.

@oisee
oisee merged commit 05402e1 into main Oct 2, 2026
2 checks passed
@oisee
oisee deleted the fix/P8-invalid-asm branch October 2, 2026 14:00
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.

1 participant