diff --git a/docs/matching-cookbook.md b/docs/matching-cookbook.md index 0cbf8af674..0dc0f1b13a 100644 --- a/docs/matching-cookbook.md +++ b/docs/matching-cookbook.md @@ -5841,3 +5841,62 @@ behemoth hides a `jal` easily.) **Standing rule of thumb:** prefer a **callee-saved** register for any pin whose variable outlives a call; if the target's register really is caller-saved and the value really does span a `jal`, the pin cannot express it — that is a genuine wall verdict, not a drafting slip. + +## §75 — A propagation cap is usually a MINORITY-SPELLING SOURCE OVERLAY, not a wall: census the carried extern before believing the exclusion message (Phase 29 SESSION-19, `func_8014F3E8` ×4 → ×138) + +`dedup_propagate` authors the shared macro from ONE source overlay and carries that overlay's +file-scope `extern` lines into the macro **verbatim**. Those externs are then instantiated in every +member TU. So **whatever spelling the source overlay happens to use becomes the fleet's spelling** — +and if the source is an outlier, the macro conflicts everywhere else and the group silently caps its +reach at the outlier's island. The exclusion message calls that `byte-diverge / irreconcilable`, +which is the wrong cause and reads like a wall. + +**The tell: the bytes cannot be diverging.** Members are selected by `h_exact` — the SHA1 of raw +instruction bytes, relocs included. If a group has N members it is because all N are byte-identical. +So an exclusion is a **compile** conflict, never a byte one. Any message saying otherwise is lying +(cf. §68's mislabel — same tool, same defect family). + +**The census that names the real cause (30 seconds, read-only).** Take the symbol the carried extern +declares and count every spelling of it across the tree: +``` +grep -rh '' src --include=*.c --include=*.h \ + | grep -E 'extern|^\s*(void|s32|int|u32)\s+\s*\(' \ + | sed -E 's/^\s+//; s/\s+/ /g; s/ \\$//' | sort | uniq -c | sort -rn +``` +Worked case — `func_8014F468`, carried by the `func_8014F3E8` body: + +| spelling | count | | +|---|---|---| +| `extern s32 func_8014F468(void);` | 1,710 | fleet canon | +| `s32 func_8014F468(void)` (def) | 134 | fleet canon | +| `extern void func_8014F468(void);` | 20 | **the outlier** | +| `void func_8014F468(void)` (def) | 4 | **the outlier — and all 4 are `ov_SC07_{006,007,010,011}`** | + +The source overlay I banked from was one of the four. The macro inherited `extern void`, and the 134 +overlays that *define* the symbol `s32` rejected it — propagation landed on exactly the 4-overlay +island. Nothing about the code was hard. + +**The fix is NORMALIZATION, not a reconciliation engine.** Flip the minority spelling to the fleet +canon (here 24 occurrences: 4 definitions + 19 overlay externs + 1 line in the freshly-authored +macro), byte-gate the affected binaries, then extend the group. `func_8014F468` is a pure inline-asm +`$sp`-switch trampoline, so the return type carries no C-level value flow — and 134 overlays already +*proved* `s32` is byte-correct for the identical function. All 4 flipped binaries stayed +byte-identical. + +**Why a reconciliation engine is the WRONG shape here.** One macro text is instantiated in 138 TUs; +it cannot carry a per-overlay extern. If the members genuinely disagree, no per-member rewrite of a +*shared* body can satisfy them all — you must make them agree first. (`reconcile_tu.fix()` already +does "TU wins + cast at use" for DATA decls and deliberately skips `d.kind == 'func'`; extending it +would not have helped, because the conflicting text lives in the shared header, not in a draft.) + +**Practice:** +1. **Prefer a majority-spelling source overlay.** Before propagating from overlay X, census X's decls + of every symbol the body carries. A minority source caps the group by construction. +2. **Always pass `--recover`** on a targeted `--addr` run. Without it, the first culprit overlay + triggers the historical all-or-nothing drop and the group banks **×0** instead of ×(N−1). This + session lost a whole group to that flag before re-running. +3. **After normalizing, the body is already a macro** — so the follow-up is `dedup_extend` + (`--binaries `), **not** `dedup_propagate --addr`, which can only author from an + *inline def* and will report "no source overlay has it matched". +4. Re-check any group historically stuck at a small reach for the same cause — `func_80174CB0` (×3 + since SESSION-18) was carrying the identical class. diff --git a/src/ov_SC07_006/ov_SC07_006_jr_80140608.c b/src/ov_SC07_006/ov_SC07_006_jr_80140608.c index 46d4ebcb91..e03a61cc3c 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_80140608.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_80140608.c @@ -4315,7 +4315,7 @@ DEFINE_func_8014F3E8() /* dedup: shared engine-core @0x8014F3E8 (src/shared) */ extern void func_8014F4C0(); -void func_8014F468(void) +s32 func_8014F468(void) { extern int D_801F4EF4; diff --git a/src/ov_SC07_006/ov_SC07_006_jr_80154C24.c b/src/ov_SC07_006/ov_SC07_006_jr_80154C24.c index a8eb75c336..226487f3a8 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_80154C24.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_80154C24.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_006/ov_SC07_006_jr_801588CC.c b/src/ov_SC07_006/ov_SC07_006_jr_801588CC.c index ff7f7fec7a..31543bab6b 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_801588CC.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_801588CC.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c b/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c index 0bc935e17c..5be48097c1 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_8015C32C.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_006/ov_SC07_006_jr_8017AE2C.c b/src/ov_SC07_006/ov_SC07_006_jr_8017AE2C.c index f364dda336..b86bb93f1d 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_8017AE2C.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_8017AE2C.c @@ -1535,7 +1535,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c b/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c index 864272ac7f..acc2708a91 100644 --- a/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c +++ b/src/ov_SC07_006/ov_SC07_006_jr_8017BEBC.c @@ -1509,7 +1509,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_007/ov_SC07_007_jr_80140608.c b/src/ov_SC07_007/ov_SC07_007_jr_80140608.c index 5abf1a5a3e..bb760c4e40 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_80140608.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_80140608.c @@ -3624,7 +3624,7 @@ DEFINE_func_8014F3E8() /* dedup: shared engine-core @0x8014F3E8 (src/shared) */ extern void func_8014F4C0(u8 *a0); -void func_8014F468(void) +s32 func_8014F468(void) { extern int D_801C665C; diff --git a/src/ov_SC07_007/ov_SC07_007_jr_80154C24.c b/src/ov_SC07_007/ov_SC07_007_jr_80154C24.c index daeb941046..1d2e2ed54b 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_80154C24.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_80154C24.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_007/ov_SC07_007_jr_801588CC.c b/src/ov_SC07_007/ov_SC07_007_jr_801588CC.c index 9a750463e3..e8be82c2d7 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_801588CC.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_801588CC.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_007/ov_SC07_007_jr_8015C32C.c b/src/ov_SC07_007/ov_SC07_007_jr_8015C32C.c index 5cb7bd5540..fbdb60df0a 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_8015C32C.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_8015C32C.c @@ -1533,7 +1533,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_007/ov_SC07_007_jr_8017AE2C.c b/src/ov_SC07_007/ov_SC07_007_jr_8017AE2C.c index 00315caf3b..dee983559e 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_8017AE2C.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_8017AE2C.c @@ -1535,7 +1535,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c b/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c index 7683b820d6..fc7c0b076b 100644 --- a/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c +++ b/src/ov_SC07_007/ov_SC07_007_jr_8017BEBC.c @@ -1509,7 +1509,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_010/ov_SC07_010_jr_80140608.c b/src/ov_SC07_010/ov_SC07_010_jr_80140608.c index 55e5dcc670..07b45c723d 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_80140608.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_80140608.c @@ -3113,7 +3113,7 @@ DEFINE_func_8014F3E8() /* dedup: shared engine-core @0x8014F3E8 (src/shared) */ extern void func_8014F4C0(u8 *a0); -void func_8014F468(void) +s32 func_8014F468(void) { extern int D_801A6B54; diff --git a/src/ov_SC07_010/ov_SC07_010_jr_80154C24.c b/src/ov_SC07_010/ov_SC07_010_jr_80154C24.c index 92031423a0..f46ee6f44c 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_80154C24.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_80154C24.c @@ -948,7 +948,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern u8 D_800D3918[]; extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); diff --git a/src/ov_SC07_010/ov_SC07_010_jr_801588CC.c b/src/ov_SC07_010/ov_SC07_010_jr_801588CC.c index 3f60216e9e..3b6570d22f 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_801588CC.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_801588CC.c @@ -948,7 +948,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern u8 D_800D3918[]; extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); diff --git a/src/ov_SC07_010/ov_SC07_010_jr_8015C32C.c b/src/ov_SC07_010/ov_SC07_010_jr_8015C32C.c index 0fe991a979..dd39853d8b 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_8015C32C.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_8015C32C.c @@ -948,7 +948,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern u8 D_800D3918[]; extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); diff --git a/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c b/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c index 6edc78c99d..fe0c2df661 100644 --- a/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c +++ b/src/ov_SC07_010/ov_SC07_010_jr_8017AE2C.c @@ -950,7 +950,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern u8 D_800D3918[]; extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); diff --git a/src/ov_SC07_011/ov_SC07_011_jr_80140608.c b/src/ov_SC07_011/ov_SC07_011_jr_80140608.c index 7d8590a49c..bee8953136 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_80140608.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_80140608.c @@ -3626,7 +3626,7 @@ DEFINE_func_8014F3E8() /* dedup: shared engine-core @0x8014F3E8 (src/shared) */ extern void func_8014F4C0(u8 *a0); -void func_8014F468(void) +s32 func_8014F468(void) { extern int D_8018F1EC; diff --git a/src/ov_SC07_011/ov_SC07_011_jr_80154C24.c b/src/ov_SC07_011/ov_SC07_011_jr_80154C24.c index f5f45d74c0..5a184a58ac 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_80154C24.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_80154C24.c @@ -1534,7 +1534,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_011/ov_SC07_011_jr_801588CC.c b/src/ov_SC07_011/ov_SC07_011_jr_801588CC.c index ae4bfb2191..cd5ca64f8a 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_801588CC.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_801588CC.c @@ -1534,7 +1534,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_011/ov_SC07_011_jr_8015C32C.c b/src/ov_SC07_011/ov_SC07_011_jr_8015C32C.c index 1710f31103..8b0aa3185d 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_8015C32C.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_8015C32C.c @@ -1534,7 +1534,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_011/ov_SC07_011_jr_8017AE2C.c b/src/ov_SC07_011/ov_SC07_011_jr_8017AE2C.c index 8a412bdf2a..19cad0725f 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_8017AE2C.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_8017AE2C.c @@ -1536,7 +1536,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/ov_SC07_011/ov_SC07_011_jr_8017BEBC.c b/src/ov_SC07_011/ov_SC07_011_jr_8017BEBC.c index 8fe78b1c6a..7a84d55835 100644 --- a/src/ov_SC07_011/ov_SC07_011_jr_8017BEBC.c +++ b/src/ov_SC07_011/ov_SC07_011_jr_8017BEBC.c @@ -1510,7 +1510,7 @@ extern s32 func_8014F2E0(s32 a0, s16 *a1, s16 *a2); extern s32 func_8014F24C(struct SubF24C *a0); extern s32 func_8014F2E0(s32 arg0, s16 * arg1, s16 * arg2); extern void func_8014F4C0(u8 *a0); -extern void func_8014F468(void); +extern s32 func_8014F468(void); extern s32 D_801152BC; extern int func_8014F74C(s32 arg0); extern s32 func_8014FA70(s32 a0); diff --git a/src/shared/engine_core.h b/src/shared/engine_core.h index 574cdbad48..8fb43a09d2 100644 --- a/src/shared/engine_core.h +++ b/src/shared/engine_core.h @@ -29296,7 +29296,7 @@ } #define DEFINE_func_8014F3E8() \ - extern void func_8014F468(void); \ + extern s32 func_8014F468(void); \ extern int func_8014F6F4(void); \ s32 func_8014F3E8(s32 param_1) \ { \