mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-05 00:47:54 -04:00
bcd44badc93b5f2dd0e077cdf8a120fd9f0e6cb4
1156 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bcd44badc9 |
fix(phase-29): T55 — frontier re-mapped; 2 families swept, 0 banked, both blockers diagnosed to the line
Honest result: NO YIELD. What it produced is a re-measured frontier, a real fix to my own T53 work,
and both failures diagnosed rather than left as "0/N".
FRONTIER RE-MAPPED (T52's +132 moved it): family_hseq -> 2,647 target families, 513 substantial,
64 with a banked exemplar AND live stubs. Caveat recorded: the top two by byte-weight (0x8013c414
180KB, 0x8013c0f8 84KB) are -O0, and _o0 families are already measured at ~1/137 — do not be drawn
by their weight.
FAMILY 1 func_8014032C (183 ins x 136 ~ 25,000 ins): sample 0/8, last_err empty. Read one sibling's
real gate result (§53/§59) past the -j16 interleave and the §58 memcpy red herring — TWO causes:
(1) conflicting types for D_80115128 — the T48/T51 class, which tu-scoped should have caught;
(2) jtbl_rodata_pads "more rodata .align than pad specs — table-count drift vs the carve", a
DISTINCT class jtbl_family_bank's own comment documents as NOT isolate-fixable (§91 --like
role trap).
After fixing (1): still 0/8. Cause 2 is the live blocker — carve work, not decl work. NOT ground
further; it is a documented wall.
THE T53 DEFECT, FOUND AND FIXED: contested() scanned only the draft's BLOCK-scope externs, because
T51's motivating family had them hand-written in the body. But gather_externs carries decls in at
FILE scope, and those are exactly the ones scope_data_externs.fix DROPS when the TU already declares
the symbol — its give-up branch, the fatal case the lever exists for. Measured: scope_data_fix
dropped 3 symbols while contested() returned []. So the stage never fired on its own class. Now
scope-independent; regression-checked against T51's case using the pre-T51 TU from git (old ==
new, added []), and it now finds D_80115128 on the T55 target.
FAMILY 2 func_80144090 (154 ins x 136 ~ 21,000 ins), chosen because has_mid_jr=False avoids the
carve: 0/136. Diagnosed: conflicting types for D_800A651C (2210 vs 379) — the SAME class.
family_sweep gates via PLAIN harvest_verify by design, so it never sees the tu-scoped lever, which
lives only in jtbl_family_bank. Probed: the lever would move D_800A651C + D_800AF648 (deletion-only)
and REFUSES D_800B9A02 as "3 file-scope decls above (ambiguous)" — an over-conservative refusal,
since duplicate-IDENTICAL externs are legal C.
THE FINDING: the same decl-scope collision class gates the frontier's mechanical families — it cost
T52's family 133 of 137 siblings, and it blocks both families probed here. The lever exists and is
byte-proven; it is not reachable from the sweep path most families use.
No src/ or config/ change: no bank, no metric move. Tree verified clean after every probe.
|
||
|
|
f72e2344a6 |
fix(phase-29): T54 — correct the ADDRESSING route, and fix the reason changing it was inert
Item 1 off T53's list. Two changes: the route, and the design flaw underneath it.
THE DEFECT UNDER THE DEFECT (cookbook §106). residual_class answers two questions in one pass:
`klass` is a MEASUREMENT (expensive, from comparing instruction streams); `(profile, bucket)` is a
POLICY (a table lookup over it). autopsy persisted BOTH and verdicts() read BOTH back — so editing
_ROUTE changed nothing until someone re-ran the whole collect, and a weeks-old row could silently
out-vote the live table with no oracle to report it. The corpus on disk is dated Jul 21 and does not
even contain the SESSION-23 targets the recommendation cited.
Fixed by re-deriving at read time: residual_class.route_for(klass, detail), called from
autopsy.verdicts(). R33 — persist the measurement, derive the decision. Subtlety: LENGTH-DRIFT's
route is MAGNITUDE-dependent (permuter only when |delta|<=2 AND explains=="tail", §60b), so a naive
re-derivation from klass alone would have silently demoted 9 rows; both inputs are already in
`detail`, so the override reproduces exactly — VERIFIED 1610/1610 against the stored corpus with the
table UNCHANGED, before touching it.
THE ROUTE CHANGE: ADDRESSING ("cse","permuter") -> ("cse","structural"). It contradicted this file's
own bucket definition ("structural — local mutation CANNOT introduce it ... it wants a C-level
idiom"): the §10/§20 hoist-vs-remat shape is a multi-instruction change with a documented recipe
(gcc-2.7.2-map/cse_expr.md §2, byte-proven on func_80149374/func_801493D0). Measured (T31): both
admitted ADDRESSING targets plateaued under a §31-directed permuter, and the class was 32% of the
admission pool. After: pool 56 -> 38, exactly 18 rows changed, ALL ADDRESSING, nothing else moved;
grinder admits 45, structural skips 512 -> 530.
THE BOUND (R14), kept in the _ROUTE comment: I read the T31 record instead of the summary line, and
the summary was looser than the evidence. T31 finding 4 byte-tested the §2 recipe on func_80132F40
across six variants and it never closed (best 40 mismatches). `structural` does NOT promise a free
fix — it means "a search over local mutations is the wrong tool, try the documented idiom", exactly
what WIDTH / BRANCH-POLARITY / IMM-OFFSET already mean. Also corrected: the checkpoint cited
func_80176734 as the flat-for-32-min evidence, but that function is not in the corpus at all.
Tooling-only: no src/ or config/ change, no bank, no metric move.
|
||
|
|
f285de46e8 |
feat(phase-29): T53 — fold the T51 lever into the gate; kill gather_externs' false positive; close a revert gap
Items 1-2 off T52's list, plus a third defect found by T53's own testing. TOOLING ONLY — banks
nothing; metrics unchanged by design (85.7% instr / 76.4% distinct / 90.65% fn-count).
1. THE T51 PRE-PASS IS A jtbl_family_bank STAGE (cookbook §103, AUTOMATED)
Order: raw -> scoped -> tu-scoped -> recovered -> reconciled. After the non-invasive stages (it
edits the TU outside the spliced body); BEFORE the recovery stages deliberately — those bend the
DRAFT and T48 measured both at +3 ins for this class, so they cannot succeed here. The stage
re-runs scope_data_fix against the SCOPED TU rather than reusing the raw body: composition-correct,
since the contested symbols no longer have a file-scope decl to be dropped against.
COUNTERFACTUAL, byte-gated on a reproduced blocker (ov_SC01_000 restored to its pre-T51 TU):
raw -> compile error (conflicting types)
scoped -> compiles, FAILS the byte check (§8d drops the decl -> the u8 CSE costs +3)
tu-scoped -> BANKED
That is the evidence the stage does the work — not T52's sweep, which ran on TUs T51 had already
scoped by hand.
Refactor note: a stage editing outside the spliced body must RE-FIND the splice point (the stub
offset indexes the ORIGINAL TU). Each stage now carries its base; every pre-existing stage passes
`orig`, where the re-search returns the identical span — same operation as before, by construction.
2. gather_externs' COMMENT-SCANNING FALSE POSITIVE — FIXED (cookbook §104)
It scanned RAW text, so a symbol named only in the draft's PROSE counted as referenced: the
func_80135D20 warning that fired on 137/137 and was right 0 times. Fix is a two-text discipline —
MATCH on cdecl._mask'ed text, EMIT by span from the ORIGINAL (a masked decl is all blanks, so
"just mask it" would splice whitespace). Same change closes a second, unobserved defect of the
class: a COMMENTED-OUT extern could be selected as the carried decl and spliced in as live code.
MEASURED as a no-op on output (R14): 20 (exemplar, sibling) draft pairs across 4 families, old vs
new -> 20 identical / 0 differing. Only the false warning changed.
3. UNPLANNED — A REVERT THAT DID NOT SURVIVE AN EXCEPTION (cookbook §105)
A wrong exemplar made remap_hseq raise AFTER the carve rewrote config/ and jr_isolate created a
region file; the exception propagated out of bank(), the revert never ran, and the tree kept a
rewritten carve config plus an UNTRACKED region file (git checkout -- src/ does not remove it).
In a 132-member sweep that residue rides into the next member's build. bank() is now a
revert-guaranteed wrapper around _bank(). Negative-control proven: the crashing invocation now
reports {'exception': 2} and leaves git status -- config/ src/ at 0.
"Revert on failure" != "revert on every exit"; the exits are success, gate-fail, refusal, and the throw.
GATES: R22 clean-fleet 140 passed, 0 failed of 140. tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED,
cdecl, audit-binaries, report/lint/dedup 1886/0). 0 NON_MATCHING (G4).
HONEST COVERAGE GAP: no live end-to-end BANK through the refactored loop — all three big families are
137/137 and the only family with live stubs (0x80191c50) has no banked exemplar, so it refuses. The
counterfactual byte-gated the exact splice on all three candidates and the 2-member run exercised
construction/refusal/revert/tally; the next real family sweep is the true end-to-end validation.
MY ERRORS: invoked the sweep with a wrong exemplar+address for a cross-address family (an unmeasured
guess about a members file I had not read — it is what surfaced defect 3); and deleted last_err's
initializer while refactoring, which would have raised NameError on the first clean gate-fail.
cookbook §103 (AUTOMATED) + §104 + §105; SETUP inventory row updated (R21).
|
||
|
|
d4dc533f54 |
feat(phase-29): T52 — func_80135260 swept 132/132 (0 failed); the family goes 4/137 -> 137/137
T51's payoff. The invocation is IDENTICAL to the T49/T50 runs; the only variable is T51's decl scoping. T49/T50 (pre-T51) 4 banked / 133 gate-fail (and all 4 were SC07 — a different cause) T52 sample (8) 8 BANKED / 8 52s T52 rest (124) 124 BANKED / 124 13m04s TOTAL 132 / 132, ZERO failures So the 133 "gate-fails" were never a codegen wall — they were one file-scope declaration per sibling TU. Fifth time this phase a wall has resolved to tooling/plumbing. GATES (from a genuinely clean tree): R22 clean-fleet `make clean && extract-all && check-all` -> 140 passed, 0 failed of 140. `make tools-health` OK — corpus 0 PHANTOM + 0 TRUNCATED, cdecl, audit-binaries, report/lint/dedup 1886 validated / 0 failed (C1 239604/239604). 0 NON_MATCHING (G4). METRICS (reconciled against make report, not asserted): instr-weighted 85.5% -> 85.7% 11240111 -> 11258063 = +17,952 ins distinct-code 76.1% -> 76.4% 67687 -> 67812 unique fns (+125) fn-count 90.62% -> 90.65% 320524 -> 320656 = +132 functions INCLUDE_ASM stubs 33189 -> 33057 = -132 +17,952 templated instructions against T50's ~18,000 estimate. distinct-code gains 125 not 132 because seven siblings are byte-identical to code already counted unique. ALSO SETTLED: - item 3 is now byte-confirmed, not just inspected: [gather_externs] warned "func_80135D20 ... the sibling will not compile" on ALL 132, and all 132 BANKED. A 100% false-alarm rate on this family, actively masking real causes. cdecl._mask is the fix (T51 used exactly that). - the T51 pre-pass is now worth folding into jtbl_family_bank; T51 withheld that pending a measured payoff, and 4/137 -> 137/137 is it. Next task. config/ (per-overlay splat.*.yaml + overlays.mk, written by the carve) is staged alongside src/ — the `git add -A src/` omission this phase already recorded once. |
||
|
|
7b896a2627 |
feat(phase-29): T52 sample — func_80135260 8/8 banked; the T51 lever is validated
Bounded sample before scaling (the standing validate-on-a-sample invariant). The ONLY variable vs the T49/T50 runs is T51's decl scoping; the invocation is identical. T49/T50 (pre-T51): 4 banked / 133 gate-fail (and all 4 were SC07, a different cause) T52 sample: 8 BANKED / 8 in 52s Committed here only because jtbl_family_bank's precondition refuses to run on a dirty config//src/ (its per-sibling revert restores from HEAD, so uncommitted banks would be silently wiped). The remaining 124 follow in the next commit; R22 clean-fleet gates the whole task at the end. Both config/ (the jtbl carve + overlays.mk) and src/ are staged — the omission this file already warned about after a prior `git add -A src/`. Also confirms item 3 empirically: [gather_externs] warned "func_80135D20 ... the sibling will not compile" on every one of the 8, and every one BANKED. Comment-scanning false positive, as T50 said. |
||
|
|
a524142eb5 |
feat(phase-29): T51 — the fleet-wide decl-scoping tool; func_80135260's 132 siblings unblocked
Item 1 off the SESSION-23 list. T48 proved the lever by hand on the exemplar, T50 located the same
blocker in every sibling; this builds the tool, measures the population, applies it fleet-wide, and
gates it. It BANKS NOTHING — it removes the blocker. The sweep is the next task.
MEASURED BEFORE BUILDING (R35). The blocker census over all 132 still-stubbed siblings is perfectly
uniform: 132/132 carry it, 3 contested symbols each, EXACTLY ONE file-scope decl statement per
(TU, sym), ZERO file-scope references below the decl (so the deletion is always safe), 660
block-scope re-declarations needed.
THE TOOL: tools/scope_tu_externs.py — the TU-side complement of scope_data_externs.py (§8d). §8d
fixes the incoming DRAFT and has a give-up branch that DROPS the draft's own decl when the TU already
declares the symbol at file scope. Right when the types agree; fatal when the byte-true draft needs a
different one — which is exactly how 132 byte-true siblings gate-failed wearing a codegen wall's
costume. This moves the TU's OWN file-scope decl down into every later function that references the
symbol and lacks its own block-scope decl, then deletes the file-scope line.
FILE(u8 D_x) ... then BLOCK(u16 *D_x) below it -> conflicting types (the 132 failures)
(no file-scope decl) ... BLOCK(u8) ... BLOCK(u16 *) -> builds; each fn owns its own view
- contested set DERIVED, never hand-listed (R33): the remapped draft's block-scope D_ externs
intersected with the TU's file-scope decls above the splice point; --family does it per sibling
- built on cdecl.split_statements/_mask (R33), not a 7th regex: depth-0 spans (a fn definition
flushes at its closing '}' — a column-0 test is NOT a file-scope test, m2c emits goto labels at
column 0 inside bodies) + length-preserving comment/string masking. That masking is what kills the
comment-scanning false-positive class still open as item 3.
- REFUSES LOUDLY, never skips silently (R32): >1 file-scope decl above the splice point; a
file-scope statement below the decl referencing the symbol; an unlocatable body brace
- coverage asserted as a DELTA (R32): file-scope -1, block-scope +len(consumers). An absolute
"a block-scope decl exists" check would have passed VACUOUSLY — these TUs already carry ~18
legitimate block-scope decls of the same symbols
VERIFIED IN TWO STEPS (T48's structure — why a 132-file edit was safe to make):
1. the move ALONE on ov_SC01_000 -> make build -> 9052dc0e BYTE-IDENTICAL, then reverted
2. fleet-wide -> R22 clean-fleet (make clean && extract-all && check-all) -> 140 passed, 0 failed
of 140; make tools-health OK (corpus 0 PHANTOM + 0 TRUNCATED, cdecl, audit-binaries,
report/lint/dedup 1886/0). Metrics UNCHANGED at 85.5% instr / 76.1% distinct / 90.62% fn-count
— the correct result for a declaration-only change.
The diff is uniform to the line: all 132 files +11/-3. A second --family run reports 132
nothing-to-do, 0 refused (idempotent).
Deliberately NOT done: wiring this as an automatic jtbl_family_bank stage. That waits until the
sweep measures the payoff — folding an unproven pre-pass into the gate is the same unmeasured
premise this phase keeps catching.
Also preserves .run/near6/g5260_a.c (the T48 raw crack body, allowlisted) — the sweep may need it
for --raw.
cookbook §103 + SETUP tool-inventory row (R21).
|
||
|
|
69dee1d429 |
docs(phase-29): T50 + SESSION-23 REVISED final checkpoint
T50 func_80135260 family: the §53 carve path banked 4/137 (all SC07), 133 gate-fail, tree clean after every revert. The 3,744-site conform_decls between runs changed NOTHING for this family (99 attempts observed mid-run, 0 banks) — it is byte-neutral and axis-complete so not harmful, but my inference that this family shared func_80177DA8's blocker was WRONG: same SC07-only signature, different cause. THE REAL BLOCKER, LOCATED: staged siblings are correctly remapped (family_remap works). The draft requires 4-byte POINTER decls for the contested data symbols — the canonical extern u8 + (*(u16**)&sym) form makes gcc CSE &sym into two callee-saved regs, costing a 7th saved register and 3 extra instructions (the identical +3 measured on the exemplar). And every sibling host TU carries the same FILE-SCOPE blocker the exemplar did: verified on ov_SC01_000, whose host TU declares the contested symbols at file scope (lines 3053-3056) alongside 18 block-scope occurrences. A file-scope decl constrains every later function in that TU — the T48 finding. So the fix is the T48 lever replicated x137: scope those decls into their consumers per sibling TU. Byte-neutral on the exemplar (proven in two steps). That is a TOOL, and it is worth ~18,000 ins. Also: gather_externs' warning naming func_80135D20 is a COMMENT-SCANNING FALSE POSITIVE (the symbol appears only in header prose and is defined in another split file). Fires on all 137, masks real causes. Same class as the Phase-19 garbled-hint bug. CHECKPOINT REVISED (supersedes the earlier SESSION-23 block): 975 functions banked, reconciled against the metric (fn-count 319,549 -> 320,524) with the per-task recount agreeing exactly. Fleet 85.5% instr / 76.1% distinct / 90.62% fn-count. R22 140/140 run 11x, dedup 1886/0, 0 NON_MATCHING. Ranked START-HERE (decl-scoping tool first), the four strategic changes, my five recorded errors — whose common thread is inference from partial output instead of measuring — and the carried defects. |
||
|
|
f3e8317bd1 |
feat(phase-29): T49 — func_80135260 x4 siblings + the 3,744-site decl conform
The §53 carve path banked only 4 of 137 siblings, ALL of them SC07 — the exact signature func_80177DA8 showed before its §99 fix, so the same lever applies. - jtbl_family_bank func_80135260: 4 BANKED / 133 gate-fail. The 4 are SC07 overlays. - conform_decls dry run confirmed the class: byte-true def is `s32 func_80135260(s32, s32, s16 *, s16 *)` but 3,744 declaration sites say `(s32, s32, s32, s32)` — params 3 and 4 declared s32 where the byte truth is s16 *. Return type agrees, so the §85 return-axis precondition does not fire. - Applied: 3,744 sites rewritten across 2,021 files; the tool's R32 assertion reports "non-canonical declarations remaining: 0 OK (axis complete)". It correctly SKIPPED the 5 DEFINING TUs (the 4 SC07 banks + ov_SC01_077) — a defining TU owns its own declarations, since per-overlay byte-true signatures legitimately differ under §16 loose typing. - This touches src/shared/engine_core.h, so it is FLEET-SHARED and R22 was mandatory (§61/§63): R22 clean-fleet 140 passed, 0 failed of 140. Also recorded: jtbl_family_bank's [gather_externs] warning named func_80135D20 as an undeclared referenced symbol, but that symbol appears ONLY in the draft's header COMMENTS (lines 3 and 29) — a comment-scanning false positive, same class as the Phase-19 gen_harvest_targets garbled-hint bug. It was not the cause of the 133 failures. Next: re-run the carve path for the remaining 133 siblings now that the decl axis is conformed. |
||
|
|
d6bd7bed9e |
feat(phase-29): T48 — func_80135260 BANKED; a file-scope extern is a TU-WIDE constraint on later functions
The T45 probe re-filed this as a crack target; it turned out to be a SCOPE problem, and the fix is a new reusable lever. DIAGNOSIS. The draft MATCHes standalone (136 ins) with block-scope `extern u16 *D_801870AC/B0/B8`, which are byte-TRUE (they produce the target's 4-byte pointer loads). The TU carries FILE-scope `extern u8 D_801870B0/AC/B8; extern s16 *D_801870B4;` at lines 3433-3436 — the preamble of the already-banked func_80135168 — and a file-scope decl constrains EVERY LATER function in the TU, so the draft's pointer decls became "conflicting types". Ordering is what makes this asymmetric: the TU's own block-scope `extern u16 *D_801870B0;` at L2829 precedes the file-scope u8 decl and only WARNS; a block-scope decl AFTER it is an ERROR. TWO WORKAROUNDS MEASURED AND REJECTED, both +3 instructions with a rotated callee-saved bank: reconcile_tu (conform to the TU) -> 139 ins vs 136, 123 mismatched cast-at-use (*(u16 **)&D_x) -> 139 ins vs 136, 123 mismatched So the byte-true code genuinely REQUIRES the pointer-typed declaration; the decls had to move. THE FIX (move the decls, never the draft — §85 applied to DATA): scoped those four file-scope externs into their only two consumers (func_80135168 and func_80135480, both of which already use the cast-at-use idiom). Verified in two steps: (1) the decl move ALONE rebuilds ov_SC01_077 byte-identical d19c9580 — declaration-only, no codegen change; (2) the original byte-true draft then banks clean, verified 1 / failed 0. R22 clean-fleet 140 passed, 0 failed of 140. THE REUSABLE LEVER: a FILE-scope extern in a shared overlay TU is a global constraint on every later function in that TU. When a byte-true draft needs an incompatible type for the same symbol, scope the existing decl to its consumers rather than bending the draft — bending it cost +3 here, twice. Family sweep is NEXT and needs the §53 carve path (has_mid_jr: true, 137 siblings, PURE) — family_sweep correctly refused it. |
||
|
|
efea7473f5 |
chore(phase-29): preserve the T42/T43 and T47 draft ladders
.run/near6/d68_{typefix,sigfix,final,blockscope,selfcontained}.c — the five-step ladder that took
func_80140D68 from "MATCHes standalone, 0/137 family" to banked + 137/137. Each step is a distinct,
byte-measured fix (§94 type-carry -> return conform -> param conform -> block-scope typedef ->
inlined macro), so the ladder IS the evidence for the extract_unit carry-gap finding.
.run/near6/g734_{a,b}.c — the two placements proving cluster B is solvable and anti-correlated with
cluster A (13 -> 14 both ways, B goes 2 -> 0 while A goes 4 -> 7).
Both sets are cheap to lose and expensive to re-derive; the .gitignore allowlist already covers
.run/near6/*.c.
|
||
|
|
5d9616739a |
docs(phase-29): T47 — func_80176734 grind; cluster B SOLVED but anti-correlated with cluster A
Acted on T46's verdict (K8/RC-4 local-alloc tying, lever = C-level lifetime shaping) instead of the
refuted allocation/permuter framings.
THE LEVER WORKS. Cluster B is `q = (Trk *)((u8 *)e + 0x3C)` landing in $a2 where the target uses $a0,
because arg0's last use (`self = arg0`) sat BELOW q's birth, keeping $a0 live so K3 first-fit pushed
q to the next free reg. Moving `self = arg0` above q's birth ELIMINATES cluster B in both placements
tried -- byte-measured:
baseline A=4 B=2 C=2 D=5 -> 13
(a) self at top A=7 B=0 C=2 D=5 -> 14
(b) self after e A=7 B=0 C=2 D=5 -> 14
BUT IT COSTS 3 POSITIONS IN A, AND THE COUPLING IS ALREADY DOCUMENTED in the draft's own header:
cluster A is a sched2 LUID tie COUPLED to lever 3 -- st1 must stay a decl-initializer (moving it into
the body forfeits the update_equiv_regs live-length doubling at local-alloc.c:1064, allocno priority
explodes, callee-saved bank rotates, frame 0x40->0x48, measured over 12 permutations), while st2/ext
must sit in the body after the index chain AND the `self = arg0` copy to reproduce the target's
save/init interleave. Moving `self = arg0` is exactly the statement that interleave is anchored on.
VERDICT: a THIRD two-knobs-one-screw in this function. st1's LUID is pinned by allocno priority ->
pins the save/init interleave (A) -> pins where `self = arg0` may sit -> decides whether q gets $a0
(B). Any future attempt must optimise A and B TOGETHER; fixing either alone is provably a wash.
Not banked, nothing regressed (draft-side only, tree clean). Cluster B has moved from an unexplained
register 2-swap to solved-but-priced-at-3-positions-in-A. Variants at .run/near6/g734_{a,b}.c.
Effort ledger recorded: Fable5 pass, wave agent (~2.6M tok, 217->13), 32-min permuter (flat),
reg_renumber oracle (framing refuted), this grind. 51,198 ins; five tiers have now bounced.
|
||
|
|
3371e57ed0 |
docs(phase-29): regalloc.md §H — the swap oracle's two unstated PRECONDITIONS
§H sold the reg_renumber-swap oracle as THE one-gdb-run discriminator between RC-6 (allocation) and S3 (scheduling). It has two preconditions it never stated, and both failed silently on the first real use after the audit: 1. reg_renumber maps PSEUDOS ONLY (index >= FIRST_PSEUDO_REGISTER = 68 on MIPS, mips.h:1179). A contested register that is already HARD at .greg time — an incoming parameter reg, a pin, or a local-alloc reuse — is structurally unreachable. Check the .greg RTL first: (reg/v:SI 6 a2) with 6 < 68 does not qualify; only (reg:SI 130)-style operands do. 2. The contest must be NARROW. The swap is global across reg_renumber, so if the pair serves many pseudos it destroys the allocations that were already correct. Byte-measured on func_80176734, baseline 13: control 1<->1 -> 13 (harness validated); <-> moved 17 pseudos -> 345; <-> moved 31 -> 97. The .greg read then showed the destination was (reg/v:SI 6 a2) — hard, a reused incoming parameter register — so the true class was local-alloc TYING (K8/RC-4), not RC-6, and the lever is C-level lifetime shaping. Harness + negative control preserved at tools/oracle/reg_renumber_swap.sh. |
||
|
|
ce7780b91f |
feat(phase-29): T46 — reg_renumber-swap oracle built + validated; it REFUTES the func_80176734 framing
Item 1's remaining half. Oracle mechanized and reusable at tools/oracle/reg_renumber_swap.sh: break at reload entry (cc1 unstripped: reg_renumber @0x82d4330, reload @0x815d4d7), swap two hard regs across reg_renumber, finish the compile, re-score with masked_diff REUSED not reimplemented (R33). NEGATIVE CONTROL: a no-op swap (31<->31) reproduces exactly the baseline 13 mismatches, so the harness faithfully reproduces the pinned compile. RESULT: both contested swaps are far WORSE — <-> (17 pseudos) = 345 mismatches +1 insn; <-> (31 pseudos) = 97. Baseline 13. WHY, AND IT REFUTES THE FRAMING: reading .greg for cluster B's own insn shows (set (reg/v:SI 6 a2) (plus:SI (reg/v:SI 5 a1) (const_int 60))) — the destination is a HARD register, not a pseudo. reg_renumber only maps pseudos (>= FIRST_PSEUDO_REGISTER = 68), so that value is structurally unreachable by this oracle. The draft has NO register __asm__ pins (header says so, grep confirms), so is hard because it is an incoming PARAMETER register that local-alloc reused as a destination. VERDICT for func_80176734 (51,198 ins): the residual is NOT global-allocation 2-colouring. It is the LOCAL-alloc hard-reg reuse / tying class — combine_regs (2.7.2 local-alloc.c:1722) + qty_phys_copy_sugg, i.e. regalloc.md K8/RC-4, whose lever is C-level LIFETIME SHAPING, not the permuter and not reg_renumber. That also explains the flat permuter: it was mutating a dial that does not control this residual. MAP REFINEMENT OWED: §H presents the swap oracle as THE way to discriminate RC-6 from S3 in one gdb run. It has an unstated PRECONDITION — the contested registers must be held by PSEUDOS. Check .greg first; if they appear as (reg/v:SI N ...) with N < 68 they are already hard, and a coarse swap returns a large meaningless number (345 here) that looks like a verdict and is not one. Tree clean; nothing banked, nothing broken. |
||
|
|
5ae6409640 |
docs(phase-29): T45 — data-axis probe is a CLEAN NEGATIVE (0 of 3); the blocker is codegen
Probe-before-investing, ~15 min, settles the data axis. FIRST: I recommended a RETIRED tool. tools/reconcile_decls.py is retired (Phase 26-A, R33, "DO NOT RE-WIRE") and its docstring states the exact caveat I had raised independently — it asks what the FLEET calls a symbol, while C asks what THIS TU declares; measured, the fleet oracle conflicts with the TU's own declaration in 548/3431 (16%) of cases and hands back an actively wrong decl. Re-ran with the live successor, reconcile_tu.py. MEASUREMENT: reconcile_tu -> drafts 3, reconciled 3, 5 data symbols, 0 coverage defects. Whole-binary gate (bare harvest_verify) -> verified 0 / failed 3, class DIFF=3. Tree residue 0. WHY THIS IS NOT A NULL RESULT — THE FAILURE CLASS MOVED. Before: func_80133298/func_8012E014 were PLUMBING; after reconciliation all three are DIFF. So reconcile_tu really did dissolve the declaration conflict and the drafts still miss the bytes. func_80135260 is the witness: CC1-FAIL -> compiles at 139 ins vs target 136, 123 mismatched. Conforming its data types to what the TU can see CHANGED ITS CODEGEN. The drafts' data types are byte-load-bearing and the TU's declarations are incompatible with them: the def-side loose-typing wall in DATA form, a genuine wall not paperwork. Do not invest further in a data-axis conform for these three. INSTRUMENT NOTE: my first probe used rtu_match, which reported CC1-FAIL "redefinition of s8" for two drafts — a FALSE blocker, since rtu_match does not strip the scalar typedefs common.h provides but harvest_verify does. The authoritative gate disagreed with my probe instrument and was right. func_80135260 (18,768 ins) is re-filed: not an integration target, a CRACK target at 3 ins over. |
||
|
|
c23afcc6c3 |
fix(phase-29): SESSION-23 checkpoint — session total is 970, not 418
I wrote 418 by wrongly excluding T32/T33 (the NEAR-6 wave + its 548-member sweep) as if they belonged to SESSION-22; they ran this session. Caught by reconciling against the metric rather than trusting the running tally: fn-count 319,549 -> 320,519 = +970, and the per-task recount agrees exactly (4 + 548 + 4 + 143 + 133 + 1 + 137). Third counting slip today, and the third caught by measuring instead of asserting — the reconciliation step is earning its keep. |
||
|
|
4133a208bf |
docs(phase-29): T44 + SESSION-23 final checkpoint
T44 func_8013B83C: a MATCHING draft (272 ins) has been sitting unbanked in .run/s21_jt7/ since Session-21 — found by measuring the preserved drafts against the right target (it is an _o0 function; my first probe used the wrong asm subdir). It does NOT bank: CARVE-REFUSED (has_mid_jr, §53), and jtbl_carve then refuses because the _o0 subseg would host NON-CONTIGUOUS .rodata carves — it needs jr_isolate_all (own code subseg, whale _o0b precedent) first. Tree verified clean; the carve refused before writing. HONEST SIZING: the bank is 272 ins x1, and the 37,536 headline should be DISCOUNTED — the exemplar is _o0 while its members are -O2, and today re-confirmed _o0 families sweep ~1/137. SESSION-23 FINAL CHECKPOINT written (supersedes the SESSION-22 blocks): 418 functions banked this session, fleet 84.8->85.5% instr / 74.7->76.1% distinct / 90.34->90.61% fn-count, R22 140/140 run 7x, dedup 1886/0, 0 NON_MATCHING. Records the four strategic changes (every codegen-map file audited vs real 2.7.2; the ADDRESSING->permuter route is wrong; the bare gate beats the ladder but has no snapshot/restore; extract_unit's carry gap characterized), a ranked START-HERE list, my four errors this session, and the carried defects. |
||
|
|
6fad5d19c8 |
feat(phase-29): T43 — func_80140D68 banked + swept 137/137; the §94 extract_unit CARRY GAP characterized
The §99 conform_decls pass REFUSED this one (§85: 414 callers consume the return), so it was solved
from the DRAFT side. Three blockers, each measured:
1. §94 type-carry, and the draft's own header asserted something FALSE — it claimed both typedefs
already exist in engine_types.h. Measured: Hw4 1 hit, Prim4 1 hit, Env_800D29F8 ZERO. So in the
real TU the #ifndef guard is DEFINED and the typedef vanished -> "parse error before D_800AE7BC".
2. Signature axis: conformed the DRAFT to the fleet's declared `s32 *` return, then param 2
(s16 * -> Prim4 *). Byte-neutral because `src` is used EXACTLY once, as (s32)src. The error
("argument `src' doesn't match prototype") is again printed with NO "error:" prefix.
3. The family sweep went 0/137 TWICE before 137/137.
THE REUSABLE FINDING — a 0/N sweep whose exemplar banks cleanly is the signature of an extract_unit
carry gap. Measured on the staged member drafts:
file-scope extern -> CARRIED
file-scope #define -> CARRIED, but only while its expansion's deps stay file-scope
file-scope typedef -> NOT carried (silently dropped)
#define whose expansion references a BODY-LOCAL extern -> NOT carried
RECIPE: make the draft SELF-CONTAINED — body-local typedefs survive (PTag_80140D68 in this same
draft was the proof all along), and if that pushes a macro's dependency body-local, inline the macro
at its use sites. 0/137 -> 0/137 -> 137/137, 0 failed, each step byte-measured.
R22 clean-fleet 140 passed / 0 failed of 140; dedup-check 1886/0.
Fleet 85.5% instr, 76.1% distinct, 90.57 -> 90.61% fn-count.
§99 arc total (T41-T43): 133 + 1 + 137 = 271 functions. Both blockers Drew green-lit are CLOSED.
|
||
|
|
59785974f0 |
feat(phase-29): T41 — §99 conform_decls: func_80177DA8 family 4/137 -> 137/137 (0 failed)
Drew green-lit the fleet-shared change. One function at a time from a committed-clean baseline, dry
run first, R22 after each step — the discipline the T39 shared-state hazard earned.
- conform_decls --fn func_80177DA8 --apply: byte-true def `void func_80177DA8(u8 *p, u32 v, s32 idx)`;
268 declaration sites rewritten across 268 files; the tool's own R32 completion assertion reports
"non-canonical declarations remaining: 0 OK (axis complete)" (§85 all-or-nothing as a COUNT, not a
hope). Nothing under src/shared, config or include. R22 -> 140/140: the decl axis is byte-neutral.
- Re-sweep: BANKED 133 / 0 failed, skipped {not-stub: 4} => the family went 4/137 -> 137/137, exactly
reversing T40's failure. R22 -> 140/140. dedup-check 1886/0.
- Fleet 85.4 -> 85.5% instr, 76.0 -> 76.1% distinct, 90.54 -> 90.57% fn-count.
T42 func_80140D68 — the pass correctly REFUSED it (414 callers consume the return, so widening the
return type is not byte-neutral, §85). Diagnosed in the real TU instead (rtu_match + reading ALL
stderr per §95 — gcc-2.7.2 prints hard errors with NO "error:" prefix, so grepping for "error" finds
nothing):
1. parse error before D_800AE7BC = a §94 TYPE-CARRY defect, and the draft's header asserts something
FALSE: it claims Hw4 AND Env_800D29F8 both already exist in engine_types.h. Measured: Hw4 1 hit,
Prim4 1 hit, Env_800D29F8 ZERO. FIXED by keeping Hw4 guarded (it does exist) and moving
Env_800D29F8 outside the guard, draft-local per §100. Still MATCH (65 ins).
2. conflicting types — conformed the DRAFT's return to the fleet's declared s32 * (still MATCH).
Only remaining delta: param 2 byte-true `s16 *` vs declared `Prim4 *`. conform_decls still refuses
(its return-axis precondition fires regardless). OPEN, with the next probe named.
|
||
|
|
37e5a19558 |
feat(phase-29): T40 — sweep 143/548; the 405 failures are one named class (§99 K&R-vs-prototype)
family_sweep --hseq --band all --only <4 cores> -j12 -> 143 banked / 405 failed. R22 clean-fleet
140 passed, 0 failed of 140; dedup-check 1886/0. Fleet 85.3 -> 85.4% instr, 75.8 -> 76.0% distinct,
90.50 -> 90.54% fn-count.
Unlike T33's 548/548, this sweep mostly failed — so the failures were DIAGNOSED, not accepted:
- func_80138C60 swept 137/137 clean.
- func_8013B6A0 / func_8013B598 swept 1/137 each — EXPECTED, not a regression: Phase 20 byte-proved
the -O0 cluster is OVERLAY-LOCAL, so their siblings need per-overlay _o0 carves that do not exist.
- func_80177DA8 swept 4/137 — ROOT CAUSED: its banked def is K&R and its own TU declares it no-proto,
but NON-SC07 overlays declare a PROTOTYPE (extern void func_80177DA8(s32,s32,s32)), so the remap
conflicts. The 4 successes are SC07 overlays, which declare it not at all.
THE SYNTHESIS: that is the SAME §99 K&R-vs-prototype class as item 3's func_80140D68 (K&R def vs 138
prototype callers). ONE conform_decls pass unlocks both — ~17,000 instructions. conform_decls exists
for exactly this ("the draft's signature is byte-TRUTH; move the DECLS, never the draft"). NOT run:
it is a fleet-shared 138+-declaration change and this session already tripped one shared-state
hazard, so it wants an explicit go-ahead (P5).
MY ERROR, recorded: I read a `head -6` list of modified dirs as the complete set and briefly thought
the sweep's count did not reconcile. Measured properly it does — 143 stubs removed across 142 files.
Same class as grepping the wrong field earlier today: truncated output is not exhaustive output.
|
||
|
|
c06f5f1e4e |
feat(phase-29): T39 — items 1-4; 4 reach-138 cores banked, the bare gate beats the ladder
Worked Drew's order 1->2->3->4 at xHigh (no fan-out). ITEM 1 func_80176734: permuter COMPLETELY FLAT at 13 (8 cycles x 240s, regalloc profile chosen over the classifier's cse because the residual is 3 register 2-swaps). Not one improving waypoint in 32 min. THIRD ADDRESSING-bucketed target in a row where the permuter under-delivers (11->7, 10->6, now 13->13 flat) — the T31 routing finding is now well evidenced. Remaining: the reg_renumber-swap gdb oracle; feasibility confirmed (cc1 unstripped, reg_renumber @0x82d4330, prior-art .gdb exists) but it needs a .greg pseudo-identification pass, so not started. ITEM 2: 4 of 7 banked — func_80177DA8, func_8013B6A0, func_8013B598, func_80138C60. THE BARE GATE WAS THE UNLOCK: gate_stage reported failed:2 on the _o0 pair while bare harvest_verify reported verified 2/failed 0 on the SAME drafts, and rtu_match independently confirms func_8013B6A0 matches in the real TU. That gives the carried "ladder-vs-bare-gate asymmetry" defect a REPRODUCTION — the ladder is destroying good drafts, not diagnosing them. All 4 are reach-138 PURE families = 35,604 templatable instructions. SHARED-STATE HAZARD hit and repaired: the failed func_80135260 attempt left fix_arity_callers --any-proto edits in 17 TUs holding none of my banks (the bare gate has no snapshot/restore, unlike the ladder after the Task-14 incident). Caught by diffing the tree, not by the tool's report. Reverted the 17, kept the 3 bank-bearing files, re-verified R22 clean-fleet 140/140. Nothing under src/shared, config or include was touched, so blast radius was ov_SC01_077-local (§63). ITEM 3 func_80140D68: fails even bare-gated, and the PREDICTED CAUSE WAS WRONG — there is no DEFINE_func_80140D68 macro. Real conflict is §99 K&R-vs-prototype: draft is K&R `u32 *`, 138 callers declare `extern s32 *func_80140D68(s32 *, Prim4 *, s32, s32, s32);`. Lever exists (§99 did this at 1,072-decl scale today) but it is a fleet-shared 138-decl change. Scoped, not attempted. ITEM 4 func_80178004 biv-init wall: RE-PROBED and UPHELD — my own hypothesis refuted. The cited mechanism (loop.c:3803/3823, benefit->0 eliminates emit_iv_add_mult) is verbatim present in real 2.7.2 inside strength_reduce (3214); loop.md's flagged version difference is in combine_givs, which this verdict does not rest on. The wall stands. |
||
|
|
b885acf676 |
docs(phase-29): T38 — fix expr.c:5535 (and the second wrong cite beside it)
Derived the correct lines myself AND had an independent agent derive them separately — warranted after two stacked line-number errors earlier in the session. Both derivations agreed exactly. - expr.c:5535 -> 4577 (guard 4570-4576), case INDIRECT_REF: @4540, expand_expr @4026. 5535 is a gcc-2.8.1 line; in our 2.7.2 it is MIN_EXPR/MAX_EXPR optab code. - expr.c:5891 -> 4888, case COMPONENT_REF: @4748. THIS SECOND CITE WAS ALSO WRONG and had not been noticed: 5891 lands in case COND_EXPR: (jumpifnot/cleanups). Two precisions from the independent derivation, folded in rather than dropped: - the INDIRECT_REF guard is a 4-WAY OR, not a single test (SAVE_EXPR-wrapping-PLUS, aggregate-typed deref, and ADDR_EXPR-of-aggregate also grant /s), so "only when top-level PLUS_EXPR" was too strong. The cast-defeats-/s rule is now bounded to a scalar-typed deref through a plain pointer — which is the case the idiom is actually about. - a SECOND MEM_IN_STRUCT_P (op0) = 1 at 4873 is conditional (BLKmode bitfield, returns early at 4876) and is NOT the one meant — flagged so it is not cited by mistake. Old cites struck not deleted (H5); the top-of-file provenance note corrected (it named 4904, which is the OFFSET_REF grant — a real third site but not this idiom's). Tool limitation recorded: sweep_citations.py cannot tell a live cite from a struck-through historical one. Docs-only: no src/ or config/ touched; R22 not re-run and not claimed. |
||
|
|
86caa7dfdb |
fix(phase-29): T36/T37 — my checker had a FORM-FEED bug; the "12 fabricated" were mine, not the agents'
T36 CORRECTION (the important half). Building the cookbook sweep tool surfaced a defect in
tools/verify_map_findings.py, which I had already used to validate BOTH map audits:
- GNU C sources use FORM FEED (\f) page separators — loop.c 47, cse.c 36, reload1.c 27,
local-alloc.c 21. Python's splitlines() splits on \f; grep/sed do not. Every line number computed
after the first \f was shifted (up to 47 in loop.c), which is LARGER than the checker's own +/-40
window — precisely how a real quote gets reported FABRICATED.
- Re-run after the fix: T34 regalloc 27 OK/153 NEAR/0 FAB -> 180 OK/0/0. T35 four-file
47 OK/240 NEAR/12 FAB -> 299 OK/0/0. THE AGENTS' LINE NUMBERS WERE EXACT ALL ALONG. I had even
written the false "off by +2..+19" claim into the T35 agent prompt.
- MY DIAGNOSIS OF THE 12 WAS ALSO WRONG. I said agents pasted map prose into source_quote and
"verified" it by grepping — but I grepped claim_excerpt (which IS map prose) instead of
source_quote. The real source_quote was ` record_jump_equiv (insn, 0);` at cse.c:7511, a
correctly-located C line. Two stacked errors: a broken tool, then a check of the wrong field that
appeared to confirm it.
- Fixed: both tools use split("\n"); verify_map_findings.py documents the trap so it cannot return;
loop.md's "12 unverified" note is WITHDRAWN in place. Nothing was deleted on this basis (all 12
were CONFIRMED-status, none underpinned a refutation), and the T34/T35 upheld/overturned splits are
unaffected — those came from adversarial agents, not the checker.
T37 THE COOKBOOK SWEEP (what was asked for). New tools/sweep_citations.py puts the mechanical half of
a citation audit into zero-token tooling (offline-tooling-first): symbol-form cites are compared to
the real 2.7.2 definition line; file-form cites are localised to their enclosing function.
- matching-cookbook.md: 57 resolvable citations, all localisable. MIXED provenance but mostly sound —
materially better than the map files. loop.c:5556, local-alloc.c:1765/1795/1825, global.c:906/917/
924/1000, local-alloc.c:1021/1064, global.c:588/594, sched.c:820, expmed.c:556, jump.c:2131 all
land where the prose says. GENUINE MISS: expr.c:5535 is MIN/MAX optab code; the /s grant sites are
4577 and 4904.
- STATED LIMITATION: "lands in the right function" is weak for giants (expand_expr 4026->~6300,
jump_optimize 139->~2200). This is a CITATION sweep, not a claim audit — proportionate because the
cookbook's idioms are byte-proven and its cites are explanation. No idiom re-litigated.
Docs+tools only: no src/ or config/ touched; R22 not re-run and not claimed.
|
||
|
|
ce8f7629ae |
docs(phase-29): T35 — the last 4 codegen-map files audited vs real gcc-2.7.2
Scope enumerated before acting: cse_expr.md, loop.md, sched.md (full pass — T33 landed only a partial), t7g-giant-harvest.md. 35 agents (9 derive + 26 adversarial refute), 2.48M subagent tokens. 308 findings: 174 CONFIRMED / 99 LINE-DRIFT / 26 REFUTED raised -> 20 UPHELD, 6 OVERTURNED / 9 unverifiable. cse_expr.md had the highest error density (17 refuted of 74); loop.md the lowest (3 of 96) thanks to its pre-existing caveat table. 12 FABRICATED (vs 0 last audit) — DIAGNOSED, not waved through: the agents pasted MAP text into the source_quote field instead of compiler source. All 12 are CONFIRMED-status and none underpins an upheld refutation, so nothing was deleted on bad evidence — but they are UNVERIFIED, they sit in loop.md's biv-elimination area, and loop.md now records that as an open gap rather than a pass (R32). Headline corrections: - cse_expr: THE 1000-INSN CSE FLUSH DOES NOT EXIST IN 2.7.2 (added in 2.8.1; grep num_insns -> no hits). It drove THREE places — §1's killer table, §6's giant tell, §7's "shift +-insns across the 1000 boundary" lever. A lever aimed at a counter our compiler lacks, in exactly the giants this map serves. All struck. - cse_expr: §2's "kill THE class reg" is singular and wrong. The audit BYTE-REPRODUCED T31's wall on the pinned cc1: expand_block_move (mips.c:2350-2351) copy_addr_to_reg's BOTH aggregate addresses. Two byte-proven remedies recorded, with the caveat that field-by-field copy is closed when the target's own bytes need the block move (func_80132F40's case). - cse_expr: assign_temp absent in 2.7.2 and no /s reset on slot reuse (recycled slots INHERIT /s); no BUILT_IN_MEMSET; §6's "recompute after a join is never a residual" false at -O2. - sched: S7's EPILOGUE half false (no live define_expand "epilogue" on MIPS) — re-scoped not deleted; insn_cost is DEP-KIND-BLIND so restoring /s anti edges is not free. - loop: "no memory load is EVER hoisted from a loop containing a call" FALSE — invariant_p checks RTX_UNCHANGING_P first; byte-proven that a const int* load hoists to the preheader. Call args are emitted LEFT-to-right, not right-to-left. Remaining: matching-cookbook.md (~52 citations, MIXED provenance) — but a DIFFERENT risk profile, since its idioms are byte-proven and citations are explanation, so a targeted citation sweep is proportionate rather than a full audit. Not done; flagged. Docs-only: no src/ or config/ touched, R22 not re-run and not claimed. |
||
|
|
7acd0c4e2a |
feat(phase-29): tools/verify_map_findings.py — the codegen-map audit fabrication check (R3)
Moved out of .run/ (where the blanket ignore would have lost it) into tools/ per R3, and generalised
from regalloc to any docs/gcc-2.7.2-map/* audit.
The check an LLM audit of a source-derived document cannot do for itself: agents return
{real_file, real_line, source_quote}; this re-opens each file at each line and compares the verbatim
quote to what is actually there. Whitespace-normalised, +/-40-line search window, and it reports
NEAR (quote real, line wrong) SEPARATELY from FABRICATED (text appears nowhere) — because with the
2.8.1->2.7.2 drift reaching +611 lines in reload1.c, a wrong lookup lands INSIDE A DIFFERENT FUNCTION
and every sentence built on it still reads plausibly.
Used on the T34 regalloc.md audit: 184 findings, 0 FABRICATED.
|
||
|
|
79c327b2a2 |
docs(phase-29): T34 — regalloc.md re-derived vs real gcc-2.7.2; 7 corrections, 14 false alarms caught
26 agents (5 derive + 21 adversarial refute), 1.73M subagent tokens. Two guards, because a false REFUTED deletes a working lever and is worse than a stale line number: - MECHANICAL FABRICATION CHECK (.run/verify_regalloc_findings.py, NEW): every claim had to carry a verbatim source_quote + file + line; I re-opened each file at each line and compared. 184 checked, **0 FABRICATED** (27 exact, 153 NEAR = quote real but line arithmetic off by +2..+19, 4 declared unverifiable). Distinguishes NEAR from FABRICATED because the 2.8.1->2.7.2 drift (+300..+600 in reload1.c) can land a lookup inside a DIFFERENT function and still read plausibly. - ADVERSARIAL SECOND STAGE: every REFUTED claim went to an independent agent told to refute the refutation, defaulting to upholding the map. **Of 21 REFUTED, 14 OVERTURNED, 7 stand.** The raw audit output would have deleted 14 CORRECT levers (RC-6's verdict, the decoy-qty lever, the <=3-qty creation-order rule, the keepalive-read lever). FINAL: 119 CONFIRMED / 40 LINE-DRIFT / 7 REFUTED-upheld / 4 UNVERIFIABLE. The model is sound. The 7, marked [A23] inline: 1. K4 flag_caller_saves is ON (toplev.c:3387-3394 at -O2), BYTE-PROVEN on the real cc1 — a call-crossing value is not confined to $s0-$s7-or-spill. Added the missing diagnostic: caller-save slots are 4-BYTE-PACKED vs reload spill slots 8-ROUNDED (misreading one as the other sends you to RC-1 + decl reordering, the wrong lever entirely). 2. RC-7's premise false: a frame address is never CONSTANT_P (rtl.h:237-240 excludes PLUS), so it gets a real slot + lw. THIS EXPLAINS T31's byte-tested failure today — cse_expr.md §2's remat recipe could not dissolve func_80132F40's hoist (47->40, never 0) because the promised mechanism does not apply to frame addresses. Independent audit and live byte-test converged. 3. The "init MOVED to just before its use" pass is 2.8.1-only; 2.7.2 deletes the init instead. 4. K2 refs are LOOP-DEPTH-WEIGHTED (reg_n_refs += loop_depth), not per-insn-mention. 5. K1 qty numbers come from BIRTH order, not regno order. 6. RC-15/K2: allocno_live_length is the DENOMINATOR — priority is a density. 7. Pins do NOT kill the S2 boost — independently reproducing yesterday's sched.md finding from a different agent/section, plus the decisive detail that sched.c:423 DOES add the pseudo guard where it wants one, so the omission at :2478 is deliberate. NOT applied: the 40 LINE-DRIFT fixes wholesale — generic quotes match several places, so publishing all 40 risks replacing 2.8.1 drift with fresh 2.7.2 drift. Header carries 12 hand-verified anchors + an instruction to grep before citing. Struck text preserved, not deleted (H5). Docs-only: no src/ or config/ touched, R22 not re-run and not claimed. |
||
|
|
46870139bd |
feat(phase-29): T33 — 548/548 family members banked (0 failed); fleet 84.8 -> 85.3% instr
- family_sweep --hseq --band all --only <4 cores> -j12 -> BANKED 548 member-matches / 0 failed
across 137 overlays. Preconditions CHECKED not assumed: map regenerated first (sig-overlays +
family_hseq) so the exemplars read matched-ov077 not the stale draft-ov077; all 4 families
has_mid_jr=false (§53 carve law) and diff_class PURE 137/137; --band all because two cores are
`mid` and the default `substantial` band would have silently dropped them; --reconcile-raw avoided.
- R22 clean-fleet after the sweep: 140 passed, 0 failed of 140. dedup-check 1886 validated / 0
failed, C1 coverage 239604/239604, 0 NON_MATCHING in any default build (G4).
- SESSION ARC: instr 84.8 -> 85.3%, distinct-code 74.7 -> 75.8%, fn-count 90.34 -> 90.50%.
552 functions banked (4 exemplars + 548 members) ~= 74,802 templated instructions.
- sched.md SOURCE-VERSION CORRECTION: the map declares its source as gcc-papermario, which Phase 23
established is gcc 2.8.1 — not our 2.7.2 — and it was never re-derived. Citations are correct for
the WRONG compiler. One claim is byte-refuted and load-bearing: §1.7/§S12 said the S2 birthing
boost needs SET(REG_pseudo,...) so pins must be removed ("Unpin first"); real 2.7.2
birthing_insn_p (sched.c:2469) tests only GET_CODE(SET_DEST)==REG with NO pseudo check and gates on
reg_n_sets==1 (2490) — hard-reg dests ARE boosted. Corrected in place (old text struck, not
deleted) + a hand-verified 2.7.2 cross-reference table and a warning block.
DRIFT IS NOT UNIFORM: ~+27 in sched.c but +103/+377/+611 in local-alloc.c/reload1.c — big enough to
land inside a different function. ~44 drifted citations across sched/regalloc/loop .md (a screen,
a lower bound). regalloc.md is worst and is NOT yet re-derived — named as next.
- All line numbers verified by me against tools/reference/gcc-2.7.2, not taken from the agents.
|
||
|
|
05430eb26e |
feat(phase-29): T32 — NEAR-6 crack wave banks 4 reach-138 cores ×1; R22 140/140
Ultracode fan-out (12 agents, 1.70M subagent tokens): 6 crack agents, one per NEAR target, each carrying its byte-measured residual + T31's disproved routes, then a distill agent per target that adversarially re-checks the claim. - BANKED ×1 (whole-binary gate, gate_stage --no-propagate per §55b law 1): func_80140958 (260 ins), func_80177B5C (147), func_80132F40 (72), func_8012E364 (67). Every agent MATCH claim was RE-MEASURED BY ME with match_one before it was believed (G3/P9: match_one is a candidate, a bank is the whole-binary gate), and verified against the SOURCE not gate_stage's accumulating verified-list (§55b trap 4). R22 clean-fleet: 140 passed, 0 failed of 140. - engine_core.h moved by exactly one byte-neutral arity fix (void -> no-proto) = fleet-shared, so R22 was mandatory (§61/§63), not the per-binary gate. - func_80140D68 MATCHes standalone but NOT whole-binary — the §30a integration class; its distill agent named the likely cause in advance (DEFINE_func_* extern must return u32*, not void). - func_80176734 217 -> 13 with the instruction count now EXACT (371/371). cse_expr.md §H's "no bank, 5 permuter-shaped clusters" is BYTE-REFUTED: 4 of 5 were steerable from C; the -1 length delta was a combine/LOG_LINK effect (flow.c links a SET only to the next use in the SAME bb), not frame pressure. Two coupled allocator/sched ties survive. - FOUND: docs/gcc-2.7.2-map/sched.md cites gcc-2.8.1 line numbers (birthing_insn_p 2498->2469, adjust_priority 2534->2507, potential_hazard 1345->1318, schedule_select 2646->2616) — surviving papermario numbers Phase 23's source-version correction never swept. One is LOAD-BEARING: §1.7 and §S12 claim the S2 boost needs SET(REG_pseudo,...) so pins must be removed; sched.c:2477 tests only GET_CODE(SET_DEST)==REG with NO pseudo check, discriminator is reg_n_sets==1 (2490). Verified by me against tools/reference/gcc-2.7.2, not taken from the agents. Map edits owed (next task). - MY DEFECT: all 6 agents shared one scratch dir (1,452 files); deliverables are uniquely named and verified intact, but short-named scratch could collide. Per-agent subdirs next wave. |
||
|
|
e6e059a286 |
docs(phase-29): T31 — the 6 wave NEAR measured; 2 improved, 0 banked; the ADDRESSING route is the finding
NOTHING BANKED — no draft reached closeness 0. Recorded as such (P9). No src/ or config/ change, so the fleet is untouched at HEAD's verified 140/140; R22 deliberately NOT re-run and NOT claimed. - VERIFIED the checkpoint's six closeness numbers against the bytes (R14/R35): 217/10/11/6/7/9 all reproduce EXACTLY through match_one --json, with asm_subdir/-O0 DERIVED from wave22_targets.json rather than guessed. All six are reach-138 cores = ~135,516 templated ins (~1.04pp) if cracked. Reproducer .run/near6_measure.py. - PERMUTER (only 2 of 6 are §60a-admissible): func_80177B5C 11->7, func_80140958 10->6, both re-measured with match_one — an oracle INDEPENDENT of the permuter's scorer (R34) — agreeing exactly. Both plateaued after cycle 1. Seeds preserved + allowlisted. - THE FINDING: residual_class routes ADDRESSING -> permuter, but gcc-2.7.2-map/cse_expr.md §2 documents that exact class (hoist-vs-remat) as STEERABLE by a byte-proven C recipe. The tool spends CPU searching for what the map says has a deterministic fix, and both ADDRESSING targets plateaued exactly as that predicts. R35-shaped instrument defect, not a compiler wall. - NEGATIVE RESULT, byte-tested on func_80132F40 (6 variants): the §83d CSE fork is REAL (s32 fixes the min-block opcodes but hoists &v[0] into a 5th callee-saved reg, 47 mism), and the §2 kill moves it (47->40) but does NOT dissolve it in 3 placements. §2 has an unstated boundary: proven where the address's only uses are call arguments; a STRUCT-COPY source address survives the kill. close=6 (s16) remains the best known state — the wave agent's verdict, independently re-earned. - NEW DIAGNOSIS: func_80140958's post-permuter residual is not scheduling — my draft CONSTANT-FOLDED a loop value the target keeps live (li v0,3 / li a3,3 / li t3,12 vs addu/sll from $v1). Untried. - NOT SPENT, deliberately: func_80176734 (already a no-bank Fable5 pass, §H), func_80140D68 (~200 compiles already), func_8012E364 (~2500 variants already). - tools-health exit 0 (green, fail-closed) at preflight. |
||
|
|
72e6a096ca |
chore(phase-29): preserve the wave22 unbanked drafts + the regenerated family map
CAUGHT BY VERIFYING THE CHECKPOINT INSTEAD OF ASSERTING IT. `.run/wave22/` was covered by the blanket `/.run/*` ignore, so the 13 UNBANKED drafts — 6 NEAR with precise residual diagnoses and 7 that reached match_one MATCH but did not bank whole-binary — existed only on disk. My own checkpoint's "START HERE" list names them as next-session fuel, and they cost ~2.59M subagent tokens to produce. One `git clean -fdx` would have destroyed them: exactly the exposure the .run/giants Fable5 cracks had before Phase 27 curated them (R20). Now allowlisted: .run/wave22/*.c + .run/wave22_targets.json (the per-target canonical callee/data declarations resolved from the real TU scope — the §17a-1 lever the wave was built on). Also commits docs/family-hseq.md, regenerated by this session's family_hseq runs. |
||
|
|
26c6f50c52 | docs(phase-29): SESSION-22 final checkpoint — wave22 complete, 1,787 functions banked, fleet 84.8% instr | ||
|
|
75bed15697 |
feat(phase-29): func_80171B4C family banked 137/137 — wave22 complete (690 functions)
137/137 banked via jtbl_family_bank (jr family, carve-aware path). R22 clean-fleet 140 passed / 0 failed of 140. MEASURED: fn-count 319,412 -> 319,549 (+137); instr-weighted 84.7 -> 84.8% (+9,590 ins); distinct-code 74.5 -> 74.7% (+130 unique fns). WAVE22 COMPLETE: 18 targets drafted (12 MATCH / 6 NEAR / 0 FAIL, 2.59M subagent tokens) -> 5 exemplars banked -> 685 members swept -> 690 functions total. This commit stages config/ EXPLICITLY. Twice today I omitted it and left a carve uncommitted, both times caught by jtbl_family_bank's dirty-tree precondition rather than by me or any gate. |
||
|
|
a8c0f83528 |
fix(phase-29): commit func_80171B4C's carve config — SECOND incomplete change set today
Same error as commit commit:1103 this morning, which I recorded as a lesson and then repeated: I scoped `git add` to src/ and docs and omitted config/, leaving the jtbl carve that func_80171B4C's bank depends on (its `- [0x499f4, c, …]` split + `.rodata` carve + the JTBL_INTERLEAVE order) uncommitted. harvest_verify KEEPS a carve on success, so it is part of the banked state, and the R22 140/140 I reported was verified WITH these files present. Caught by jtbl_family_bank's dirty-tree precondition again — not by me, not by any gate. That is now twice in one session that a tool's precondition was the only thing standing between a partial commit and a broken HEAD. THE REAL LESSON, and it is not "be more careful": a scoped `git add` is an UNVERIFIED ASSERTION about a change set's boundary, and nothing in this project checks it. R32 says a claim like that needs an assertion. The concrete guard: before committing banked work, `git status --porcelain config/` must be empty or its contents must be part of the same commit. Recorded for the next session rather than bolted on at the end of a long one. |
||
|
|
687d761bde |
feat(phase-29): wave22 families swept 548/548 (R22 140/140) — parallel gating proven at scale
4 families x 137 members: BANKED 548 / 0 failed. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,859 -> 319,412 (+553); instr-weighted 84.4 -> 84.7% (+36,640 ins);
distinct-code 74.4 -> 74.5% (+134 unique fns).
TODAY'S PARALLEL GATE WIRING PROVED AT SCALE: this run reported `gating 411 group(s) across distinct
binaries, -j12`. When I shipped it earlier I could only smoke-test 4 fail-fast groups and said
explicitly that the 1.5x measured there was NOT the 8-16x claim; 411 full build-and-gate cycles is
the shape the claim was about.
A PERFECT 548/548 also says the wave's exemplars were right for the right reasons — a body that
templates across 137 byte-variant siblings with zero rejections is not a marginal match.
BAND NOTE: the first sweep attempt used --band substantial and staged NOTHING; these exemplars are
60-76 ins, i.e. the MID band (substantial is >=80). The tool reported that honestly
("0 matched-exemplar families (band=substantial); 0 candidate members") rather than returning a
clean-looking 0 banked — the skip-vs-result distinction this session kept running into.
|
||
|
|
599a33c056 |
feat(phase-29): wave22 — 5 exemplars banked from an 18-target Ultracode wave (R22 140/140)
THE WAVE: 18 h_seq family exemplars (~255k templated instructions), one agent each, drafting from
cached Ghidra-C + the target .s with canonical callee/data decls resolved from the real TU scope.
Result 12 MATCH / 6 NEAR / 0 FAIL (2.59M subagent tokens). No agent touched the tree — the
draft-only constraint held (verified: git status clean across src/config/tools/include).
BANKED 5: func_80148E54, func_80171B4C, func_8014A738, func_8012A328, func_80163534.
R22 clean-fleet 140 passed / 0 failed of 140.
A BUG I INTRODUCED EARLIER TODAY, FOUND BY WORKING THE 12->5 GAP. My block-scope descent in
reconcile_tu fed ordinary STATEMENTS to cdecl.parse; some parse without raising into a declarator
with an EMPTY base type and the statement's symbol as its name. That fake row overwrote the genuine
plan entry for the same symbol, so the span rewrite landed on a statement instead of the declaration
— and my own R32 completion assertion still PASSED, because the conformed text appeared somewhere.
Byte-witnessed on D_80126B5C: planned twice ("draft 's32'" and "draft ''"), output unchanged, gate
PLUMBING. Now block-scope rows are accepted only from a real `extern` with a non-empty base type.
TWO BANKS CAME FROM TODAY'S OWN FINDINGS:
- func_8012E014's single 0-arg call site took --cast-zero-arg-calls (built this morning for
func_801789AC's 138 sites).
- §99 HELD A THIRD TIME: K&R conversion dissolved func_80163534's s32->u16 narrowing across 1,072
declarations, leaving only a caller-neutral pointer change on the last param.
STILL UNBANKED (measured blockers, not guesses): func_8013B6A0 + func_8013B598 CC1-FAIL in the _o0
split; func_80133298 + func_80135260 + func_8012E014 genuine DIFF (match_one MATCH did not hold
whole-binary = TU-context); func_80138C60 parse-order (an extern referencing a body-local typedef
declared after it); func_80177DA8 prototype-vs-K&R mismatch.
|
||
|
|
8479c4491e |
fix(phase-29): scope_data_externs DROPS a data extern the TU already declares (SC07 type-identity blocker)
THE BLOCKER: the SC07 quartet (ov_SC07_006/007/010/011) refused two families with
`conflicting types for D_800AF634`. Both sides read `S_AF634 []` — the SAME type STRING — so it is a
type-IDENTITY collision: the templated body carries its OWN block-scope `typedef struct {…} S_AF634;`
while the TU's declaration of D_800AF634 comes from a MACRO-INJECTED one (§8c), making two DISTINCT
types with one name. cdecl.compatible cannot see this and correctly answers "compatible".
THE FIX: if the TU already declares the symbol above the insertion point, DROP ours instead of
keeping it. A redeclaration we do not emit cannot collide — with anything, identity or type — and the
TU's own declaration is in scope and authoritative. Strictly better than the previous behaviour,
which was a hard compile error; the whole-binary byte-gate still arbitrates if the TU's type implies
a different access.
AND IT HAD TO REACH BLOCK SCOPE, not just column 0. §8d demotes these externs on the way in, so by
the time a sibling draft is STAGED they are already indented — a col-0-only scan (my first cut) saw
nothing to do on exactly the drafts that needed it. C requires a block-scope `extern` to agree with a
file-scope declaration in scope, so a redundant redeclaration conflicts at ANY scope.
VERIFIED on the failing member: D_800AF634's declaration is removed from the staged draft, and the
re-sweep's error moved past it. HONEST STATUS: the quartet is NOT yet banked — the next conflict is a
FUNCTION decl (`conflicting types for func_80024054`), a different axis (§58c / cast_call_sites)
which the sweep's member staging does not currently run. Not peeled further here: §95's law says
splice once and dump EVERY cc1 error rather than one per gate cycle. Tree clean, nothing banked.
|
||
|
|
58d191f934 | docs(phase-29): item 4 — SC07 quartet is a type-IDENTITY collision (same type NAME, distinct types), fix is to drop the draft's redundant decl | ||
|
|
daec0e9f54 | docs(phase-29): --span-tables archaeology solved T26's blocker; _o0 table starts reconstructed (0x801D82FC/0x801D836C), residual is §8e layout | ||
|
|
d109f591f9 | docs(phase-29): item 1 — grinder 4 wins/2 banked (reach-1, R22 140/140); its targeting census is the real result | ||
|
|
5e701049d6 | feat(decomp): grinder gate — +1 fns x0 propagated (fleet 84.4%) | ||
|
|
1300f07a82 | feat(decomp): grinder gate — +1 fns x0 propagated (fleet 84.4%) | ||
|
|
cd0f595bbd | docs(phase-29): item 3 — PLUMBING census re-verdicted; 7/10 banked, 3 true verdicts measured (§102 confirmed twice) | ||
|
|
01bfa24a40 | docs(phase-29): func_8013BD74 root-caused — _o0 has no tables= record, needs the --span-tables archaeology | ||
|
|
55cd894024 |
perf(phase-29): family_sweep gates groups in PARALLEL by default (the SESSION-20 adapter, finally wired)
SESSION-20 measured serial family-sweep gating as "roughly an 8-16x throughput loss on a 32-thread box" and BUILT tools/sweep_parallel.py for it — but only reachable via a manual `--stage-only` two-step, so this path stayed serial and three sweeps in SESSION-22 (133 + 273 + 137 members) ran serially for no reason. §101, the stale-default class. SHAPE OF THE CHANGE — deliberately minimal after two failed attempts earlier today. A parallel PRE-PASS (phase 2a) runs only the per-group `harvest_verify` subprocess; phase 2b then consumes the results IN THE ORIGINAL SERIAL ORDER, so every line of post-processing (the MISMATCH backstop, the zero-bank restore, the counters, the prints) is untouched and output stays deterministic. No closure restructuring — that is exactly what broke it twice before. SAFETY, not a new claim: the Makefile already builds binaries concurrently (check-all/extract-all use `xargs -P$(JOBS)`, JOBS=16) and bulk_harvest's farm does the same with a per-binary lock. The §28 hazard is two makes racing on the SAME artifacts, prevented by the per-overlay lock (two splits of one overlay build the same binary and therefore serialise). NEGATIVE-CONTROLLED BOTH WAYS: `--stage-only` stages identically under -j1 and -j12 (4 groups each); a full gate returns IDENTICAL tallies (0 banked / 4 failed) parallel vs serial; tree clean after both. HONEST MEASUREMENT: on the only sample available (4 groups, and they fail FAST on a compile error rather than running full builds) parallel was 4s vs serial 6s — ~1.5x, NOT the 8-16x. That figure needs a large family (137 groups of full builds) to show, and every such family was already banked today. The wiring is proven correct here; the throughput claim remains SESSION-20's measurement, not mine. `-j 1` restores the old behaviour. |
||
|
|
5f6af56c2b | docs(phase-29): items 1+2 diagnosed — func_8016EC0C is permuter fuel behind a masking PLUMBING verdict; func_8013BD74's Error 1 is the §59(3) pad-spec drift | ||
|
|
bb2195b97e | docs(phase-29): §102 — a PLUMBING verdict can mask a DIFF; K&R byte-neutrality must be measured | ||
|
|
ee4bd50a3c | docs(phase-29): SESSION-22 final checkpoint + cookbook §101 (the stale-default class) | ||
|
|
2863acb83c |
feat(phase-29): func_80175DA8 0/137 -> 137/137 by moving ONE typedef into the body (§100)
Its 0/137 was the §94 TYPE-CARRY signature: the draft defines `typedef struct {…} Sp_80175DA8;` at
FILE scope, and remap_hseq templates the BODY but not the type, so every sibling compiled without it.
§94's remedy is the shared engine_types.h lift (right for func_8016B6BC, whose four types were
transitively referenced). But the cheap remedy was already in the same draft: it carries S_AF634 at
BLOCK scope and that templates fine, because a type declared in the body travels WITH the body.
Sp_80175DA8 is used by that function ONLY (7 mentions, 6 inside the body, 0 elsewhere), so moving it
into the body is byte-neutral (d19c9580 unchanged), T0, zero blast radius — versus editing a header
included by 140 binaries with uniquify/collision care and an R22.
Re-swept: 137/137, 0 failed. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,720 -> 318,857 (+137); instr 84.2 -> 84.4% (+31,647 ins); distinct-code
73.9 -> 74.4% (+129 unique fns).
§99 AND §100, AN HOUR APART, ARE THE SAME LESSON: both times the cookbook's named remedy was the
expensive fleet-wide one (524-site decl conform / shared-header lift) and the correct fix was
DRAFT-LOCAL (K&R definition / block-scope typedef). Before editing anything shared, ask what the
smallest scope is that still travels with the body.
|
||
|
|
ab065b1646 |
fix(phase-29): sweep pinned exemplars BY DEFAULT — the §42e guard's cause was removed in Phase 27
The guard skipped any exemplar carrying a `register __asm__("$N")` pin because templating it
cc1-CRASHED the sibling TUs (§42e). Phase 27 BYTE-PROVED that SIGABRT was `extract_unit` dropping the
body's file-scope macros — OUR bug — and fixed it (_carry_macros); its own roadmap delta then put the
PINS class "back on the mechanical-harvest table". The cause was removed and the default never
changed, so the guard kept skipping real work.
MEASURED THIS SESSION on one family: func_80175AB8 reported `skipped {'pinned-exemplar': 137}` and
then banked 133/137 the moment it was bypassed (R22 140/140). A protection whose cause is gone is not
free — it is a silent skip (R32) wearing a safety label, and the whole-binary byte-gate was always the
real arbiter here.
--allow-pins kept as an accepted no-op so existing recipes/docs keep working; --no-pins restores the
old behaviour. Negative control: --no-pins still reports `pinned-exemplar: 4`; the default stages them.
This is the THIRD stale default found today, after sweep_parallel being opt-in (8-16x throughput left
on the table) and conform_decls refusing a remedy it could perform. Same shape each time: correct when
written, cause since removed, still the default, opt-out only if you remember the flag.
|
||
|
|
a884d5f5d6 |
feat(phase-29): func_80175AB8 swept 133/137 via --allow-pins — a STALE GUARD was skipping them
The first sweep returned "banked 0 / skipped {'pinned-exemplar': 137}" — a SKIP, not a failure. The
§42e guard refuses pinned exemplars to avoid a cc1 SIGABRT, but Phase 27 BYTE-PROVED that crash was
extract_unit dropping file-scope macros (a TOOL bug, fixed by _carry_macros), not a compiler limit.
Re-run with --allow-pins: 133/137 BANKED. R22 clean-fleet 140 passed / 0 failed of 140.
MEASURED: fn-count 318,585 -> 318,720 (+135); instr 84.0 -> 84.2% (+25,423 ins); distinct-code
73.4 -> 73.9% (+127 unique fns).
THE GUARD IS NOW COSTING BANKS — the same shape as sweep_parallel being opt-in: a protection that was
correct when written, whose cause was later removed, still defaults ON. Measured cost on ONE family:
137 skipped, 133 bank fine. Phase 27's roadmap delta already said the PINS class was back on the
table; nothing changed the default. Flipping it is a one-line change, deliberately deferred to a
fresh session — that is exactly how family_sweep got broken twice today.
SC07 QUARTET, third occurrence today, now named: ov_SC07_006/007/010/011 refused again (same four as
func_80176218). NOT broken — func_8014CF04, func_8015D1B8 and func_801789AC all swept them cleanly.
The correlation is the sibling TU (_jr_8016AE5C.c, a different carve layout; these 4 were onboarded
in Phase 27 with code at PAC entry 1). §59: read ONE sibling's real gate result before concluding.
func_80175DA8 0/137 is the §94 TYPE-CARRY signature (local typedef Sp_80175DA8 templated as a body
but not as a type) — the same shape that took func_8016B6BC 0/137 -> 137/137 today. Named next step,
31,878 templated instructions.
|
||
|
|
5f1fc5b5eb |
feat(phase-29): caller pair banked (57,822 templ ins) via K&R defs — §92's remedy corrected (§99)
func_80175AB8 + func_80175DA8 both banked. R22 clean-fleet 140 passed / 0 failed of 140.
§92 SAID these need "the §17a-1 caller pair, NOT a bare conform" — the diagnosis was right (conforming
a narrow param changes argument promotion at every call site, measured PLUMBING -> DIFF) but the
remedy was the expensive one. The actual fix touches NO declaration: convert the DEFINITION to K&R,
where a narrow param PROMOTES to int (C89 6.3.2.2) and is therefore already compatible with the
fleet's existing `s32` prototype, while still emitting narrow-param codegen. §43 applied to the def
side. T0 draft-only, ZERO blast radius, versus a 524-site fleet conform.
THREE reconcile_tu BUGS SURFACED, ONE OF THEM MINE:
(a) BLIND TO BLOCK SCOPE. split_statements is depth-0 BY DESIGN, and §8d deliberately demotes data
externs into the function body — so the tool saw one statement and no declarations, printing
"reconciled: 0 draft(s), 0 data symbol(s); coverage defects: 0" for a draft cc1 rejected with
`conflicting types for D_8011F7BC`. A silent skip (R32). Fixed: descend one level.
(b) MY BUG, introduced by (a): descending into ANY `{` also enters struct/union/enum definitions, so
MEMBERS parse as declarations and get conformed — `u32 code;` became the TU's
`typedef void (*code)(unsigned short*);` INSIDE the struct, and `p->code` became
`p->(*(u32 *)&code)`. Caught by DIFFING THE TOOL'S OUTPUT AGAINST ITS INPUT before trusting it;
the byte-gate would have said PLUMBING and explained nothing. Guard: function bodies only.
(c) LATENT since the tool was written: _cast_sub matched bare identifiers and rewrote MEMBER ACCESSES
as globals. Unreachable until (a) existed. Guard: (?<![.\w])(?<!->).
cookbook §99.
|