diff --git a/docs/cookbook-index.md b/docs/cookbook-index.md index 66684150c..9e2d0f19b 100644 --- a/docs/cookbook-index.md +++ b/docs/cookbook-index.md @@ -2,7 +2,7 @@ > **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section. > -> `docs/matching-cookbook.md` is ~716 KB / 407 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. +> `docs/matching-cookbook.md` is ~716 KB / 412 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses. **How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win. @@ -110,7 +110,7 @@ - **§70** — The giv-init base register: walk the PARAMETER, not a copy of it (Phase 29 SESSION-18, `func_801777BC`) L5612 - **§145** — Three loop/combine levers from the S40 wave-2 drafters (16/16 match_one) L9917 -### structs, block moves & memcpy (29) +### structs, block moves & memcpy (30) - **§3-T2** — Source statement order drives instruction scheduling L78 - **§5** — Known hard-residual classes (instruction-identical, one byte-exact blocker) L199 @@ -141,8 +141,9 @@ - **§129** — Post-carve, `rtu_match`/`match_one` COUNT THE JUMP TABLE AS INSTRUCTIONS; and a carve must never be committed without its owner (P30 S28, `func_8013BD74`) L8430 - **§129a** — the target instruction count is INFLATED after a carve L8434 - **§3-The** — DEFINITION-side alias is the only escape when the fleet canon disagrees on a promoting param L9463 +- **§3-Two** — errors of mine, both instructive L9999 -### types, signedness & load/store width (30) +### types, signedness & load/store width (31) - **§3-I1** — Unsigned range check: `(x - lo) < (hi-lo)` → `addiu`+`sltiu` L41 - **§3-I2** — Byte mask forces `andi` even after `lbu` L47 @@ -174,6 +175,7 @@ - **§3-Do** — NOT "strip the duplicate typedef" — it breaks the extern that uses it L8030 - **§3-The** — type-form rules L8872 - **§143** — `cast_call_sites` read a RETURN STATEMENT as a prototype and deleted it. A 0/39 sweep became 18/39. (P30 S40) L9824 +- **Then** — propagation returned 0/137 TWICE — both times a missing TYPE L9990 ### declarations, prototypes & K&R (54) @@ -276,7 +278,7 @@ - **§127a** — §71 (sibling-first) is the strongest `-O0` lever, and it beats the index L8370 - **§132** — The `JR-PAIR-IN-ONE-O0-OBJECT` "wall" was TWO instrument defects: a merged-double span the carve could not see, and a truncated object no rule deleted (P30 S29, `func_8013B83C` + `func_8013BD74`) L8563 -### family propagation & sweeps (70) +### family propagation & sweeps (71) - **§8d** — Templating a body INTO a TU must not CHANGE its declaration environment — demote the carried data externs (Phase 26 session 8, byte-proven on `func_8015AE2C` ×133) L483 - **§11** — Cross-binary dedup & code-sharing (Phase 11 — "one match unlocks many") L908 @@ -348,6 +350,7 @@ - **§138** — The propagation lanes: a gate refusal is a DECLARATION, and which lever you owe depends on blast radius L9405 - **§142** — An open stub whose `h_exact` class is MATCHED elsewhere is FREE. Propagate the body; do not gate a draft. (P30 S39, +7,710 ins in two commands) L9768 - **§143** — `cast_call_sites` read a RETURN STATEMENT as a prototype and deleted it. A 0/39 sweep became 18/39. (P30 S40) L9824 +- **Then** — propagation returned 0/137 TWICE — both times a missing TYPE L9990 ### integration / TU plumbing (36) @@ -490,7 +493,7 @@ - **§142** — An open stub whose `h_exact` class is MATCHED elsewhere is FREE. Propagate the body; do not gate a draft. (P30 S39, +7,710 ins in two commands) L9768 - **§3-The** — measurement (do this before any wave; it is ~20 lines and needs no builds) L9780 -### process, measurement & doctrine (56) +### process, measurement & doctrine (57) - **§8e** — The jtbl ALIGNMENT LAW + the pad-spec filter — multi-table .rodata spans (Phase 29, byte-proven; `.run/probe_jtbl/verdict.md`) L530 - **§3-The** — mechanism: game-code dedup is SOURCE-LEVEL, not an object swap (R-D1, the key lesson) L926 @@ -548,8 +551,9 @@ - **§140** — A METRIC IS NOT A MEASUREMENT UNTIL IT IS REPRODUCIBLE FROM THE COMMITTED TREE (P30 S1e: a phantom regression that gated the session's best lever) L9650 - **§3-The** — measurement (do this before any wave; it is ~20 lines and needs no builds) L9780 - **§3-And** — the report-vs-bytes lesson attached to it L9812 +- **§146** — RE-MEASURE A WALL BEFORE YOU RESPECT IT. Both "permanent" giants fell to drafts already on disk. (P30 S6, +50,094 ins) L9967 -### (unbucketed — title matched no symptom vocabulary) (118) +### (unbucketed — title matched no symptom vocabulary) (120) - **§3-How** — to use this L30 - **§1** — Idiom catalog (asm pattern → C that produces it) L39 @@ -669,6 +673,8 @@ - **§3-The** — trap that hid it — SAME FUNCTION, TWO ROUTES, ONLY ONE IS FREE L9795 - **Route** — selection (why `--addr` sometimes says "nothing changed") L9804 - **§144** — THE LITERAL'S SPELLING PICKS THE IMMEDIATE ENCODING (P30 S40 wave 1, `func_801822E0`) L9878 +- **§3-Why** — a correct draft can read as an intrinsic wall L9978 +- **§3-The** — rule L10013 ## All sections, in order @@ -1080,3 +1086,8 @@ - **§143** — `cast_call_sites` read a RETURN STATEMENT as a prototype and deleted it. A 0/39 sweep became 18/39. (P30 S40) L9824 - **§144** — THE LITERAL'S SPELLING PICKS THE IMMEDIATE ENCODING (P30 S40 wave 1, `func_801822E0`) L9878 - **§145** — Three loop/combine levers from the S40 wave-2 drafters (16/16 match_one) L9917 +- **§146** — RE-MEASURE A WALL BEFORE YOU RESPECT IT. Both "permanent" giants fell to drafts already on disk. (P30 S6, +50,094 ins) L9967 +- **§3-Why** — a correct draft can read as an intrinsic wall L9978 +- **Then** — propagation returned 0/137 TWICE — both times a missing TYPE L9990 +- **§3-Two** — errors of mine, both instructive L9999 +- **§3-The** — rule L10013 diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index 07403e9e1..7a8ac8042 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -9961,3 +9961,62 @@ IVs. Same family of decisions: *how many named pointers exist in the C* is a cod **Symptom lines for the index:** **"one extra induction register"** · **"a pointer bump addiu disappeared"** · **"stores are in the wrong order"** · **"one instruction too many in a loop"**. + +--- + +## §146 — RE-MEASURE A WALL BEFORE YOU RESPECT IT. Both "permanent" giants fell to drafts already on disk. (P30 S6, +50,094 ins) + +The roadmap carried two functions as **permanent walls** since Phase 24. Between them they were +50,094 instructions — the largest single item on the board — and they had deterred a Fable5-scale +attempt. Both were matched **from stored drafts, in minutes.** + +| wall | recorded verdict | what it actually took | +|---|---|---| +| `func_80178004` (165×138) | Phase 26: Fable5, **~477k tokens**, "intrinsic 3-integer regalloc wall" | a stored draft, gated as-is | +| `func_801412A8` (198×138) | close=29/110 since Phase 24 | 1 of **31** stored drafts + the §37/§124 alias | + +### Why a correct draft can read as an intrinsic wall + +`func_801412A8`'s TU declares `extern int func_801412A8(int,int,int,int,int,int)` and its callers +**use the return value**, while the byte-true definition is +`Prim_1412A8 *(Prim_1412A8 *, int, int, int, u16, u16)`. Narrow params cannot agree with an `int` +prototype, and the `()` no-prototype escape is illegal precisely when a param promotes — so neither +side can move. **The resulting byte difference is in the CALLERS, and `match_one` only ever compiles +the target function.** The measuring instrument was structurally blind to where the difference lived, +so the residual was attributed to codegen. The §37/§124 def-side alias decouples them: the TU's +declaration keeps governing the call sites (their codegen untouched), the definition keeps its +byte-true signature. + +### Then propagation returned 0/137 TWICE — both times a missing TYPE + +`family_remap._carry_macros` carries file-scope `#define`s, but **(a) it does not carry typedefs at +all, and (b) it is not transitive** — it brought `addPrim_1412A8` and stopped, though that macro +calls `setaddr`/`getaddr`, and `getaddr` casts to `PTag_1412A8`. Lifting +`Env_1412A8 / PTag_1412A8 / Prim_1412A8` + `OT/getaddr/setaddr` into `engine_types.h` took it to +**137/137**. A total-zero sweep on a PURE family with a *matched* exemplar is a tooling signal, not a +codegen one (§53) — here it fired twice in a row for two different missing symbols. + +### Two errors of mine, both instructive + +**Lift without strip.** I added the typedefs to `engine_types.h` and left the originals in +`ov_SC01_077.c`. gcc-2.7.2 rejects a repeated typedef even when identical — the lesson already +recorded at the foot of `engine_types.h` — so R22 came back **139/140, `[FAIL] ov_SC01_077`**, the +exemplar's own overlay. **A proper lift strips the source; `build_engine_types --strip` does both.** +The clean-fleet gate caught it before commit, which is exactly why fleet-shared edits are R22-gated. + +**Sampling instead of scanning.** My first pass over the stored drafts used `head -8` of 31 and +reported "best closeness 40" — the MATCH was in the 9th. And I checked whether a draft defined +`Prim_1412A8` with a plain `grep -c`, which matches inside `addPrim_1412A8`, and briefly concluded +the carry worked. Same shape as reading a `return` as a declaration (§143): a pattern that is a +substring of the thing you are actually asking about. + +### The rule + +**A wall verdict is only as current as the instrument that produced it.** Before spending +frontier-model tokens on a documented wall: re-run every stored draft through `match_one` (ALL of +them, not a sample), and check whether the tools that produced the verdict have changed since. Here +that cost four minutes and was worth 50,094 instructions. The corollary for the ledger: when a tool +is repaired, the verdicts it produced become **hypotheses again**, not facts. + +**Symptom lines for the index:** **"a documented wall"** · **"an old close= verdict"** · +**"match_one MATCH but the whole binary differs"** · **"a sweep returns 0 of N twice"**.