mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-01 07:40:42 -04:00
docs: cookbook §303 (module island pads derived at build time; island-pads/island-blocked dissolve) + SETUP row (P31 S62 T3a)
This commit is contained in:
@@ -736,6 +736,7 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo
|
||||
| | `tools/stub_invariant_audit.py` | **(Phase 31 S62 T1, cookbook §301)** Regression test for the masked comparer: INCLUDE_ASM pastes the original bytes, so `diff_object_s(object, .s)` must be 0 for every stub; quotes the denominator (stubs with internal-`j` relocs). Run after ANY change to `masked_diff.py`. |
|
||||
| | `tools/interleave_check.py` | **(Phase 31 S62 T2, cookbook §302)** Order ⇔ yaml consistency for an overlay's jtbl carve: the `_JTBL_INTERLEAVE` order must equal the yaml subseg sequence position by position. `--fix` regenerates the order from the yaml (never hand-edit it). Run after ANY restore of overlays.mk or a splat yaml (two of the five S61 reds and four of the six clean-sweep failures were exactly this). |
|
||||
| | `tools/pads_audit.py` | **(Phase 31 S62 T2, cookbook §302)** DERIVES each object's `JTBL_PADS` from the bytes: compiles the TU to count its tables, walks the retail words inside the yaml carve with those sizes (pad 4 ⇔ one zero word), reports SPEC-DRIFT / CARVE-DRIFT / ok with the derived spec. Reproduced 15/15 correct specs as its negative control; replaced S61's blind value searches. |
|
||||
| | `tools/jtbl_rodata_pads.py --derive` | **(Phase 31 S62 T3a, cookbook §303)** Module path of the §8e pads filter: the Makefile runs `--derive $(BINARY) --tu <tu>` for every `md_*` object — jump-table pads derived at build time from the retail island + the emission stream (trailing pads `0t1`, table-aware, const data passes through). No stored spec; an anchor miss fails the build with the offset. |
|
||||
| | `tools/blocker_probe.py` | **(Phase 29 SESSION-16, cookbook §65)** WHY a byte-correct draft fails the whole-binary gate. Read-only; **two oracles** (R34): STATIC (`cdecl.parse` + `cdecl.compatible` — cc1's own acceptance question, never text equality) beside the REAL cc1 (via `rtu_match`), leading with the DISAGREEMENT table. Classes `self_decl_hdr`/`self_decl_tu`/`callee_decl`/`data_decl`/`local_type`, each mapped to a blast-radius tier (T0 draft-only / T1 binary-local / T2 fleet-shared). Blockers STACK, so a function's tier is the MAX over them. 36 drafts in ~9 s. Replaced+deleted `.run/diag_plumbing.py`. |
|
||||
| | `tools/symcheck.py` | **(Phase 29 SESSION-18, cookbook §67a)** The pre-gate SYMBOL-SET guard: diffs the symbols a draft's object references (reloc records) against the target `.s`'s `%hi`/`%lo`/`jal` set. Catches the class **every masked oracle is structurally blind to** — `match_one`/`masked_diff` compare relocation-MASKED words (object-vs-`.s` mode is symbol-agnostic by construction) and `rtu_match` **compiles without linking**, so a draft that invents an extern no symbol table defines reads MATCH in both and can never bank (the SESSION-17 `func_801463A0` `_s`-alias trap). Negative-control-proven: on a draft with one renamed data extern, `match_one` reports the SAME 14 mismatched as the correct draft while `symcheck` exits 1 naming both the MISSING and the INVENTED symbol. `--c` (compiles via `match_one`, so the triple can never drift) or `--obj`. A cheap necessary condition, NOT a match oracle — still finish on the byte-gate (G3/P9). |
|
||||
| | `tools/demacroize.py` | **(Phase 29 SESSION-16, cookbook §65b)** The per-overlay-local escape from a shared-header decl conflict — the largest stranded class, and the one §20 called unrecoverable. The conflicting `extern` lives INSIDE a `DEFINE_func_*` body, so it exists only at instantiation sites: this expands those instantiations **in the overlay's own TU**, correcting only the conflicting decl to the draft's byte-true sig (never dropping it, §57a-1). **T1** — writes confined to `src/<binary>/**`, so the per-binary gate suffices and no R22 risk is created by construction (contrast `fix_header_decl`, fleet-blind, §63 UPDATE). `--emit-edits` (read-only, feeds `rtu_match`) / `--apply`. **Price: the function can no longer propagate ×138 — such a bank is ×1** (full distinct-code credit, ~1/138 of instr). |
|
||||
|
||||
@@ -29671,3 +29671,39 @@ function (SC04_018: offset/value swapped in one store).
|
||||
**Process rule that falls out (R59 candidate, sharpened):** a blanket restore of overlays.mk or a
|
||||
splat yaml is a carve-state edit; it must be followed by `interleave_check` on every overlay whose
|
||||
lines it touched, and `pads_audit` on every object whose spec it carried.
|
||||
|
||||
## §303 — MODULE ISLAND TABLES: DERIVE THE PADS AT BUILD TIME, PEEL NOTHING — THE §154-A/§260 "island-pads"/"island-blocked" WALLS DISSOLVE (P31 S62 T3a; byte-proven md_SC03_076 func_801F0A9C + func_801F0F28, sha 9a165e36…)
|
||||
|
||||
**The shape.** A module's rodata island (offset 0, `[0x0, .rodata, md_X]`) packs every switch's
|
||||
jump table in source order, each table followed by 0–n zero words; the island is bound to the main
|
||||
TU object, and every stub's `.s` carries its own table (+ its trailing pad) at the stub's position
|
||||
in the stream, while a matched body's cc1 emits `.align 3 + $L + N entries` — the real entries only.
|
||||
§260 peeled only END-adjacent tables into their own object; interior tables ("island-blocked") and
|
||||
padded tables ("island-pads") were refused: 16 + 9 fns in the S62 resolver stock alone.
|
||||
|
||||
**The law: emission order == island order, so the object can emit the whole island in place.**
|
||||
cc1 places each table at its function's position; INCLUDE_ASM'd `.s` blocks interleave in place;
|
||||
C const data (`D_…:`) lands where the source puts it. The ONLY missing bytes are the pads a matched
|
||||
body no longer supplies — and they are computable from the retail island. `tools/jtbl_rodata_pads.py`:
|
||||
- is now table-aware: it acts only on an `.align 3` that a `$L` label follows; const data
|
||||
(`.align 2`, `D_…:`, `.byte`), includes and string pools pass through untouched;
|
||||
- takes trailing pads: token `0t1` = no leading pad, one zero word after the table (`4t2` etc.);
|
||||
- **`--derive <binary> --tu <tu>` (modules; wired in the Makefile for every md_* object):** parses
|
||||
the maspsx stream's rodata items in order — `.include`d `.s` blocks (span from their `/* off
|
||||
vaddr */` comments, sized by directive when the comment carries no hex), C data objects (start =
|
||||
the address in the `D_XXXXXXXX` name, size from the directives), C tables — then walks the retail
|
||||
island: a `.s` span must start exactly at the running position, C data at its aligned address,
|
||||
and a C table takes lead 4 iff the retail word at the position is zero, N in-range code words,
|
||||
then trailing zeros up to the next anchor (or the next non-zero word); an anchorless stream (an
|
||||
isolated §260 object) is framed by its yaml `.rodata` piece. Any anchor miss refuses with the
|
||||
offset — a CARVE-DRIFT verdict AT BUILD TIME, attributable, never a silent shift.
|
||||
- Nothing is stored (R33): no modules.mk spec, no yaml edit, no isolation — so nothing can drift
|
||||
(contrast §302: every S61 red was a stored carve spec drifting).
|
||||
|
||||
**Gate side.** `harvest_verify._jtbl_prep_one`: a module island wall now just leaves the splice
|
||||
in place (`[jtbl] module island table … handled by --derive`); the build judges. The old §260
|
||||
peel stays valid for already-peeled pieces (`--tu` frames them).
|
||||
|
||||
**Controls.** Positive: the derive reproduces the hand-proven `0t1,0` and its filtered output is
|
||||
byte-identical to the stored-spec output. Negative: every module binary rebuilt through the derive
|
||||
stage must stay byte-identical (the S62 module sweep — count quoted in the phase log).
|
||||
|
||||
Reference in New Issue
Block a user