Promote daObjRcCarpet_c as a compiler-owned C++ TU - #2104
Conversation
✅ PR validation — PassedCommitted merge passes; 8 contributor credit reassignment(s) noted, not a blocker. Full merge validation
Contributor credit moved (8)
Byte-verified means the range carries Warnings: contributor attribution changed, not a blocker (8 changed, 0 lost -- src/actors/daObjRcCarpet_c.cpp: tangosdev -> github-actions[bot]; src/actors/daObjRcCarpet_c.cpp: tangosdev -> github-actions[bot]; src/actors/daObjRcCarpet_c.cpp: tangosdev -> github-actions[bot]; +5 more); 9 address range(s) left the byte-verified set while enrolled totals held steady: ov036:0x02112158-0x021121c8, ov036:0x021121c8-0x0211224c, ov036:0x0211224c-0x021122c0, ov036:0x021122c0-0x02112318, ov036:0x02112318-0x02112378, +4 more; 8 more function(s) now claim a match that nothing compiles; enroll them in a delinks.txt to have the ROM build check them. Per-file link-check detailAll 1 changed file(s) compile to the ROM byte-for-byte with correct relocation targets.
The private worker commits a test merge, builds the stock ROM profile, compares every executable module, measures matched and source-built code, checks contributor lineage, and verifies affected relocations. The mod profile is opt-in and is not part of this merge gate. |
29d9a52 to
ef612ac
Compare
andrewboudreau
left a comment
There was a problem hiding this comment.
Reviewed at ef612aca2. The promotion itself is clean and I checked it hard. One change requested, on the two coined symbol names — and not for the reason I expected when I started. I went looking for a convention-consistency problem and found a correctness one instead, so this comment is mostly the measurement.
What is solid
The class name is ROM-proven. 15daObjRcCarpet_c is present in extracted/overlays/overlay_0036.bin; FlyingCarpet is absent. So the promotion is not name-blocked on the class, which is what stopped PoleLift in #2066.
FlyingCarpet_* is not your debt. FlyingCarpet_Spawn / FlyingCarpet_SpawnInfo are on origin/main today across eleven tracked files. You inherited them and correctly left them alone. Out of scope here, and I am not asking for them.
The converted-baseline moves as a clean SET, not a loss.
base count 2570 head count 2570
REMOVED (3) ADDED (3)
src/_ZN15daObjRcCarpet_c6RenderEv.cpp -> src/actors/daObjRcCarpet_c.cpp#_ZN15daObjRcCarpet_c6RenderEv
src/_ZN15daObjRcCarpet_cD0Ev.cpp -> src/actors/daObjRcCarpet_c.cpp#_ZN15daObjRcCarpet_cD0Ev
src/_ZN15daObjRcCarpet_cD1Ev.cpp -> src/actors/daObjRcCarpet_c.cpp#_ZN15daObjRcCarpet_cD1Ev
Three-for-three per-member rewrite, count flat. That is the shape a promoted TU is supposed to make, and the nine // @symbol markers are what earn it.
Static gates, on the real merge tree, both ways:
vs origin/tools/intact-tu-section-order 8/8 pass -> pass (entries 10789 -> 10782, -7)
vs origin/main 8/8 pass -> pass (entries 10814 -> 10782, -32)
Nothing goes green → red on either base.
The delink consolidation is right. Nine .text ranges collapse into one contiguous 0x02112158..0x021125b0, matching the manifest's linker run exactly, and the TU picks up .data 0x02113f4c..0x02114020. Slots 16/17 of the vtable are 0x02112158 / 0x021121c8 — your D1 and D0, at the head of the run — so the out-of-line destructor really is the key function and the compiler-emitted vtable is legitimately this TU's to own.
Change requested: RcCarpet_VT22 and RcCarpet_VT29 name a phantom
-data_ov036_02113ff4 kind:data(any) addr:0x02113ff4 ambiguous
-data_ov036_02114010 kind:data(any) addr:0x02114010 ambiguous
+RcCarpet_VT22 kind:data(any) addr:0x02113ff4 ambiguous
+RcCarpet_VT29 kind:data(any) addr:0x02114010 ambiguous
The slot arithmetic is correct, and that is exactly what makes this dangerous. _ZTV15daObjRcCarpet_c is at 0x02113f9c; +22*4 = 0x02113ff4 and +29*4 = 0x02114010. Both check out. A reader will believe these names.
1. They are not objects. They are interior words of one contiguous vtable.
Dumped from overlay_0036.bin (base 0x021111a0), the table runs 0x02113f9c..0x02114020 — 33 words, every one a code address, with no structural break anywhere:
slot16 0x02112158 <- D1, this TU slot21 0x02010148
slot17 0x021121c8 <- D0, this TU slot22 0x02010144 <- "RcCarpet_VT22"
slot18 0x02010160 slot23 0x02010140
slot19 0x02010154 ...
slot20 0x0201014c slot29 0x02010124 <- "RcCarpet_VT29"
Slots 18–30 are a monotonically descending run of arm9 addresses — inherited base virtuals. Slots 22 and 29 are ordinary members of that run. Nothing distinguishes them.
2. Nothing about the vtable explains why symbols exist there.
Every one of the 33 slots carries a relocation. Twenty of them target main:
slot18 from:0x02113fe4 to:0x02010160 module:main
slot21 from:0x02113ff0 to:0x02010148 module:main
slot22 from:0x02113ff4 to:0x02010144 module:main <- has a symbol
slot23 from:0x02113ff8 to:0x02010140 module:main <- does not
slot29 from:0x02114010 to:0x02010124 module:main <- has a symbol
slot30 from:0x02114014 to:0x020100dc module:main <- does not
If the symbols came from the vtable's own relocations, twenty slots would have them. Two do. So the cause is somewhere else.
3. The cause is overlay aliasing, and the referent belongs to another overlay.
0x02113ff4 occurs as a word exactly once in the whole cartridge — arm9_dec.bin at file offset 0x8c9dc. 0x02114010 occurs at 0x8c998. Both sit inside a dense pointer table: 83 of the 96 surrounding words are 0x0211xxxx addresses.
Ten overlays load at the same base and all cover both addresses:
ov014 ov015 ov016 ov020 ov021 ov022 ov029 ov034 ov036 base 0x021111a0
ov075 base 0x02113ee0
They are mutually exclusive actor overlays sharing one address window, so that arm9 table resolves into whichever one is resident. dsd cannot tell which, so it fanned a symbol into every overlay's table — data_ov014_02113ff4, data_ov015_02113ff4, and so on, including ov036's.
And in two of those overlays the address already has a real, meaningful name in tracked config:
config/arm9/overlays/ov029/symbols.txt RotatingPlatformWdw_SpawnInfo addr:0x02113ff4
config/arm9/overlays/ov022/symbols.txt LavaSeesaw_SpawnInfo addr:0x02114010
SpawnInfo objects, reached from an arm9 spawn-info dispatch table. That is a coherent story for what arm9 word 0x8c9dc actually points at. daObjRcCarpet_c's vtable slot 22 is not.
4. The rename note also inverts the direction
inferred compatibility alias for the ROM relocation target at vtable slot 22
In config/arm9/overlays/ov036/relocs.txt this address is a relocation source, not a target:
from:0x02113ff4 kind:load to:0x02010144 module:main
The target is 0x02010144 in main. Minor next to the above, but it is in the row that a future reader will use to decide whether to trust the name.
The ask
Revert both rows to data_ov036_02113ff4 / data_ov036_02114010 — symbols.txt and the two symbols/actor_renames.tsv rows.
The neutral names are phantoms too, but they assert nothing. RcCarpet_VT22 asserts that daObjRcCarpet_c has a data object at its own vtable slot 22, which is not true in any sense, and a coined name that manufactures evidence is the thing that blocks data verification later.
I want to be fair about intent: "compatibility alias … exact source spelling is not preserved" shows you knew these were not real source symbols, and that hedge is the right instinct. The problem is that the note stays in the TSV while the name travels into symbols.txt, the manifest, and every downstream tool.
Nothing here threatens the byte match — intact-object mode takes the whole .data section wholesale, so the interior split does not reach the output, and I expect the validator to be green. That is the point: this is a config-truth defect the byte gates structurally cannot see.
Note, not an ask
These two symbols truncate _ZTV15daObjRcCarpet_c's extent to 22 words when the real table is 33. That is the same shape as the _ZTV14dScMgD3DBase_c truncation already open on my side, it predates this PR, and reverting the names does not fix it. Please don't try to fix it here — the extent change trips a ratchet and wants its own PR. I only mention it so the next person to touch ov036 knows the extent is not to be trusted.
Ordering
Stack is #2096 → #2103 → #2104.
- #2096 still carries CHANGES REQUESTED from me over
FlyGuy_VT7/FlyGuy_VT14; re-measured at28587e4e5and both are still present. Same family of issue as above, which is why I want the convention settled once rather than three times. - #2103 I have reviewed and it is ready on content, held only on its base.
- #2104 is cut from #2103 and lands third.
Worth saying plainly that this PR is the reason #2103 exists — #2103's own test fixture asserts it still reproduces "RcCarpet's measured RTTI/resource inversion". The pairing is sound; the ordering is just forced.
Everything else in this one I checked and it holds.
589dddc to
6ef413a
Compare
andrewboudreau
left a comment
There was a problem hiding this comment.
Heads-up from the merge lane, not a content objection: this PR went DIRTY when #2103 and #2125 landed. Nothing about the review verdict changes.
git merge-tree --write-tree origin/main <head> on the current tips:
#2062 CONFLICT (content): notes/cpp-tu-current-state.md
#2104 CONFLICT (content): attribution.json
CONFLICT (content): notes/cpp-tu-current-state.md
Both files are the standing serial chokepoint for this lane — every TU promotion rewrites them, so any two TU PRs in flight collide there regardless of how disjoint their source is.
Do not hand-resolve notes/cpp-tu-current-state.md. It carries its own instruction at the top:
<!-- Generated by tools/cpp_tu_state.py. Do not hand-edit live counts. -->
Take either side to clear the marker, then regenerate and check:
python tools/cpp_tu_state.py --write-note
python tools/cpp_tu_state.py --check-note
Hand-merging it produces a file that is textually plausible and numerically wrong — the counts are derived from the post-merge tree, not from either parent, so neither side's numbers are right and a hunk-by-hunk resolution splices two stale snapshots. --check-note is what catches that.
attribution.json is the other one: it conflicts three-way, not as a key union. Resolving it by taking the union of keys silently drops the third parent's edits. Attribution is a stated non-goal here, so if it fights you, take main's and move on rather than spending time on it.
Once you push the restack I'll re-run the gates on the new merge tree and pick the review back up where it stands.
ef612ac to
0a5171c
Compare
|
Reviewer requests are resolved on refreshed head
The fresh production build is exact: 11,088/11,088 functions, 5/5 source-owned data claims, 106/106 modules, zero mismatches, stock ROM SHA-256 |
7a8f1dd to
c77441b
Compare
0a5171c to
66b9839
Compare
|
Restacked and revalidated in head
Fresh proof: exact ROM ( |
Promotes the original ov036
daObjRcCarpet_ctranslation unit: nine legacy source files become onesrc/actors/daObjRcCarpet_c.cppowning text0x02112158..0x021125b0and data0x02113f4c..0x02114020. The compiler emits D1/D0, RTTI, the type name, and the vtable. C ABI remains only at the ROM's unmangled factory, SpawnInfo, two unnamed helpers, and the measured manual construction seam required for allocator/relocation fidelity.Reviewer follow-up:
mainafter merged Promote daPropeller_Heyho_c as a compiler-owned C++ TU #2096; the obsolete FlyGuy parent stack is gonenotes/cpp-tu-current-state.mdfrom the post-rebase tree rather than hand-resolving itdata_ov036_02113ff4/data_ov036_02114010aliasesRcCarpet_VT22/RcCarpet_VT29rowsFresh validation on head
66b9839b49ddovermain4006a7835994:d1506e90efae5e2d2cf119926a4ac2a291bd5ca78349d09d5024e1a918c478e8NO-SYMwarning, 0 blockingThe
attribution-overridelabel remains applied per project policy. No claims, attempt-ledger, or dashboard artifacts are included.