Files
BFM-decomp/tools
Drew T 3e0028c2ed feat(phase-30 S47-F2b): group-level draft-vs-draft data aliasing (83 aliased, 5 banked)
family_sweep stages every member of an (overlay, split) group into ONE TU before gating, so two
templated bodies routinely carry different views of one address — D_80114F24 is `s32` in one body
and `Vec8` in another. scope_data_fix is handed one draft plus the pre-splice TU and structurally
cannot see the others, so that collision was invisible to it.

_alias_group_data_conflicts(): after staging, any data symbol a group's drafts declare with >=2
distinct types gets a PER-DRAFT §37 asm-label alias. The alias is suffixed with the function name
(aD80114F24_8017B880) — aliasing both drafts to a shared name would re-create the same collision at
one remove, which the unit test exists to catch. Each body keeps its own type: for data the declared
type drives the load (lh vs lhu), so canonicalising would silently change codegen for every other
view. Codegen unchanged — the asm label pins the emitted symbol.

83 conflicts aliased across 172 groups; banked 2 -> 5. R22 clean-fleet 213 passed / 0 failed of 213.

WHY THE HEADLINE SYMBOLS DID NOT MOVE — root cause now CONFIRMED, not inferred. D_80114F24 (12)
and D_800AE620 (10) are unchanged because the conflicting declaration is MACRO-INJECTED:
`extern Vec8 D_80114F24;` lives inside a DEFINE_ macro in engine_core.h (D_800AE620 has 6 such),
while the overlay .c holds only DEFINE_func_XXXX() invocations. Neither a scan of the staged drafts
nor a scan of the TU text can see it — that needs the preprocessed TU. The sweep already does
exactly this for CALLEES (cast_call_sites' canonical map is cpp-derived "so it sees macro-injected
declarations"); the data path never got it.

This collapses F2's remainder and F4 into one fix: memcpy's 26 failures are the same shape — task B
found nine `extern void *memcpy(...)` spellings inside those same DEFINE_ macros. A cpp-derived
declaration map feeds both, and the alias mechanism is already built and control-tested; only the
detection SOURCE is wrong. For memcpy the alias is the documented house solution, not a workaround
(engine_core.h:24480 hand-writes `extern void func_8005C324(...) __asm__("memcpy")`).

Four attempts on this class for 5 members: three mechanisms proposed before reading what the
compiler actually complained about. The mechanisms are correct; they targeted the wrong collision.
2026-08-10 22:24:13 -06:00
..