mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 05:56:00 -04:00
070cf375c9
- banked 42 gate-proven SIG_FIXABLE_KR matches in ov_SC01_077 (of 48 predicted; 6 honestly
reverted by the whole-binary byte-gate, P9) + propagated 13 h_exact-shared x134 via
dedup_propagate (one body -> 134 overlays, each byte-gated, fail-closed)
- fleet byte-identical-from-source 54.48% -> 55.00% (+0.52%); REAL +1,778; dedup groups
1395 -> 1408; make check-all 136/136 byte-identical (R22); dedup-check 1408 validated/0 failed
- wall probe (R14): raw drafts 0/99 + sig_unify fails -> the K&R/sig_unify avenue is exhausted;
the residual conflict-class is ARITY_WALL (the §14e param-count dead-end) or structural (T4/T5)
- FIX a T1 classifier bug surfaced by verifying the wall vs the bytes: tu_compile_error captured
the baseline's pre-existing byte-NEUTRAL warnings ("makes integer from pointer", cc1 rc=0) and
mislabeled 99 fns LOOSE_TYPING_WALL; now keeps only non-warning errors -> there is NO loose-typing
wall, the real residual wall is ARITY_WALL=74. docs/wall-taxonomy.md amended with the correction.
- 134 overlay .c files carry the propagated DEFINE_func instantiations; a one-time full-fleet
make extract was required for the per-overlay propagation gate + check-all
148 lines
11 KiB
Markdown
148 lines
11 KiB
Markdown
# Wall Taxonomy — the 957 unmatched shared residuals in `ov_SC01_077` (Phase 17 / T1)
|
||
|
||
> **What:** a full-census classification of every remaining `INCLUDE_ASM` stub in the canonical
|
||
> harvest source `ov_SC01_077` by the *blocker class* it hits in the real drafting pipeline —
|
||
> so Phase 17 can size each avenue's ceiling and **sequence the levers (biggest first)**.
|
||
> **How:** `tools/wall_taxonomy.py` runs `m2c --valid-syntax` → `match_one` (standalone, relocation-masked)
|
||
> → for the body-byte-correct subset, `sig_unify` + a full-overlay-TU `cc1`, and labels each stub by the
|
||
> first wall it hits (cookbook §14b/§14c/§14e/§15). Deterministic; reproduce with:
|
||
>
|
||
> ```
|
||
> python3 tools/wall_taxonomy.py --jobs 16 # ~22 s; writes .run/wall_taxonomy.json + this table
|
||
> ```
|
||
>
|
||
> **Validated against the bytes (R14):** the **SIG_FIXABLE_KR** bucket was confirmed on the real
|
||
> whole-binary byte-gate — the 4 functions the classifier flagged in a 40-stub probe were **exactly** the
|
||
> 4 (of 40) that `harvest_verify` verified byte-identical after `sig_unify`; all other buckets correctly
|
||
> did **not** byte-match through signature work alone. The classifier's "fixable-now" set = the real
|
||
> gate-passing set. (PERMUTER_CLASS is an evidenced *candidate* bucket — see its caveat below — pending T6.)
|
||
|
||
Baseline at census: fleet 136/136 byte-identical from clean; 54.48% byte-identical-from-source;
|
||
`ov_SC01_077` = 957 unmatched shared stubs (each propagates ×134 overlays via `dedup_propagate`).
|
||
|
||
## ⚠ Correction + T3 update (2026-06-19) — the "loose-typing wall" was a classifier artifact
|
||
|
||
During T3, verifying the wall bucket against the bytes (R14) found a flaw in the original step-3 classifier:
|
||
the full-TU `cc1` stderr includes **pre-existing harmless warnings** — the baseline `ov_SC01_077.c` already
|
||
emits 3 `"passing arg of func_80171AB0 makes integer from pointer"` warnings and **compiles `rc=0`,
|
||
byte-identical** (those warnings are byte-neutral: a pointer and an `s32` share a register on MIPS). The
|
||
classifier matched that warning text before the real, `rc`-flipping **error**, so it mislabeled 99 functions
|
||
`LOOSE_TYPING_WALL` when their actual blocker was something else (e.g. `void value not ignored` — m2c using a
|
||
void function's return). **Fix:** `tu_compile_error` now keeps only non-warning error lines. Corrected result:
|
||
|
||
**There is no loose-typing wall (99 → 0).** It re-bucketed into **`ARITY_WALL` (74)** — genuine param-count
|
||
conflicts (`conflicting types for func_X` / too-few/many-args), the §14e documented dead-end — plus
|
||
`VOID_VALUE_MISUSE` (17, structural → T4/T5) and a few others. Corrected post-T3 census (916 residual stubs,
|
||
after T3 banked 42):
|
||
|
||
| bucket | count | primary avenue |
|
||
|--------|------:|----------------|
|
||
| `STRUCTURAL_MISS` | 368 | T4/T5 |
|
||
| `PERMUTER_CLASS` | 146 | T6 candidate |
|
||
| `MCOMPILE_fnptr-call` | 85 | T4 (fn-ptr-table types) |
|
||
| `ARITY_WALL` | **74** | **the real wall** — §14e param-count/arity dead-end |
|
||
| `M2C_DECOMP_FAIL` | 59 (58 jtbl) | T4 (jump-table context) |
|
||
| `MCOMPILE_stack-var` / `arg-arity` / `undeclared` / `void-value` / `bad-deref` / `incomplete-arg` | 143 | T4/T5 |
|
||
| `NONFAITHFUL_DEFER` | 16 | defer |
|
||
| `SIG_FIXABLE_KR` (remaining) | 4 | T3 |
|
||
| `DATA_CONFLICT` | 1 | T2 (still ≈0 → skip) |
|
||
|
||
**Per-lever (corrected): T4+T5 ≈ 656 (72%), T6 = 146 (16%), ARITY_WALL = 74 (8%), defer = 16, T2 ≈ 0.**
|
||
The sequencing recommendation is **unchanged and strengthened** — the real wall is *arity* (74, smaller than
|
||
the spurious 99) and even more of the residual is structural (T4/T5). The "cast the loose callee func_80171AB0"
|
||
lever I briefly chased was built on the misattributed warnings → **void** (the warnings don't block or change bytes).
|
||
|
||
**T3 result (the K&R / sig_unify avenue, gate-proven):** banked **42** `SIG_FIXABLE_KR` matches in `ov_SC01_077`
|
||
(of 48 predicted; 6 honestly reverted by the gate) + propagated **13** ×134 fleet-wide → **fleet 54.48% → 55.00%
|
||
(+0.52%)**, REAL +1,778, 136/136 byte-identical, dedup-check 1408/0. The avenue is then **exhausted**: the
|
||
remaining conflict-class is `ARITY_WALL` (dead-end) or structural (T4/T5), not signature-fixable.
|
||
|
||
---
|
||
|
||
## The census (957 stubs, ranked by count) — original T1 snapshot (LOOSE_TYPING_WALL row superseded above)
|
||
|
||
| count | % | Σnins | bucket | primary avenue |
|
||
|------:|---:|------:|--------|----------------|
|
||
| 368 | 38% | 25345 | `STRUCTURAL_MISS` | **T4** (rich context) / **T5** (struct) — m2c gets the structure wrong |
|
||
| 146 | 15% | 4941 | `PERMUTER_CLASS` | **T6** candidate — near-miss, same instruction count |
|
||
| 99 | 10% | 3282 | `LOOSE_TYPING_WALL` | **WALL** — a matched caller passes a contradictory type (§14e) |
|
||
| 85 | 8% | 3495 | `MCOMPILE_fnptr-call` | **T4** — type fn-pointer tables in the m2c context (§15 S2) |
|
||
| 59 | 6% | 12597 | `M2C_DECOMP_FAIL` | **T4** — feed jump tables to m2c (58/59 are jump-table, §8) \| hard |
|
||
| 48 | 5% | 1419 | `SIG_FIXABLE_KR` | **T3** — `sig_unify` resolves it (**gate-proven**) |
|
||
| 45 | 4% | 4928 | `MCOMPILE_stack-var` | **T5/T4** — m2c stack/struct recovery |
|
||
| 32 | 3% | 4138 | `MCOMPILE_arg-arity` | **T4/T5** — m2c arg-count recovery |
|
||
| 21 | 2% | 838 | `MCOMPILE_undeclared-other` | **T4** — undeclared callee/symbol into context |
|
||
| 16 | 1% | 2437 | `NONFAITHFUL_DEFER` | **DEFER** — GTE/handwritten/special; not m2c-matchable |
|
||
| 14 | 1% | 1382 | `MCOMPILE_m2c-incomplete-arg` | **T4/T5** — m2c incomplete arg recovery |
|
||
| 14 | 1% | 2277 | `MCOMPILE_bad-deref` | **T5/T4** — m2c deref'd a non-pointer (`?`/`M2C_UNK`) |
|
||
| 8 | 1% | 946 | `MCOMPILE_other` | residual (8 fns; mixed m2c-output errors) |
|
||
| 1 | 0% | 204 | `MCOMPILE_bad-switch` | T4/T5 — m2c switch reconstruction |
|
||
| 1 | 0% | 160 | `LEAF_READY` | T6/harvest — directly matchable, trivial |
|
||
| **957** | | **70871** | | (99.2% carry an actionable label; `DATA_CONFLICT` = **0**) |
|
||
|
||
Example targets (biggest-first = highest leverage; full per-fn data in `.run/wall_taxonomy.json`):
|
||
- `STRUCTURAL_MISS`: `func_80176218`(327), `func_8016A290`(284), `func_8015126C`(254)
|
||
- `M2C_DECOMP_FAIL` (jtbl): `func_8017C974`(947), `func_80178D40`(890), `func_8018103C`(579)
|
||
- `MCOMPILE_fnptr-call`: `func_8015EA3C`(204), `func_8015D738`(201), `func_8015F448`(188)
|
||
- `MCOMPILE_bad-deref`: `func_80144B9C`(**770** — the Phase-15 prime target, all-134), `func_8012D714`(284)
|
||
- `PERMUTER_CLASS`: `func_80132288`(97), `func_8013DBE4`(97), `func_80164930`(81)
|
||
- `SIG_FIXABLE_KR`: `func_80128AF4`(72), `func_80144458`(64), `func_8017E51C`(58)
|
||
- `LOOSE_TYPING_WALL`: `func_80141CA4`(476), `func_80140F00`(128), `func_80155150`(105)
|
||
|
||
## Aggregated by primary lever (this is the sequencing driver)
|
||
|
||
| count | % | Σnins | lever |
|
||
|------:|---:|------:|-------|
|
||
| **639** | **67%** | 39204 | **T4** (rich context: struct + fn-ptr-table + jump-table + plain), with **T5** the struct input to ~474 of them |
|
||
| 146 | 15% | 4941 | **T6** (decomp-permuter) — 146 candidates (**101 are ≤4-mismatch near-certain**; 19 likely 5–8; 26 speculative 9–16) |
|
||
| 99 | 10% | 3282 | **WALL** (loose typing) — documented dead-end; T5's *correct* struct types may dissolve a subset (§14e) |
|
||
| 48 | 5% | 1419 | **T3** (`sig_unify`) — gate-proven immediate wins |
|
||
| 16 | 1% | 2437 | **DEFER** (non-faithful: GTE/handwritten/special) |
|
||
| 9 | 1% | 1106 | residual / trivial |
|
||
| **0** | **0%** | 0 | **T2** (DATA-symbol byte-array header) — **no addressable functions** |
|
||
|
||
**Giants (106 functions > 150 ins, the ~3.4 MB highest-leverage targets):** 30 are `M2C_DECOMP_FAIL`
|
||
(jump-table → **T4 jtbl context**), 28 `STRUCTURAL_MISS` (**T4/T5**), 12 `arg-arity`, 12 `stack-var`,
|
||
6 `NONFAITHFUL_DEFER`, 5 `bad-deref`, 4 `fnptr-call`, rest scattered. **The giants are unlocked by T4
|
||
(jump-table + struct context), not by T3 or T6.**
|
||
|
||
## What this means for sequencing (T1's purpose)
|
||
|
||
1. **SKIP T2 (the DATA-symbol byte-array header).** The census finds **0** data-symbol-conflict functions.
|
||
The cookbook flagged this as "the next yield-limiter" (§14c-c) when Phase 16 jumped past it — but
|
||
`sig_unify` (which canonicalizes data externs) plus the prior harvest already absorbed it. Building a
|
||
universal `extern u8 D_X[]` header would address nothing. **Document the finding; do not build T2.**
|
||
|
||
2. **Bank T3's 48 gate-proven `SIG_FIXABLE_KR` wins first** — deterministic, byte-gate-verified, cheap; a
|
||
clean opening (~5% of residuals, ×134 each). Extend `sig_unify` coverage / wire it into a propagation pass.
|
||
|
||
3. **Lead with T4 (the rich-context generator) as the primary lever** — it addresses **67%** of residuals
|
||
and **all 30 jump-table giants**. Build it with three context sources, in value order:
|
||
- **(a) jump-table data** → unlocks `M2C_DECOMP_FAIL` (59, incl. the 947/890/579-ins giants). m2c
|
||
literally errors "jump table is not provided"; the §8 rodata/jtbl machinery already exists.
|
||
- **(b) struct types** (T5's output) → the 474 `STRUCTURAL_MISS`/`bad-deref`/`stack-var`/`arg-arity` set,
|
||
incl. `func_80144B9C` (770). **T5 (struct inference + emulator field-typing) is T4's enabling input —
|
||
run them together**, not as separate sequential avenues.
|
||
- **(c) fn-pointer-table types** → the 85 `MCOMPILE_fnptr-call` ("called object is not a function").
|
||
|
||
4. **T6 (permuter) is the byte-closer, validated early.** 146 candidates (101 near-certain ≤4-mismatch).
|
||
Critically, T4 will **convert `STRUCTURAL_MISS` into `PERMUTER_CLASS`** (better m2c structure → only
|
||
regalloc/schedule left), *growing* T6's addressable set. Confirm the bucket is real on the known-answer
|
||
ladder (`p16_known_answer --gate`) before projecting its yield (the only unverified bucket here).
|
||
|
||
5. **The wall is ~99 `LOOSE_TYPING_WALL` (+ the arity subset).** Phase 16's loose-typing finding, now
|
||
quantified at ~10–13%. No clean deterministic fix; the only lever is T5's *correct* struct types possibly
|
||
making some call sites type-consistent (§14e hypothesis — test, don't assume). Plus 16 `NONFAITHFUL_DEFER`.
|
||
|
||
**Net:** the deterministic ceiling (T3 `sig_unify`, no permuter) is ~5%, matching Phase 16. The *eureka*
|
||
lever is **T4+T5 (context+struct)** at 67% reach, with **T6** closing the regalloc residual — not T2 (empty)
|
||
and not signature work alone. This reorders the plan's avenues to **T3 (free wins) → T4+T5 (build together)
|
||
→ T6 (validate + close) ; T2 skipped**.
|
||
|
||
## Reproduce / maintain
|
||
|
||
- `python3 tools/wall_taxonomy.py --jobs 16` — full census → `.run/wall_taxonomy.json` + the table above.
|
||
- `--limit N` probes the classifier on the first N stubs; `--no-step3` skips the TU-context conflict sub-split.
|
||
- The tool is read-only on tracked files (step 3 uses throwaway `src/ov_SC01_077/_wt_*.c` copies, auto-removed).
|
||
- Re-run after any harvest wave to watch buckets drain and re-rank the remaining avenues.
|