cc phase 3: re-admit Cast store RHS (ledger class 2, last class)#606
Open
bboe wants to merge 3 commits into
Open
cc phase 3: re-admit Cast store RHS (ledger class 2, last class)#606bboe wants to merge 3 commits into
bboe wants to merge 3 commits into
Conversation
…minals (phase 3) The Block(Assign(expr=Cast)) def shape — the lowering of a cast store RHS (p->field = (T)x) — now sinks into its AX-clobbering store terminal exactly like the Index/BinaryOperation classes, replaying the Cast through generate_expression at the terminal's post-materialization RHS slot (identity codegen, no spill/reload). The reads_ir_temp operand guard is shared with the index-term twin via the new module-level _ast_node_reads_ir_temp helper. Byte-neutral until Cast is admitted as a byte-safe store RHS (Task 2): no [Block(Cast); Address; Store] triple exists in the corpus yet, so the extension collects nothing and the per-function byte gate stays 0-delta. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ledger check: re-admit Cast; readdir must be 0-delta or shrink, nothing else may change. Measured result: readdir 248 -> 248 (0-delta), and the per-function byte-size gate reports zero deltas across all 361 functions. Task 1 (93e038e) extended the store-RHS value sink to the ir.Block(Assign(Cast)) def shape. This change adds ast_nodes.Cast to the _is_byte_safe_store_rhs admission tuple, which makes the sink fire on the chained-member cast store (directory->entry.d_ino = (ino_t)d_ino in readdir). The store's plan is the AX-clobbering chained-member arm, so the value sink's preserve=False gate fires and Task 1's Block-Cast sink replays the cast at the terminal RHS slot -- legacy-parity, no cast-temp spill. Hand-diff of readdir asm (cc.py --bits 32 --object --per-function-sections) at the parent commit 93e038e vs HEAD: the readdir .text section bodies are byte-identical (103 lines, IDENTICAL unified diff). The would-be +6 spill/reload around the address resolution never appears -- the d_ino cast store stays the legacy inline sequence: lea eax, [ebx+12] ; chained-member base (AX-clobbering) mov ebx, eax mov esi, edx movzx eax, byte [esi+6] ; (ino_t)d_ino cast load, replayed at RHS slot mov byte [ebx+4], al ; terminal store No def-spill (mov [ebp-N], eax) then reload (mov eax, [ebp-N]) brackets the address resolution. The earlier docstring premise that Cast was excluded because Store.width was the dropped-width fix is falsified: casts are codegen-identity, the store width is the lvalue's field width (unchanged by the cast), and the real regression was a cast-temp spill the Task 1 sink erases. Docstring updated accordingly. All four ledger classes are now cashed (class 1 BinaryOperation, class 3 Index, class 4 compound-index in phase 2; class 2 Cast here in phase 3). Verification: - tests/test_cc_function_sizes.py: PASS (361 functions, readdir 0-delta) - tests/unit: 898 passed, 1 xfailed - pre-commit codesorter: Passed - tests/test_cc_bits.py: 122 passed, 0 failed - tests/test_cc_place.py: golden byte-identical (no re-bless) - tests/test_programs.py (bbfs): 104 passed, 0 failed (ls exercises readdir) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-admit Cast store RHS via the cast Block(Assign(Cast)) store-RHS sink; readdir 0-delta; all four ledger classes now cashed at byte parity. The design-specs errata records that the Store.width premise was corrected (the regression was a cast-temp spill, not a dropped width). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 3 of the native-Address emission refactor — re-admits the last ledger class (class 2:
Caststore RHS). With this, all four store-RHS ledger classes (1/2/3/4) are cashed at.text-size parity. Design + plan + errata on thedesign-specsbranch (2026-06-19-cc-native-address-emission-phase3-plan.md).The corrected mechanism
Reconnaissance falsified the design's
Store.widthpremise:ir.Storealready has a vestigial unusedwidthfield, and thereaddir+6 was never a width drop — it was a cast-temp spill across address resolution (the same class-1/3/4 anatomy phase 2 erased with the store-RHS sink). ACaststore RHS lowers toir.Block(Assign(Cast)), which the phase-2 sink couldn't reach. So phase 3 extends the value sink to that Block def shape, mirroring the existing_collect_ir_sunk_index_termsBlock handling.Store.widthstays vestigial (a removal candidate); narrowing-cast truncation is a separate deferred gap belonging in the cast codegen, not onStore. Full rationale in the design-specs errata.Commits
sink cast store-RHS Block defs— extend_collect_ir_sunk_store_values/_emit_sunk_store_value/ the Block suppression toBlock(Assign(Cast))defs; share the_ast_node_reads_ir_tempwalker. Byte-neutral (no Cast admitted yet).re-admit Cast store RHS— addast_nodes.Castto_is_byte_safe_store_rhs.readdir0-delta (the +6 spill erased by commit 1's sink).phase-3 close-out— CHANGELOG.Verification
.textbyte gate 0-delta (361 functions, 49 files) at every commit; unit 898 passed;cc_bits122/122;cc_placegolden;asm50/50;bboefs6/6;programsbbfs 104/104 + ext2 134/134. Codesorter clean; sorting audit SORTED CLEAN; whole-branch review APPROVED (one finding below).Known caveat (whole-branch review finding, not gate-visible)
An accumulator-preserving cast store whose value rides AX still reserves an unused frame slot —
grow_heap(sub esp20→24) andstrtol(108→112), +4 bytes of stack each. The.textcode bytes are identical (the gate can't see it —sub esp, Nis encoding-length-neutral), and the slot is correctness-clean (never read). This is a pre-existing slot-allocation pattern (main'sreleasealready has gap slots) that Cast admission extends by two sites. Recovering it — excluding ax-riding single-use store-RHS temps from frame allocation, which also helps phase 2's preserve-plan sites — is a tracked follow-up, orthogonal to this re-admission.🤖 Generated with Claude Code