4.3 KiB
§39 — The ×1→×134 giant-endgame: propagate a matched -O2 giant via the NATIVE DEFINE-macro path (Phase 24 T7 §G close, 2026-07-08)
After the whale, two matched-but-×1 reach-134 giants remained — func_801770E0 (152) and func_801372B0 (207). The whale-session handoff proposed a hand-rolled src/shared/<fn>.h shared header per giant (the §38 whale mechanism). That was an -O0 necessity, not the -O2 path — both banked via the ordinary DEFINE_func_X() (engine_core.h) macro + dedup_propagate --recover. Five durable lessons:
(1) R14 — verify each "×1" claim against the bytes BEFORE acting. The handoff named THREE ×1 giants; func_8014E048 was ALREADY ×134 (a 134-member group + DEFINE_func_8014E048() in every overlay, done an earlier task — the handoff conflated its earlier ×1 state). Confirm the current member count (awk the group's binaries: list) + a representative other overlay's site (INCLUDE_ASM stub vs DEFINE_) before "finishing" any function. A stale handoff line is a claim, not ground truth.
(2) The DEFINE-macro path HANDLES pins/asm/anon-structs — the whale's shared header is -O0-ONLY. func_8014E048 (register-__asm__ pins + volatile-asm barriers), func_801770E0 (pins + anon-struct /s casts), and func_801372B0 (pins + asm-label externs + zero-byte barriers) ALL propagate ×134 as plain DEFINE_func_X() macros — compiles_standalone (real cc1, -O2) accepts every one (the handoff's "compiles_standalone REJECTS pin/asm bodies" was WRONG; the real blockers are (3)–(5)). Reach for a whale-style separate-object shared header ONLY when the fn is -O0 inside an -O2 TU (gcc-2.7.2 has no per-fn -O0 pragma → it needs its own object). An -O2 giant = the native macro path, full stop.
(3) THE overlay_files POST-WHALE-SPLIT GAP (the reusable fix). The whale rollout (§38) split every overlay's <ov>.c into <ov>.c/<ov>_o0b.c/<ov>_after.c, but dedup_propagate.overlay_files only scanned _a/_o0 — so every function in the post-whale _after region was invisible to dedup_propagate, for BOTH source-def-find (func_801770E0 → "no source overlay has it matched") AND stub-replacement in the 133 members. Fix = add _o0b/_after to the suffix list. Rule: any new per-file split suffix must be added to overlay_files or its functions silently can't propagate (a green per-overlay gate never fires because the site is never found — verify via the fleet dedup-check member count, not just the build).
(4) find_site's backward extern scan STOPS at a non-extern line — keep the extern block contiguous. func_801770E0's 5 externs had a /* comment */ on its own line between them; find_site collected only the externs below the comment and dropped the 4 above → compiles_standalone failed on undeclared callees. Relocate any standalone comment ABOVE the extern block (byte-neutral). (A trailing extern …; /* … */ comment IS tolerated; a whole comment LINE mid-block is not.)
(5) LOCAL-TYPEDEF giant → UNIQUE-rename + lift to engine_types.h, NEVER the bare name. func_801372B0 declared local SVEC/GLINE typedefs (above the fn, not in the extracted body) → compiles_standalone (common.h + engine_types.h only) failed on the undefined types. Critically, a DIFFERENT SVEC (u16 fields — a different fn) lives in _after.c, so lifting the bare name would double-define with a conflicting layout fleet-wide. Fix: rename to Svec_801372B0/Gline_801372B0 (all occurrences confirmed scoped to the fn's region first), lift the renamed types to engine_types.h (the plan-builder explicitly allows bodies USING engine_types.h types — only inline typedef/named-struct{ DEFS are rejected), byte-verify the source overlay unchanged (d19c9580), then --recover. The rename is byte-neutral (pointer-passing + struct-member codegen is layout-driven, not name-driven).
Result: func_801770E0 + func_801372B0 ×134, clean fleet 136/136, dedup 1811→1813/0, fleet 65.95→66.02% (byte-weighted gain larger — 152+207-ins giants). The giant endgame's matched set is now fully ×134; the only remaining reach-134 ×1 fns are small (3 propagatable stragglers 0x80174650/0x8012A018/0x80165CA0 + 17 local-type-blocked) = the T8 tail (Drew's focus directive: giants only, no small sweeps).