Conversation
- virtual_stack.rs — spill logic uses emit_store_int/emit_store_bool/emit_store_float_bits/emit_stack_gep - inline/ops.rs — all 10 functions rewritten: comparison, binary arithmetic, float ops, bitwise, shifts, unary intrinsics Remaining: - inline/dispatch.rs — 60+ occurrences (biggest file, but same patterns already handled by helpers) - control_flow.rs — 3 occurrences - statements.rs — 2 occurrences - specialization.rs — likely no changes needed
Wired up (using layout helpers): - virtual_stack.rs — spill logic - inline/ops.rs — all arithmetic, comparison, bitwise, shift, intrinsic ops (10 functions) - control_flow.rs — if/else condition loading - statements.rs — main exit code reading Remaining: - inline/dispatch.rs — 60+ occurrences (biggest file, same patterns) That's the last codegen file. dispatch.rs is 1192 lines with the same GEP/slot patterns repeated for dup, swap, over, rot, nip, tuck, roll, pick, and/or/not, aux stack ops, etc. Same mechanical substitution but large. Want to get the PR reviewed as-is with this solid foundation, or push through dispatch.rs first?
|
test |
|
PLACEHOLDER - will replace |
Code Review: Virtual Stack (PR 360)This is a solid refactoring PR that extracts repeated LLVM IR generation patterns into well-named helpers. The net -165 lines while adding layout-aware helpers is a meaningful improvement. Positives: Consistent emit_* naming convention. Good doc comments explaining 40-byte vs tagged-ptr semantics. Centralizing layout-dependent logic in layout.rs. Substantial boilerplate reduction in ops.rs and control_flow.rs. Issue 1 - emit_load_two_float_operands inconsistent return value: The function returns (ptr_a, slot1_a, val_a, val_b) but the semantics of the second element differ by mode: in 40-byte mode it is slot1_a (different from ptr_a); in tagged-ptr mode it is just ptr_a.clone() (redundant). One call site already ignores it with _slot1_a. Consider a named struct. Issue 2 - Unimplemented tagged-ptr float handling silently generates incorrect code: Both emit_load_two_float_operands and emit_store_float_bits have TODO branches in tagged-ptr mode that fall back to raw bit operations. These will silently produce incorrect IR if tagged-ptr mode is used with floats. Prefer todo!() / unimplemented!() to make failures loud rather than silent. Issue 3 - Weakened test assertion in mod.rs: Before: assert!(ir.contains("trunc i64 %result to i32")); After: two separate contains checks for "trunc i64 %" and "to i32". These can now pass even if the two strings appear in unrelated instructions. A line-level check would be stronger: assert!(ir.lines().any(|l| l.contains("trunc i64 %") && l.contains("to i32"))); Issue 4 - discriminant() suppressed with allow(dead_code) rather than removed: The spill code no longer calls it. Either remove it or add a comment explaining which future path needs it. Minor Nits: emit_store_float_result parameter slot1_or_ptr leaks layout internals to callers; store_target would be more neutral. No new unit tests for emit_* helpers in layout.rs. Summary: Good refactor overall. Main actionable items: (1) Use todo!() for tagged-ptr float TODOs instead of silently wrong fallbacks. (2) Strengthen the weakened test assertion in mod.rs. (3) Remove or properly document discriminant(). |
…──────────────────────────────────────────────────────────────────────────────────┐ │ Review Item │ Action │ ├────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 1. Float operand return inconsistency │ Renamed slot1_or_ptr to store_target │ ├────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 2. Silent incorrect code for │ Replaced all three TODO fallbacks with todo!() — will panic loudly │ │ tagged-ptr floats │ │ ├────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 3. Weakened test assertion │ Strengthened to line-level check: ir.lines().any(|l| l.contains(...) && l.contains(...)) │ ├────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 4. discriminant() dead code │ Removed entirely │ ├────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 5. Missing unit tests for new helpers │ Added 7 tests: load_two_int_operands (both modes), load_top_int, store_int_result_in_place (both modes), │ │ │ float tagged-ptr panic tests │ └────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
PR Review: Virtual Stack (#360)This is a solid refactoring that significantly reduces code duplication by centralizing layout-specific LLVM IR generation into helper methods in What's Good
Issues1. Duplicate doc comment on The doc comment has two opening lines that describe the same thing — looks like an old draft wasn't fully removed: /// Store a float result (as double) at the given stack pointer.
/// In 40-byte mode: stores bits to slot1 (discriminant 1 already at slot0).
/// Store a float result (as double) at the given store target. // <-- leftover
The first two lines should be dropped or merged with the third. 2.
// Prefer this pattern:
return Err(CodeGenError::Unimplemented("tagged-ptr float load".into()));
// Over:
todo!("tagged-ptr float load not yet implemented")(The existing 3. Leaky abstraction: The function returns let (ptr_a, _slot1_a, val_a, val_b) = self.emit_load_two_float_operands(stack_var)?;The A cleaner approach would be to return an opaque 4. The parameter is called Minor Nits
SummaryThe core refactoring direction is correct and the result is clearly better than before. The main things worth addressing before merging:
Happy to discuss the float API design if helpful. |
…──────────────────────────────────────────────────────────────────────────────────┐ │ Review Item │ Action │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 1. Duplicate doc comment │ Removed the stale first line │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 2. todo!() → │ All three float paths now return Err(CodeGenError::Logic(...)) instead of panicking. Tests updated from should_panic to │ │ Err(CodeGenError) │ is_err() checks │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 3. slot1_a leakage │ emit_load_two_float_operands now returns (ptr_a, val_a, val_b) — 3-tuple, no slot1. emit_store_float_result takes ptr_a │ │ │ and computes slot1 internally. Callers simplified │ ├───────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │ 4. store_target naming │ Parameter renamed to ptr_a — matches what callers pass │ └───────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
PR Review: Virtual Stack Layout Helpers This is a clean, well-executed refactoring. The core idea - centralising LLVM IR generation into layout-aware helpers in layout.rs - is the right design. Net -110 lines with better abstraction and dual-mode (40-byte / tagged-ptr) support is a solid outcome. Strengths
Issue 1: Duplicate GEP in control_flow.rs top_ptr and popped_stack are identical GEPs (same base, offset -1). This emits two getelementptr instructions to the same address. LLVM deduplicates at -O1+ but it is noise at -O0. Since top_ptr IS the new SP after the pop, reusing it directly drops the redundant call. The original code had this same issue. Issue 2: Unnecessary else in emit_store_float_bits and emit_store_float_result Both functions early-return Err in the tagged-ptr branch but still wrap the non-tagged path in an else block. The else is dead after the return. Idiomatic Rust drops it and lets the non-tagged path fall through to Ok(()). Issue 3: dispatch.rs is the acknowledged remaining gap 60+ occurrences of the same GEP pattern in dispatch.rs are not yet migrated. Fine as a staged approach but worth a follow-up issue to ensure full adoption. Issue 4: Weakened test assertion in mod.rs is correct but could use a comment Changed from ir.contains("trunc i64 %result to i32") to the more permissive lines().any() form. Necessary because the SSA name is now a fresh temp rather than the hardcoded %result. A brief comment would help future readers. Summary Solid foundation. Issues 1 and 2 are easy fixes. Issues 3 and 4 are awareness items. Great direction overall. |
…──────────────────────────┐ │ Item │ Action │ ├─────────────────────┼───────────────────────────────────────────────────────────────────────┤ │ 1. Duplicate GEP │ Reuse top_ptr via .clone() instead of emitting a second identical GEP │ ├─────────────────────┼───────────────────────────────────────────────────────────────────────┤ │ 2. Unnecessary else │ Removed from emit_store_float_bits — early return then fall through │ ├─────────────────────┼───────────────────────────────────────────────────────────────────────┤ │ 3. dispatch.rs gap │ Acknowledged — next PR │ ├─────────────────────┼───────────────────────────────────────────────────────────────────────┤ │ 4. Test comment │ Added comment explaining why the assertion uses line-level matching │ └─────────────────────┴───────────────────────────────────────────────────────────────────────┘
PR Review: Virtual Stack Layout HelpersThis is a clean, well-executed refactoring. Layout helpers in layout.rs nicely abstract the 40-byte vs. tagged-pointer representation differences, and the net reduction of ~110 lines while making each call site more readable is a solid win. Positive observations
Issues and suggestions
Minor nits
Summary Ready to merge. The missing 40-byte float tests (item 2) are the most impactful gap; the rest is documentation and tracking hygiene. Ideal to add those tests before merge, but including them in the dispatch.rs follow-up is also reasonable. |
No description provided.