Files
hakorune/docs/development/current/main/phase33-16-INDEX.md
nyash-codex a7dbc15878 feat(joinir): Phase 240-EX - Pattern2 header condition ExprLowerer integration
Implementation:
- Add make_pattern2_scope_manager() helper for DRY
- Header conditions use ExprLowerer for supported patterns
- Legacy fallback for unsupported patterns
- Fail-Fast on supported patterns that fail

Tests:
- 4 new tests (all pass)
- test_expr_lowerer_supports_simple_header_condition_i_less_literal
- test_expr_lowerer_supports_header_condition_var_less_var
- test_expr_lowerer_header_condition_generates_expected_instructions
- test_pattern2_header_condition_via_exprlowerer

Also: Archive old phase documentation (34k lines removed)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 00:33:04 +09:00

272 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Status: Active
Scope: Phase 33-16Loop Header PHI SSOTに関する現役目次。歴史詳細は archive 側を参照。
# Phase 33-16: Loop Header PHI SSOT - Documentation Index
**Last Updated**: 2025-12-07
**Status**: ✅ Complete implementation design ready
## Quick Navigation
### For Implementation
**Start here**: [phase33-16-visual-guide.md](phase33-16-visual-guide.md)
- Architecture flow diagram (all 7 phases)
- Code change map with exact line numbers
- 7 complete code changes (copy-paste ready)
- Testing commands
### For Understanding
**Read first**: [phase33-16-qa.md](phase33-16-qa.md)
- Answer to all 5 core questions
- Exact code snippets with explanations
- "What you DON'T need" guidance
- Complete flow summary
### For Context
**Detailed planning**: [phase33-16-implementation-plan.md](phase33-16-implementation-plan.md)
- Executive summary
- Problem analysis
- 6 concrete implementation steps
- Testing strategy
- Risk analysis and mitigation
- Future enhancements
### Quick Summary
**Reference**: [PHASE_33_16_SUMMARY.md](PHASE_33_16_SUMMARY.md)
- TL;DR answers
- Architecture evolution
- Implementation scope
- Key architectural insight
- Testing roadmap
### Original Design
**Background**: [phase33-16-loop-header-phi-design.md](phase33-16-loop-header-phi-design.md)
- Original design document
- Problem statement
- Solution overview
---
## Your 5 Questions - Direct Answers
### Q1: Where exactly should LoopHeaderPhiBuilder::build() be called?
**Location**: `src/mir/builder/control_flow/joinir/merge/mod.rs`, line 107
**When**: Between Phase 3 (remap_values) and Phase 4 (instruction_rewriter)
**Why**: Phase 3.5 allocates PHI dsts before instruction_rewriter needs them
**Details**: [phase33-16-qa.md#q1](phase33-16-qa.md#q1-where-exactly-should-loopheaderphibuilderbuilld-be-called)
### Q2: How do I get the header_block_id (loop_step's entry block after remapping)?
**Code**: `remapper.get_block(entry_func_name, entry_func.entry_block)?`
**Key**: Entry block is the loop header for Pattern 2
**Details**: [phase33-16-qa.md#q2](phase33-16-qa.md#q2-how-do-i-get-the-header_block_id-loops-entry-block-after-remapping)
### Q3: How do I get the loop variable's initial value (host-side)?
**Code**: `remapper.get_value(ValueId(0))?`
**Key**: ValueId(0) is always the loop parameter in JoinIR space
**Details**: [phase33-16-qa.md#q3](phase33-16-qa.md#q3-how-do-i-get-the-loop-variables-initial-value-host-side)
### Q4: Where should instruction_rewriter record latch_incoming?
**Location**: `src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs`, ~line 300
**When**: In tail call section, after parameter bindings
**Code**: `loop_header_phi_info.set_latch_incoming(loop_var_name, target_block, latch_value)`
**Details**: [phase33-16-qa.md#q4](phase33-16-qa.md#q4-where-should-instruction_rewriter-record-latch_incoming)
### Q5: Should the Phase 33-15 skip logic be removed or modified?
**Answer**: **Modify, NOT remove**
**Strategy**: Use header PHI dst when available, fallback to parameter
**Details**: [phase33-16-qa.md#q5](phase33-16-qa.md#q5-should-the-phase-33-15-skip-logic-be-removed-or-modified-to-use-header-phi-dst)
---
## Implementation at a Glance
### Files to Modify
- `src/mir/builder/control_flow/joinir/merge/mod.rs` (2 locations: Phase 3.5, Phase 4.5)
- `src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs` (5 locations: signature, latch tracking, exit logic)
### Changes Summary
| Phase | What | Where | Type |
|-------|------|-------|------|
| 3.5 | Build header PHIs | merge/mod.rs | New |
| 4 | Update signature | instruction_rewriter.rs | Signature |
| 4 | Track latch | instruction_rewriter.rs | New code |
| 4 | Use PHI for exit | instruction_rewriter.rs | Modified |
| 4 | Use PHI for carriers | instruction_rewriter.rs | Modified |
| 4.5 | Finalize PHIs | merge/mod.rs | New |
### Scope
- **Lines added**: ~100
- **Lines modified**: ~100
- **Lines removed**: 0 (backward compatible)
- **New files**: 0 (uses existing LoopHeaderPhiBuilder)
---
## Architecture Diagram
```
Phase 3: remap_values()
↓ (ValueIds remapped: 0→100, 0→101, etc.)
Phase 3.5: LoopHeaderPhiBuilder::build() ⭐ NEW
└── Allocate phi_dst(101), entry_incoming(init_value)
└── Pass loop_header_phi_info to Phase 4
Phase 4: instruction_rewriter::merge_and_rewrite()
├── When tail call: set_latch_incoming()
└── When Return: use phi_dst (not parameter)
Phase 4.5: LoopHeaderPhiBuilder::finalize() ⭐ NEW
└── Emit PHIs into header block
Phase 5: exit_phi_builder::build_exit_phi()
└── Return carrier_phis with header PHI dsts
Phase 6: ExitLineOrchestrator::execute()
└── Update variable_map with carrier_phis
```
---
## Testing Checklist
Before implementation:
- [ ] Review phase33-16-qa.md (answers to your questions)
- [ ] Review phase33-16-visual-guide.md (code locations)
- [ ] Baseline compile: `cargo build --release`
During implementation:
- [ ] Implement Phase 3.5 → compile
- [ ] Update signature → compile
- [ ] Add latch tracking → compile
- [ ] Replace exit_phi_inputs → compile
- [ ] Replace carrier_inputs → compile
- [ ] Add Phase 4.5 → compile
- [ ] Update docs → compile
After implementation:
- [ ] `NYASH_JOINIR_DEBUG=1 ./target/release/nyash --dump-mir test.hako | grep "Phase 33-16"`
- [ ] Verify header block has PHI instructions at start
- [ ] Verify exit values reference header PHI dsts
- [ ] Test: `joinir_min_loop.hako` produces correct MIR
- [ ] Test: Loop variable values correct at exit
---
## Document Quick Links
### Complete Guides (in order of use)
1. **phase33-16-qa.md** (11 KB)
- Start here for understanding
- All 5 questions answered
- Code examples ready to copy-paste
2. **phase33-16-visual-guide.md** (22 KB)
- Use during implementation
- Architecture diagrams
- Complete code changes with line numbers
- Copy-paste ready code
3. **phase33-16-implementation-plan.md** (18 KB)
- For detailed planning
- Risk analysis
- Testing strategy
- Future enhancements
4. **PHASE_33_16_SUMMARY.md** (8.2 KB)
- Quick reference
- TL;DR answers
- Key insights
- Next steps
### Reference Documents
5. **phase33-16-loop-header-phi-design.md** (9.0 KB)
- Original design document
- Historical context
---
## Key Concepts
### Loop Header PHI as SSOT (Single Source of Truth)
The core idea: Instead of using undefined loop parameters, use PHI nodes at the loop header to track the "current value" of loop variables.
**Why it works**:
- PHI nodes ARE SSA-defined at the header block
- PHI dsts can safely be referenced in exit values
- Eliminates SSA-undef errors from undefined parameters
**Architecture**:
- **Phase 3.5**: Pre-allocate PHI dsts (before instruction processing)
- **Phase 4**: Set latch incoming during instruction processing
- **Phase 4.5**: Finalize PHIs with all incoming edges
- **Phase 6**: Use PHI dsts in exit line reconnection
### Two-Phase PHI Construction
**Phase 3.5: build()** - Allocate PHI dsts
```rust
let phi_dst = builder.next_value_id(); // Allocate
entry_incoming = (entry_block, init_value); // Set entry
latch_incoming = None; // Will be set in Phase 4
```
**Phase 4.5: finalize()** - Emit PHI instructions
```rust
PHI {
dst: phi_dst, // Already allocated
inputs: [
(entry_block, init_value), // From Phase 3.5
(header_block, latch_value), // From Phase 4
]
}
```
---
## Known Limitations & Future Work
### Phase 33-16 (Current)
✅ Minimal scope: Loop variable only, no other carriers
✅ Pattern 2 primary focus (break statements)
✅ Backward compatible with Phase 33-15
### Phase 33-16+ (Future)
- [ ] Extract multiple carriers from exit_bindings
- [ ] Handle Pattern 3+ with multiple PHIs
- [ ] Pattern-specific header block identification
- [ ] Optimize constant carriers
---
## Support & Debugging
### If implementation breaks:
1. **Compilation error**: Check if loop_header_phi_info is properly passed as mutable reference
2. **SSA-undef error**: Check if finalize() is called and all latch_incoming are set
3. **Wrong values**: Check if latch_incoming is set from correct tail call args
4. **No header PHI**: Enable `NYASH_JOINIR_DEBUG=1` and check "Phase 33-16" output
### Debug commands:
```bash
# Check debug output
NYASH_JOINIR_DEBUG=1 ./target/release/nyash --dump-mir test.hako 2>&1 | grep "Phase 33-16"
# Inspect MIR
./target/release/nyash --emit-mir-json mir.json test.hako
jq '.functions[0].blocks[0].instructions[0:3]' mir.json
```
---
## Next Phase: Phase 34+
After Phase 33-16 is complete:
1. Pattern 4 (continue statement) implementation
2. Trim patterns with complex carriers
3. Loop-as-expression full integration
4. Performance optimizations
---
**Ready to implement?** Start with [phase33-16-qa.md](phase33-16-qa.md)!