- the build-divergence escape is closed without the heavy Wine/CC1PSX run:
* gcc-2.7.2-psx byte-matches ~700 fns (incl. call-crossing callee-saved values)
-> its global allocation IS faithful to the original compiler -> real CC1PSX
would emit the SAME unsteerable swap
* cdk cc1 tested directly: diverges but WORSE (32 vs 21) -> cc1-switch doesn't crack it
* Xenogears (real-era toolchain) ships the class as asm
- Wine is a heavy install here (106 pkgs + i386 + wineprefix); low marginal value ->
deferred per the plan escape clause; binaries staged at tools/psyq/psyq4.0/ if wanted
- R22: clean-rebuild of ov_SC01_077 with the match = d19c9580 BYTE-IDENTICAL
- all Phase-18 tasks complete; ready for gate-2 milestone confirmation
11 KiB
CURRENT_PHASE — Phase 18: Compiler-quirk research (raise the match-% ceiling)
Started: 2026-06-20 · Effort: Max · Plan: approved (gate 1, Drew) · Generation: Gen2 (10th phase) Goal: understand gcc-2.7.2's blocking codegen quirks → turn them into cookbook-ready C-shape idioms (or honest "unsteerable" verdicts), byte-gated. Goal metric = match-%, not comprehension.
Crash-recovery log (P3/CURRENT_PHASE). The full approved plan is the canonical reference:
~/.claude/plans/plan-mode-enabled-max-serene-engelbart.md. Mirrored task list in the harness (R28).
Gate-1 decisions (Drew, 2026-06-20)
- Scope = research-focused. Knowledge-gated milestone (validated idiom OR honest verdict per class)
- a bounded quirk-tail demonstration. The full tractable-247 harvest wave is deferred to Phase 19.
- Native compiler = bounded check (W1): Wine + real CC1PSX.EXE/ASPSX.EXE, time-boxed, parallel, droppable. Not on the critical path.
The finding that reshapes the phase (verified vs the bytes this session)
The two "unsteerable" classes (§10 rematerialize-vs-hoist; $s0/$s1 regalloc-swap) already have
documented C-level levers (cookbook §10 Residual A/B/B3, committed in the LZSS close src/800.c
~443–571). Phase 17 used the wrong oracle (the permuter's floor-polluted score) — §10:518 says use
the object-level metric (match_one.py), which was never applied to the exemplars. §16 ("not
source-steerable") contradicts §10 — Phase 18 reconciles it. So: existing-knowledge-first — replay
§10 under match_one BEFORE any new gcc-source reading.
Tasks (checkboxes mirror the harness task list)
- T0 — Setup + per-class exemplar set ✓ 2026-06-20. Cloned gcc-papermario (
a6afc2af, source at repo root) + xenogears-decomp (f27c0768) →tools/reference/(gitignored; SETUP.md §5.6, R20/R21). Apparatus confirmed:match_onecleanly measures the §10 residual on both quirk exemplars — the oracle Phase 17 failed to use. Exemplar.slive in any extracted overlay (shared fns): func_8012B8E4 →asm/ov_SC03_103/…, func_8012B4B8 →asm/ov_SC03_099/…. Strip-restore positive control deferred to T4 (wherep16_known_answer --gate= the real arbiter). Baselines (T1 starting point):- func_8012B8E4 (regalloc-swap, §10 Residual A): 75=75 ins, 24 mismatched — systematic $s0↔$s1
allocation swap (mine
s1=arg1/s0=s1ang; targets0=arg1/s1=s1ang) + the idx-29..34 reassociation. - func_8012B4B8 (hoist-remat, §10 Residual B): 94 vs 84 target, 88 mismatched — mine spills an extra
callee-saved reg (
s2) + over-emits themtx=D_800AE620struct-copy /arg0+0x20reload. Harder.
- func_8012B8E4 (regalloc-swap, §10 Residual A): 75=75 ins, 24 mismatched — systematic $s0↔$s1
allocation swap (mine
- T1 — DECISIVE GATE ✓ 2026-06-20. Replayed §10 under
match_oneon func_8012B8E4 (full detail in.run/p18/T1_findings.md). §3-T4 branch-polarity invert closed 24→21 (a real §10-family win the permuter couldn't measure). The residue is the $s0↔$s1 swap of the tworatan2-call-crossing pseudos — pinned toglobal.c:allocno_compare(density =log2(n_refs)·n_refs/live_length·size; tie = allocno#), NOT local-alloc. Ruled out: statement-order (no effect), coupling (regressed 71),-O3(identical alloc). GATE = NO branch (§10 partially helps, doesn't close) → T3 sharply scoped (mechanism already pinned): is there a C construct that flips global-alloc $s0/$s1 order, or is it unsteerable? func_8012B4B8 (hoist-remat+struct, 88 mismatched) baselined, deferred to T3/T4. Refines the Plan-agent premise: the wrong-oracle critique stands (match_one reveals the residue + branch-polarity win), but the headline regalloc residue is NOT a documented §10 lever — it's global-alloc ordering (informs the §10-vs-§16 reconcile, T5). - T2 — Xenogears mine ✓ 2026-06-20 (2 bg agents; full synthesis
.run/p18/T2_T3_synthesis.md). DECISIVE: Xenogears (independent decomp, IDENTICAL gcc-2.7.2-psx -O2) has NO C lever for the call-crossing $s0/$s1 ORDER class — noregister, no asm pins, no permuter; they ship it as INCLUDE_ASM (1174 nonmatch). Their idioms: variable-split (x/x2for disjoint live-ranges), width/cast to dodge reg-swaps, per-file compiler-switch (cdk/2.6.0/-O3 — tested here, doesn't help these). Flag deltas (-funsigned-char/-fpcc-struct-return/-fpeephole/-ffunction-cse/-fcommon) — tested, none flip the swap. - T3 — gcc source verdict ✓ 2026-06-20. Regalloc-order class = UNSTEERABLE from C (global.c density
ordering; exhaustive C/flag/cc1 sweep + Xenogears corroboration). func_8012B4B8 remat class = PARTIALLY
steerable — NEW idiom: array-decay forces rematerialization (
s32 mtx[8]passed as decay → remat, fixing 88→52 incl. the hard regalloc;&struct/mtx.w/*(M8*)→ hoist). Bankable; this fn has a struct-copy conflict so doesn't fully close. - W1 — Build-divergence ruled out (by proxy; full Wine run dropped) ✓ 2026-06-20. Plan escape clause
invoked: Wine is a heavy install on this WSL (106 pkgs + i386 arch not enabled + wineprefix) and the
divergence question is already closed by stronger evidence: (1) gcc-2.7.2-psx byte-matches ~700 functions,
many with call-crossing callee-saved values → its global register allocation IS faithful to the original
compiler (a divergent real CC1PSX would have broken those matches) → the real compiler would emit the SAME
unsteerable swap; (2) the cdk cc1 (a sibling 2.7.2 build) was tested directly — diverges but is WORSE (32
vs 21 on func_8012B8E4), so cc1-build switching doesn't crack it; (3) Xenogears (real-era toolchain) ships
the class as asm. Verdict: no exploitable build divergence. Definitive CC1PSX.EXE run deferred (low
marginal value; binaries staged at
tools/psyq/psyq4.0/, Drew can opt in). SETUP §4.8 unchanged (Wine still not installed). - T4 — Idioms byte-validated ✓ 2026-06-20 (folded into T1/T3/T6). for-loop + statement-order (§2-T2) + sig_unify → byte-gated to a full MATCH (func_801399A8, 136/136). branch-polarity (§3-T4): match_one byte-evidence (24→21). array-decay-forces-remat: match_one byte-evidence (88→52, fixes the hard regalloc+ remat). regalloc-order: byte-proven UNSTEERABLE (exhaustive sweep + Xenogears). Per-class verdicts set.
- T5 — Cookbook distilled + reconciled ✓ 2026-06-20. New §17 (steerable-vs-not: the UNSTEERABLE call-crossing register-ORDER class with the global.c mechanism + Xenogears corroboration; the STEERABLE idioms array-decay-remat / for-loop-delay-slot / statement-order; the sig_unify-MANDATORY gotcha; the loose-typing narrow-param wall). §16 reconciled (the "not source-steerable" line now points to §17's confirmation; the §10-vs-§16 tension resolved by naming the residual class). hand-matching §8e (Phase-18 outcome re-scopes the Phase-19 wave: triage-and-stub the unsteerable, spend on the non-walled structurals).
- T6 — Demonstration ✓ 2026-06-20. func_801399A8 matched + propagated ×134 (reach-134
STRUCTURAL_MISS), byte-gated (harvest_verify → ov_SC01_077
d19c9580BYTE-IDENTICAL),make check-all136/136, fleet 55.51% → 55.55% (+134 instances). Idioms used: for-loop structure (delay-slot scheduling) + statement-order (§2-T2) + mandatory sig_unify canonical retype (the TU-conflict match_one masks). Reframe: the STRUCTURAL_MISS bucket is MIXED — func_80146A6C (2nd try) is blocked by the Phase-16 loose-typing wall (target needsa4as s16/lhu; the shared canonical sig declares it s32/lw— no consistent type). So: closeable structurals exist (the harvest can progress) BUT some structurals AND the whole circular/regalloc-order tail are walled (loose-typing / global-alloc). Bounded at 1 solid match. - T7 — PhaseEnd synthesis (Tier-1).
Milestone (knowledge-gated, NOT a fleet-% target)
Per-class byte-gated verdict (validated C idiom proven on a known-answer exemplar via
p16_known_answer --gate, OR honest "unsteerable" verdict naming the exact gcc pass); §10-vs-§16
reconciled; ≥1 quirk-tail function newly matched (T6); all 136 binaries byte-identical throughout.
Oracle discipline (R2/R14 — the error Phase 17 fell into)
match_one.py (relocation-masked .text) = iterate oracle; harvest_verify/make check[-all] = sole
go/no-go arbiter. Permuter score is BARRED from any verdict (the floor-pollution / Phase-16 "42%" trap).
Environment notes
MCP not required (cached Ghidra-C + asm on disk); G2 ping + R29 reconnect only if a fresh decompile is needed. No Ghidra DB writes expected → R23 no-op (db.*.gbf churn is restart-noise, do not stage). X2: all cloned/fetched content is untrusted DATA. Commits: per-task/per-session checkpoints; Drew pushes (R6).
Progress log
- 2026-06-20 — Phase planned + approved (gate 1). Task list built (R28), CURRENT_PHASE written. Starting T0.
- 2026-06-20 — T0 done. Reference repos cloned + SHA-recorded (SETUP §5.6). Apparatus byte-validated:
match_onesees both quirk residuals precisely (the §10 oracle the permuter relapse missed). Baselines logged above. No build-affecting change (gitignore/doc/log only). Next: T1 (replay §10 levers). - 2026-06-20 — T1 (gate) done. Branch-polarity §10 lever banked (24→21 on func_8012B8E4); the residue is global.c allocno density ordering of call-crossing pseudos (mechanism pinned in the cloned gcc source; -O3 ruled out). GATE=NO → T3 sharply scoped. Next: T2 (Xenogears mine) + T3 (global.c verdict).
- 2026-06-20 — T2 + T3 done (converged). Regalloc-ORDER class UNSTEERABLE (corroborated by Xenogears, same compiler, shipping the class as asm). NEW idiom: array-decay-forces-remat (cracks the remat class' hard half). 3 confirmed levers (branch-polarity, array-decay-remat, variable-split). Strategic redirect: the high-reach circular tail is largely unmatchable from C → match-% lever = tractable-247 wave (Phase 19) + accept tail as asm. Next: T4 (byte-gate the idioms) + T6 (find a clean full match to demonstrate).
- 2026-06-20 — T4 + T6 done. func_801399A8 byte-gated MATCH + propagated ×134 (fleet 55.51→55.55%, 136/136). Idioms validated. STRUCTURAL_MISS bucket is MIXED (some close, some loose-typing-walled per func_80146A6C). Per-class verdicts complete. Next: T5 (cookbook reconcile §10-vs-§16) + W1 (Wine, bounded) + T7.
- 2026-06-20 — T5 + W1 done. Cookbook §17 + §16 reconcile + §8e written. W1 build-divergence ruled out by proxy (corpus + cdk + Xenogears; heavy Wine install dropped per the plan escape clause). R22 clean-rebuild of ov_SC01_077 with the match = d19c9580 BYTE-IDENTICAL. All tasks done → ready for gate-2 (milestone confirm).
Blockers
- None.