docs(cookbook §135): six byte-verified gcc-2.7.2 idioms + the two-lane wave shape (P30 S6f-h)

Distilled from ~100 agent-drafted functions gated whole-binary across three waves; each idiom CLOSED
a specific residual, none is a hypothesis.

CODEGEN:
1. UNSIGNED switch index => pure equality chain — for an unsigned index the case-0 leaf satisfies
   node_has_low_bound (0==TYPE_MIN) so emit_case_nodes drops the range test entirely.
2. ARRAY_REF vs INDIRECT_REF changes ALIASING hence SCHEDULING — a[i] sets MEM_IN_STRUCT_P and
   true_dependence() drops the dependence vs a constant-address store, so the load hoists.
   A '4-ins scheduling residual' that is really a type-form choice.
3. A constant store with the top bit set in the STORED width needs an UNSIGNED destination
   (u16 -> ori via force_fit_type; s16 -> sign-extended fold -> addiu).
4. The list scheduler PRESERVES relative order of disambiguable stores — a store written late SINKS.
   Move it earlier in SOURCE. Closed 9 mismatches with no permuter.
5. A short loop counter blocks strength reduction on array indexing; the original walked pointers.
6. Frame size off by a constant => DEAD LOCALS (every diff is an sp displacement of one delta).

INTEGRATION (what decides whether a byte-correct draft BANKS):
7. match_one MATCH != a bank (83%/93%/71%->89% survived the gate across the three waves).
8. cc1 reports only the FIRST conflict — grep the whole TU for every symbol in one pass (one draft
   had SIX bad prototypes, two BELOW the splice point).
9. An INTERIOR address has no symbol (D_801DA0F0 is +0x6C into D_801DA084) -> undefined reference
   at LINK, not a compile error.
10. Never redeclare a C-library name (one TU declares memcpy THREE times, incompatibly).

