mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-28 06:49:47 -04:00
docs(phase-29): T59 — the five T58 zero families diagnosed: four causes, one wall
Deliverable is the diagnosis, not banks. Method: splice ONE member, `make -j1` the single object,
read the NON-warning cc1 lines (-j16 interleaves the real error away; the §58 memcpy / "type
mismatch" warnings dominate any naive tail; §93 pipefail names the wrong stage). Tree clean after
every probe.
CORRECTION TO MY OWN T58 REPORT (R14): I said "7 remaining families all have banked exemplars".
WRONG — there were 5. 0x80175820 (276 members) and 0x8016ec0c (138) have NO matched exemplar
anywhere: INCLUDE_ASM stubs in all 138 overlays. My batch-selection test picked the first TU
CONTAINING THE NAME (a declaration) and, seeing no stub in that file, called it banked. The family
map was right all along (kind='draft-ov077', matched_members=[]) and family_sweep correctly excluded
them ("6 matched-exemplar families" — a line I read past). Use corpus.stubs(ov), never a name-grep.
Their claimed 109,296 bytes were never real fuel.
THE FIVE VERDICTS:
0x8014d610 137 PLUMBING shared-header signature conflict
0x8016163c 137 PLUMBING shared-header signature conflict
0x80156044 137 PLUMBING shared-header signature conflict
0x80143d28 136 PLUMBING conflicting types for ApplyMatrixSV (a PsyQ library symbol)
0x801457a4 137 DIFF compiles clean, bytes differ — the ONLY genuine codegen wall
THE HEADER-CONFLICT CLASS (3 families / 411 members ~ 30,000 ins) + A THIRD OPT-IN LEVER. The
"previous declaration" line was the tell: for func_8014D610 it points at line 1727, which is NOT a
declaration — it is DEFINE_func_8014D438(), a shared-macro instantiation whose expansion
forward-declares the templated fn with the canonical engine_core.h signature. All four conflicting
fns are header-declared; the two non-header families are exactly the two with different verdicts.
--fix-def-sig is the lever (a THIRD opt-in one, after T56's unreachable and T57's off-by-default).
Tested: 0/411, and the verdict did NOT move to DIFF — it moved to a precise new compile error:
canonical : void func_8014D610(s32 a0, void *a1, void *a2)
draft body: ... param_1 ... -> `param_1' undeclared
reconcile_def_sig adopts the canonical signature WHOLESALE (types AND param names) while the body
keeps the exemplar's param_N names. Its docstring calls this a "rare name mismatch"; it is not rare —
an exemplar drafted with the param_N convention hits it every time. Fix: conform TYPES, keep BODY
names (both are in hand at the call site).
THE PATTERN, THREE TIMES IN ONE SESSION: T56 a lever unreachable from the sweep path, T57 a lever off
by default, T59 a lever subtly broken. Every family-wide 0/N so far has been a statement about the
HARNESS, not the code. cookbook §108 records the recipe + the four causes.
No src/ or config/ change: no bank, no metric move.
This commit is contained in:
@@ -7538,3 +7538,52 @@ miss it (the T24 `--allow-pins` precedent). `--no-tu-scope` exists to A/B it.
|
||||
written N times — delete all N. Now it compares whitespace-collapsed forms and refuses only on a
|
||||
genuine disagreement. (Measured on `D_800B9A02`: 3 decls in **2 different forms** — so that one was
|
||||
correctly refused, and the relaxation did not paper over a real conflict.)
|
||||
|
||||
---
|
||||
|
||||
## §108 — Diagnosing a family `0/N`: the four causes, and the third opt-in lever (Phase 29 T59)
|
||||
|
||||
A family sweep's `0/N` says nothing about the code until you splice ONE member and read the compiler.
|
||||
Do it like this — the shape of the output actively hides the answer:
|
||||
|
||||
```
|
||||
make -j1 build/<the one .o> BINARY=<ov> # -j16 interleaves the real error out of reach
|
||||
# then filter: '.c:' in line AND 'warning:' not in line
|
||||
```
|
||||
The `memcpy` / `type mismatch with previous external decl` warnings (§58) are noise from unrelated
|
||||
TU positions and will dominate any naive tail. And `set -o pipefail` (§93) attributes the failure to
|
||||
the last pipeline stage, so "Error 1"/"Error 33" names the wrong stage — read cc1's own lines.
|
||||
|
||||
**The verdict split that matters is PLUMBING vs DIFF**: a compile error is a declaration problem
|
||||
(recoverable, and each has a named lever); a clean compile with differing bytes is codegen. Five
|
||||
families diagnosed this way resolved to **four distinct causes**, only one of which is a wall:
|
||||
|
||||
| cause | signature | lever |
|
||||
|---|---|---|
|
||||
| shared-header signature conflict | `conflicting types for func_X`, "previous declaration" points at a **`DEFINE_func_*()` macro line** | `--fix-def-sig` (see the bug below) |
|
||||
| PsyQ/library symbol conflict | `conflicting types for ApplyMatrixSV` | unresolved — the draft's carried decl vs the TU's |
|
||||
| genuine codegen | compiles clean, bytes differ | permuter / §31 lookup |
|
||||
| no matched exemplar | `remap: no matched unit` | not a blocker — the family has no fuel |
|
||||
|
||||
**Read the "previous declaration" line number before theorising.** For `func_8014D610` it pointed at
|
||||
line 1727, which is not a declaration at all — it is `DEFINE_func_8014D438()`, a shared-macro
|
||||
instantiation whose expansion forward-declares the templated function with the canonical
|
||||
`engine_core.h` signature. cc1 reports the conflict at the macro's line. That one line identifies the
|
||||
whole class.
|
||||
|
||||
**THE `--fix-def-sig` BUG (why the lever did not fire).** `reconcile_def_sig` rewrites the draft's
|
||||
definition to the canonical header decl **wholesale — types AND parameter names**:
|
||||
|
||||
```
|
||||
canonical : void func_8014D610(s32 a0, void *a1, void *a2)
|
||||
draft body: ... param_1 ... param_2 ... -> `param_1' undeclared
|
||||
```
|
||||
Its docstring calls this a "rare name mismatch" that "the gate rejects, never a false bank". It is
|
||||
**not rare** — an exemplar drafted with the `param_N` convention hits it every time, and the whole
|
||||
family books as a compile failure. **The fix is to conform the TYPES and keep the BODY's names**;
|
||||
both are already in hand at the call site.
|
||||
|
||||
> **The law:** three times in one session a family-wide `0/N` was a lever that was unreachable
|
||||
> (§107), off by default, or subtly broken — never the compiler. **Before diagnosing a family as
|
||||
> hard, enumerate the levers the invocation actually enabled, then read one member's real cc1
|
||||
> output.** A sweep's `0/N` is a statement about the harness.
|
||||
|
||||
@@ -8069,3 +8069,64 @@ recount agrees exactly (T52 132 · T56 136 · T57 132 · T58 137). **+67,666 ins
|
||||
measurements themselves are still old; a re-collect is owed before the grinder is trusted again.
|
||||
**DO NOT close P29 on ROI** — +0.5pp instr today, and item 1 is a diagnosis queue with ~50 families
|
||||
behind it, not a burn-down floor.
|
||||
|
||||
## 🔎 T59 — the five T58 zero families diagnosed: **four distinct causes, only one is a wall**
|
||||
|
||||
Deliverable is the diagnosis, not banks. Method: splice ONE member, `make -j1` the single object,
|
||||
read the **non-warning** cc1 lines (the `-j16` interleave and the §58 `memcpy`/`type mismatch`
|
||||
warnings hide the real line every time; §93 pipefail names the wrong stage). Tree verified clean
|
||||
after every probe.
|
||||
|
||||
### FIRST, A CORRECTION TO MY OWN T58 REPORT (R14)
|
||||
I said "7 remaining families all have banked exemplars". **Wrong — there were 5.** `0x80175820`
|
||||
(276 members) and `0x8016ec0c` (138) have **no matched exemplar anywhere**: both are INCLUDE_ASM
|
||||
stubs in all 138 overlays. My T58 batch-selection test picked the first TU *containing the name* — a
|
||||
declaration — and, seeing no stub in that file, called it banked. **The family map was right all
|
||||
along** (`kind: 'draft-ov077'`, `matched_members: []`) and `family_sweep` correctly excluded them
|
||||
("6 matched-exemplar families", a line I read past). The oracle to use is `corpus.stubs(ov)`, never
|
||||
a name-grep. Their claimed weight (60,720 + 48,576 bytes) was never real fuel.
|
||||
|
||||
### THE FIVE VERDICTS
|
||||
| family | members | verdict | cause |
|
||||
|---|---|---|---|
|
||||
| `0x8014d610` | 137 | PLUMBING | shared-header signature conflict |
|
||||
| `0x8016163c` | 137 | PLUMBING | shared-header signature conflict |
|
||||
| `0x80156044` | 137 | PLUMBING | shared-header signature conflict |
|
||||
| `0x80143d28` | 136 | PLUMBING | `conflicting types for **ApplyMatrixSV**` — a PsyQ library symbol |
|
||||
| `0x801457a4` | 137 | **DIFF** | compiles clean, bytes differ — **the only genuine codegen wall** |
|
||||
|
||||
### THE HEADER-CONFLICT CLASS (3 families / 411 members ≈ 30,000 ins) — AND A THIRD OPT-IN LEVER
|
||||
The "previous declaration" line was the tell: for `func_8014D610` it pointed at line 1727, which is
|
||||
**not a declaration** — it is `DEFINE_func_8014D438()`, a shared-macro instantiation whose expansion
|
||||
forward-declares the templated function with the canonical `engine_core.h` signature. Verified all
|
||||
four are header-declared with a signature that disagrees with the exemplar's def; the two non-header
|
||||
families are exactly the two with different verdicts.
|
||||
|
||||
`--fix-def-sig` is the lever for this — **a third opt-in one** (after T56's unreachable and T57's
|
||||
off-by-default). Tested it: **0/411, and the verdict did NOT move to DIFF** — it moved to a
|
||||
different, precise compile error:
|
||||
```
|
||||
canonical : void func_8014D610(s32 a0, void *a1, void *a2)
|
||||
draft body: ... param_1 ... -> `param_1' undeclared (first use this function)
|
||||
```
|
||||
**`reconcile_def_sig` adopts the canonical signature wholesale — types AND parameter names — while
|
||||
the body keeps the exemplar's `param_N` names.** Its docstring calls this a "rare name mismatch";
|
||||
it is not rare — an exemplar drafted with the `param_N` convention hits it every time and the whole
|
||||
family books as a compile failure. **Fix: conform the TYPES, keep the BODY's names** (both are in
|
||||
hand at the call site).
|
||||
|
||||
### THE PATTERN, THREE TIMES IN ONE SESSION
|
||||
T56 a lever unreachable from the sweep path · T57 a lever off by default · T59 a lever subtly broken.
|
||||
**Every family-wide `0/N` so far has been a statement about the harness, not the code.** Cookbook
|
||||
**§108** records the diagnosis recipe + the four causes so this is a lookup next time.
|
||||
|
||||
## ▶ NEXT (ranked, all measured)
|
||||
1. **Fix `reconcile_def_sig`'s param-name bug** (conform types, keep body names) and re-sweep the 3
|
||||
header-conflict families — **411 members ≈ 30,000 ins**, the largest measured, best-understood
|
||||
block on the board.
|
||||
2. **`0x80143d28`** (136) — `ApplyMatrixSV` conflict: the draft's carried decl of a PsyQ symbol vs
|
||||
the TU's. Likely the same shape one level out; one probe.
|
||||
3. **`0x801457a4`** (137) — the only true DIFF; measure closeness and route per §31.
|
||||
4. **Probe the distinct-code +0 anomaly** (4 data points, no identified variable).
|
||||
5. **~50 more eligible families** — regenerate `family_hseq.py` first (the map predates T56–T58), and
|
||||
select exemplars with **`corpus.stubs`**, not a name-grep.
|
||||
|
||||
Reference in New Issue
Block a user