WAVE SHAPE: two lanes; the reconcile lane is 12/12 across two waves because the orchestrator captures
the compiler error BEFORE the fan-out. Promote wave-N's Opus discoveries into wave-N+1's cheap-tier
prompt (83->93%). Paste args from a DERIVED manifest. If N reconcile targets share ONE TU, forbid
agent builds. An agent that rejects your premise is working correctly.
This commit is contained in:
Drew T
2026-08-01 20:29:35 -06:00
parent 6fe9b66f2d
commit bfbcb86b3d
2 changed files with 83 additions and 3 deletions
+11 -3
View File
@@ -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 / 360 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 / 364 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.
@@ -331,7 +331,7 @@
- **§124a** — a family sweep's `0 matched-exemplar families` may be a FILTER, not a wall <sub>L8191</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
### integration / TU plumbing (32)
### integration / TU plumbing (33)
- **§8c** — Splitting a TU means rebuilding its DECLARATION ENVIRONMENT, not moving text (Phase 26 session 6) <sub>L437</sub>
- **§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) <sub>L483</sub>
@@ -365,6 +365,7 @@
- **§109** — Conforming a definition to a shared header: fix the NAMES, then check the RETURN precondition (Phase 29 T60) <sub>L7593</sub>
- **§112** — A macro-scoped declaration only collides where the macro is INSTANTIATED (Phase 29 T67/T69, `audit_header_sigs.py`) <sub>L7723</sub>
- **§114** — The THIRD decl axis: a CALLEE the draft declares differently from the target TU (Phase 29 T76/T77) <sub>L7801</sub>
- **§3-The** — integration idioms (these decide whether a byte-correct draft BANKS) <sub>L8797</sub>
### build graph, splat & the harness (90)
@@ -509,7 +510,7 @@
- **§125** — Split the CARVE from the BODY before calling a jr residue a wall — and measure it by SHA from a CLEAN tree (P30 SESSION-28; **this section's first draft was WRONG and the method caught it**) <sub>L8199</sub>
- **§3-The** — meta-lesson <sub>L8250</sub>
### (unbucketed — title matched no symptom vocabulary) (99)
### (unbucketed — title matched no symptom vocabulary) (102)
- **§3-How** — to use this <sub>L30</sub>
- **§1** — Idiom catalog (asm pattern → C that produces it) <sub>L39</sub>
@@ -610,6 +611,9 @@
- **§3-The** — fingerprint, and the 30-second ladder that found it <sub>L8600</sub>
- **§3-The** — transferable rule <sub>L8621</sub>
- **§132a** — `--like` is for a sibling with NO record; against one that HAS a record it over-derives (P30 S29, `ov_SC07_010`) <sub>L8628</sub>
- **§135** — Six byte-verified gcc-2.7.2 idioms from the P30 S6f-h waves (and the two-lane wave shape that found them) <sub>L8758</sub>
- **§3-The** — codegen idioms <sub>L8763</sub>
- **§3-The** — wave shape that produced these <sub>L8812</sub>
## All sections, in order
@@ -974,3 +978,7 @@
- **§132b** — When the span's already-matched owner is ITSELF multi-switch: `--span-rel` (P30 S1, `func_8014032C`) <sub>L8653</sub>
- **§133** — The DEFAULT-FILTER class: three times in one session, a tool silently answered a narrower question than the one asked (P30 S1–S3) <sub>L8678</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
- **§135** — Six byte-verified gcc-2.7.2 idioms from the P30 S6f-h waves (and the two-lane wave shape that found them) <sub>L8758</sub>
- **§3-The** — codegen idioms <sub>L8763</sub>
- **§3-The** — integration idioms (these decide whether a byte-correct draft BANKS) <sub>L8797</sub>
- **§3-The** — wave shape that produced these <sub>L8812</sub>
+72
View File
@@ -8754,3 +8754,75 @@ wrapped declarations, wrapped attributes/asm-labels, multi-line typedefs, and co
braces — and its failures will look like walls, not bugs. Give it lookahead, mask comments/strings
before counting delimiters, and when a family banks 0/N with every member failing identically, **read
one compiler error before believing the compiler.**
## §135 — Six byte-verified gcc-2.7.2 idioms from the P30 S6f-h waves (and the two-lane wave shape that found them)
Distilled from ~100 agent-drafted functions gated whole-binary across three waves. Each idiom below
CLOSED a specific residual — none is a hypothesis.
### The codegen idioms
1. **UNSIGNED switch index ⇒ pure equality chain (no range test).** `switch (*(s32 *)(p+0x30))` over
cases {0,1,2,3} emits a balanced tree with an `slti` range split; `switch (*(u32 *)(p+0x30))` emits
`beq 1 / beqz / beq 2 / beq 3` with **no comparison at all**. For an unsigned index the case-0 leaf
satisfies `node_has_low_bound` (0 == TYPE_MIN), so `emit_case_nodes` drops the bound test. If the
target's switch has no range check, read the index UNSIGNED. (`func_8017C910`, 92 ins.)
2. **`ARRAY_REF` vs `INDIRECT_REF` changes ALIASING, therefore scheduling.** Writing a field read as
`a0[0x46]` makes it an ARRAY_REF, which sets `MEM_IN_STRUCT_P`; gcc-2.7.2's `true_dependence()`
then DROPS the dependence between an in-struct varying load and a not-in-struct constant-address
store, and the load hoists. Writing the same read as `*(s16 *)((s32)a0 + 0x8C)` keeps it a plain
INDIRECT_REF and restores the dependence. **A 4-instruction "scheduling residual" that is really a
type-form choice.** (`func_8017CFE0`.)
3. **A constant store whose top bit is set in the STORED width needs an UNSIGNED destination.**
`*(u16 *)p = 0x8C00` emits `ori` (via `force_fit_type`, the value stays positive);
`*(s16 *)p = 0x8C00` folds to sign-extended −29696 and `li` emits `addiu`. If the target
materializes the constant with `ori`, the destination is unsigned. (`func_8018A0F4`.)
4. **The list scheduler PRESERVES the relative order of disambiguable stores.** A store written late
in source SINKS to the end of the block rather than hoisting into load-delay slots. Two field-zero
stores had to be written ABOVE a three-halfword copy to land at the target's indices — 9 mismatches
→ 0, **no permuter**. When a store lands too late, move it earlier in SOURCE. (`func_8017CAB4`.)
5. **A `short` loop counter blocks strength reduction on array indexing.** `for (s16 i…) p[i].f0`
emits a sign-extend + multiply chain; walking explicit pointers (`p++`, `q++`) reproduces the
original's biv/giv set. The 1998 source walked pointers. (`func_8017C738`, 96 ins.)
6. **Frame size off by a constant ⇒ DEAD LOCALS, not a codegen bug.** A draft that is structurally
exact but yields a `0x40` frame against the target's `0x50` shows every `sp` displacement off by
exactly `0x10` — the original declared locals ahead of the live ones. Add the padding declaration.
The tell is that ALL diffs are `sp`-relative immediates of one constant delta. (`func_8017FD58`.)
### The integration idioms (these decide whether a byte-correct draft BANKS)
7. **`match_one` MATCH ≠ a bank.** It compiles standalone and cannot see the TU's other declarations.
Measured across the three waves: **83% → 93% → 71%(+reconcile to 89%)** of agent MATCHes survived
the whole-binary gate. **Always finish on the whole-binary gate (G3/P9).**
8. **cc1 reports only the FIRST conflict**, so a draft can look one edit away and hold three more.
One draft had invented prototypes for **six** symbols the TU declares, two BELOW the splice point.
**grep the whole TU for every symbol the draft names, in one pass.**
9. **An interior address has no symbol.** `D_801DA0F0` does not exist — it is offset `0x6C` into
`D_801DA084`. A `lui/addiu` pair can build an INTERIOR pointer; declaring the interior address as
its own extern gives `undefined reference` at LINK, not a compile error. Find the containing symbol
in the data `.s` and index into it. (`func_8017C5F0`.)
10. **Never redeclare a C-library name.** A draft's own `memcpy` prototype collided with the TU's —
which declares `memcpy` **three times** with incompatible signatures. (`func_8018A860`.)
### The wave shape that produced these
**Two lanes, and the reconcile lane is the reliable one (12/12 across two waves).**
- **Draft lane:** cheap tier (Haiku ≡ Opus at ≤~50 ins, ~4.8× cheaper — `cheap-tier-ab-validated`),
Opus direct ≥90 ins, Opus escalation in between. 17 of wave-1's 20 banks were Haiku.
- **Reconcile lane:** for every gate failure, the orchestrator **captures the compiler error first**
and embeds it. Agents cannot run the gate, so without the error a declaration conflict reads to them
as a codegen wall — S29's law, re-confirmed. With it: 12/12.
- **Between waves, do all three:** paste args from a DERIVED manifest (never typed — a hand-transcribed
path list cost wave 1 three agents' time); capture blockers; and **promote wave-N's Opus discoveries
into wave-N+1's cheap-tier prompt.** Bank rate 83% → 93% on that alone.
- **Concurrency hazard:** if N reconcile targets share ONE TU, FORBID agent builds — concurrent
splice-builds clobber a tracked file. Allow the single permitted splice-build only when targets are
spread across TUs. (Guard the campaign, not the process — §the S27 law.)
- **An agent that rejects your premise is working correctly.** Told a draft was byte-correct and only
declaration-blocked, one agent re-ran `match_one` first, found a real 1-instruction DIFF, and fixed
both. Hand agents the evidence, not the conclusion.