docs(joinir): Phase 33 Completion - Box Theory Modularization Summary
## Phase 33: Complete JoinIR Modularization via Box Theory (3 Phases)
This commit consolidates the comprehensive modularization work across three phases:
- Phase 33-10: Exit Line Modularization (ExitLineReconnector + ExitMetaCollector Boxes)
- Phase 33-11: Quick Wins (Pattern 4 stub clarification, unused imports cleanup)
- Phase 33-12: Large Module Modularization (split mod.rs, loop_patterns.rs restructuring)
### Phase 33-10: Exit Line Modularization (Boxes P0-P1)
**New Files**:
- `exit_line/reconnector.rs` (+130 lines): ExitLineReconnector Box
- Responsibility: Update host variable_map with remapped exit values
- Design: Phase 197-B multi-carrier support (each carrier gets specific remapped value)
- Pure side effects: Only updates builder.variable_map
- Testing: Independent unit testing possible without full merge machinery
- `exit_line/meta_collector.rs` (+102 lines): ExitMetaCollector Box
- Responsibility: Construct exit_bindings from ExitMeta + variable_map lookup
- Design: Pure function philosophy (no side effects except variable_map reads)
- Reusability: Pattern-agnostic (works for Pattern 1, 2, 3, 4)
- Algorithm: For each carrier in exit_meta, lookup host ValueId, create binding
- `exit_line/mod.rs` (+58 lines): ExitLineOrchestrator facade
- Coordination: Orchestrates Phase 6 boundary reconnection
- Architecture: Delegates to ExitLineReconnector (demonstrates Box composition)
- Documentation: Comprehensive header explaining Box Theory modularization benefits
**Modified Files**:
- `merge/mod.rs` (-91 lines): Extracted reconnect_boundary() → ExitLineReconnector
- Made exit_line module public (was mod, now pub mod)
- Phase 6 delegation: Local function call → ExitLineOrchestrator::execute()
- Added exit_bindings' join_exit_values to used_values for remapping (Phase 172-3)
- `patterns/pattern2_with_break.rs` (-20 lines): Uses ExitMetaCollector
- Removed: Manual exit_binding construction loop
- Added: Delegated ExitMetaCollector::collect() for cleaner caller code
- Benefit: Reusable collector for all pattern lowerers (Pattern 1-4)
**Design Philosophy** (Exit Line Module):
Each Box handles one concern:
- ExitLineReconnector: Updates host variable_map with exit values
- ExitMetaCollector: Constructs exit_bindings from ExitMeta
- ExitLineOrchestrator: Orchestrates Phase 6 reconnection
### Phase 33-11: Quick Wins
**Pattern 4 Stub Clarification** (+132 lines):
- Added comprehensive header documentation (106 lines)
- Made `lower()` return explicit error (not silent stub)
- Migration guide: Workarounds using Pattern 1-3
- New file: `docs/development/proposals/phase-195-pattern4.md` (implementation plan)
- Status: Formal documentation that Pattern 4 is deferred to Phase 195
**Cleanup**:
- Removed unused imports via `cargo fix` (-10 lines, 11 files)
- Files affected: generic_case_a/ (5 files), if_merge.rs, if_select.rs, etc.
### Phase 33-12: Large Module Modularization
**New Files** (Modularization):
- `if_lowering_router.rs` (172 lines): If-expression routing
- Extracted from mod.rs lines 201-423
- Routes if-expressions to appropriate JoinIR lowering strategies
- Single responsibility: If expression dispatch
- `loop_pattern_router.rs` (149 lines): Loop pattern routing
- Extracted from mod.rs lines 424-511
- Routes loop patterns to Pattern 1-4 implementations
- Design: Dispatcher pattern for pattern selection
- `loop_patterns/mod.rs` (178 lines): Pattern dispatcher + shared utilities
- Created as coordinator for per-pattern files
- Exports all pattern functions via pub use
- Utilities: Shared logic across pattern lowerers
- `loop_patterns/simple_while.rs` (225 lines): Pattern 1 lowering
- `loop_patterns/with_break.rs` (129 lines): Pattern 2 lowering
- `loop_patterns/with_if_phi.rs` (123 lines): Pattern 3 lowering
- `loop_patterns/with_continue.rs` (129 lines): Pattern 4 stub
**Modified Files** (Refactoring):
- `lowering/mod.rs` (511 → 221 lines, -57%):
- Removed try_lower_if_to_joinir() (223 lines) → if_lowering_router.rs
- Removed try_lower_loop_pattern_to_joinir() (88 lines) → loop_pattern_router.rs
- Result: Cleaner core module with routers handling dispatch
- `loop_patterns.rs` → Re-export wrapper (backward compatibility)
**Result**: Clearer code organization
- Monolithic mod.rs split into focused routers
- Large loop_patterns.rs split into per-pattern files
- Better maintainability and testability
### Phase 33: Comprehensive Documentation
**New Architecture Documentation** (+489 lines):
- File: `docs/development/architecture/phase-33-modularization.md`
- Coverage: All three phases (33-10, 33-11, 33-12)
- Content:
- Box Theory principles applied
- Complete statistics table (commits, files, lines)
- Code quality analysis
- Module structure diagrams
- Design patterns explanation
- Testing strategy
- Future work recommendations
- References to implementation details
**Source Code Comments** (+165 lines):
- `exit_line/mod.rs`: Box Theory modularization context
- `exit_line/reconnector.rs`: Design notes on multi-carrier support
- `exit_line/meta_collector.rs`: Pure function philosophy
- `pattern4_with_continue.rs`: Comprehensive stub documentation + migration paths
- `if_lowering_router.rs`: Modularization context
- `loop_pattern_router.rs`: Pattern dispatch documentation
- `loop_patterns/mod.rs`: Per-pattern structure benefits
**Project Documentation** (+45 lines):
- CLAUDE.md: Phase 33 completion summary + links
- CURRENT_TASK.md: Current state and next phases
### Metrics Summary
**Phase 33 Total Impact**:
- Commits: 5 commits (P0, P1, Quick Wins×2, P2)
- Files Changed: 15 files modified/created
- Lines Added: ~1,500 lines (Boxes + documentation + comments)
- Lines Removed: ~200 lines (monolithic extractions)
- Code Organization: 2 monolithic files → 7 focused modules
- Documentation: 1 comprehensive architecture guide created
**mod.rs Impact** (Phase 33-12 P2):
- Before: 511 lines (monolithic)
- After: 221 lines (dispatcher + utilities)
- Reduction: -57% (290 lines extracted)
**loop_patterns.rs Impact** (Phase 33-12 P2):
- Before: 735 lines (monolithic)
- After: 5 files in loop_patterns/ (178 + 225 + 129 + 123 + 129)
- Improvement: Per-pattern organization
### Box Theory Principles Applied
1. **Single Responsibility**: Each Box handles one concern
- ExitLineReconnector: variable_map updates
- ExitMetaCollector: exit_binding construction
- if_lowering_router: if-expression dispatch
- loop_pattern_router: loop pattern dispatch
- Per-pattern files: Individual pattern lowering
2. **Clear Boundaries**: Public/private visibility enforced
- Boxes have explicit input/output contracts
- Module boundaries clearly defined
- Re-exports for backward compatibility
3. **Replaceability**: Boxes can be swapped/upgraded independently
- ExitLineReconnector can be optimized without affecting ExitMetaCollector
- Per-pattern files can be improved individually
- Router logic decoupled from lowering implementations
4. **Testability**: Smaller modules easier to unit test
- ExitMetaCollector can be tested independently
- ExitLineReconnector mockable with simple boundary
- Pattern lowerers isolated in separate files
### Design Patterns Introduced
1. **Facade Pattern**: ExitLineOrchestrator
- Single-entry point for Phase 6 reconnection
- Hides complexity of multi-step process
- Coordinates ExitLineReconnector + other steps
2. **Dispatcher Pattern**: if_lowering_router + loop_pattern_router
- Centralized routing logic
- Easy to add new strategies
- Separates dispatch from implementation
3. **Pure Function Pattern**: ExitMetaCollector::collect()
- No side effects (except reading variable_map)
- Easy to test, reason about, parallelize
- Reusable across all pattern lowerers
### Testing Strategy
- **Unit Tests**: Can test ExitMetaCollector independently
- **Integration Tests**: Verify boundary reconnection works end-to-end
- **Regression Tests**: Pattern 2 simple loop still passes
- **Backward Compatibility**: All existing imports still work
### Future Work
- **Phase 33-13**: Consolidate whitespace utilities (expected -100 lines)
- **Phase 34**: Extract inline_boundary validators (expected 3h effort)
- **Phase 35**: Mark loop_patterns_old.rs as legacy and remove (Phase 35+)
- **Phase 195**: Implement Pattern 4 (continue) fully
- **Phase 200+**: More complex loop patterns and optimizations
🧱 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 04:03:42 +09:00
|
|
|
//! # Loop Pattern JoinIR Lowering Router
|
2025-12-07 03:26:06 +09:00
|
|
|
//!
|
docs(joinir): Phase 33 Completion - Box Theory Modularization Summary
## Phase 33: Complete JoinIR Modularization via Box Theory (3 Phases)
This commit consolidates the comprehensive modularization work across three phases:
- Phase 33-10: Exit Line Modularization (ExitLineReconnector + ExitMetaCollector Boxes)
- Phase 33-11: Quick Wins (Pattern 4 stub clarification, unused imports cleanup)
- Phase 33-12: Large Module Modularization (split mod.rs, loop_patterns.rs restructuring)
### Phase 33-10: Exit Line Modularization (Boxes P0-P1)
**New Files**:
- `exit_line/reconnector.rs` (+130 lines): ExitLineReconnector Box
- Responsibility: Update host variable_map with remapped exit values
- Design: Phase 197-B multi-carrier support (each carrier gets specific remapped value)
- Pure side effects: Only updates builder.variable_map
- Testing: Independent unit testing possible without full merge machinery
- `exit_line/meta_collector.rs` (+102 lines): ExitMetaCollector Box
- Responsibility: Construct exit_bindings from ExitMeta + variable_map lookup
- Design: Pure function philosophy (no side effects except variable_map reads)
- Reusability: Pattern-agnostic (works for Pattern 1, 2, 3, 4)
- Algorithm: For each carrier in exit_meta, lookup host ValueId, create binding
- `exit_line/mod.rs` (+58 lines): ExitLineOrchestrator facade
- Coordination: Orchestrates Phase 6 boundary reconnection
- Architecture: Delegates to ExitLineReconnector (demonstrates Box composition)
- Documentation: Comprehensive header explaining Box Theory modularization benefits
**Modified Files**:
- `merge/mod.rs` (-91 lines): Extracted reconnect_boundary() → ExitLineReconnector
- Made exit_line module public (was mod, now pub mod)
- Phase 6 delegation: Local function call → ExitLineOrchestrator::execute()
- Added exit_bindings' join_exit_values to used_values for remapping (Phase 172-3)
- `patterns/pattern2_with_break.rs` (-20 lines): Uses ExitMetaCollector
- Removed: Manual exit_binding construction loop
- Added: Delegated ExitMetaCollector::collect() for cleaner caller code
- Benefit: Reusable collector for all pattern lowerers (Pattern 1-4)
**Design Philosophy** (Exit Line Module):
Each Box handles one concern:
- ExitLineReconnector: Updates host variable_map with exit values
- ExitMetaCollector: Constructs exit_bindings from ExitMeta
- ExitLineOrchestrator: Orchestrates Phase 6 reconnection
### Phase 33-11: Quick Wins
**Pattern 4 Stub Clarification** (+132 lines):
- Added comprehensive header documentation (106 lines)
- Made `lower()` return explicit error (not silent stub)
- Migration guide: Workarounds using Pattern 1-3
- New file: `docs/development/proposals/phase-195-pattern4.md` (implementation plan)
- Status: Formal documentation that Pattern 4 is deferred to Phase 195
**Cleanup**:
- Removed unused imports via `cargo fix` (-10 lines, 11 files)
- Files affected: generic_case_a/ (5 files), if_merge.rs, if_select.rs, etc.
### Phase 33-12: Large Module Modularization
**New Files** (Modularization):
- `if_lowering_router.rs` (172 lines): If-expression routing
- Extracted from mod.rs lines 201-423
- Routes if-expressions to appropriate JoinIR lowering strategies
- Single responsibility: If expression dispatch
- `loop_pattern_router.rs` (149 lines): Loop pattern routing
- Extracted from mod.rs lines 424-511
- Routes loop patterns to Pattern 1-4 implementations
- Design: Dispatcher pattern for pattern selection
- `loop_patterns/mod.rs` (178 lines): Pattern dispatcher + shared utilities
- Created as coordinator for per-pattern files
- Exports all pattern functions via pub use
- Utilities: Shared logic across pattern lowerers
- `loop_patterns/simple_while.rs` (225 lines): Pattern 1 lowering
- `loop_patterns/with_break.rs` (129 lines): Pattern 2 lowering
- `loop_patterns/with_if_phi.rs` (123 lines): Pattern 3 lowering
- `loop_patterns/with_continue.rs` (129 lines): Pattern 4 stub
**Modified Files** (Refactoring):
- `lowering/mod.rs` (511 → 221 lines, -57%):
- Removed try_lower_if_to_joinir() (223 lines) → if_lowering_router.rs
- Removed try_lower_loop_pattern_to_joinir() (88 lines) → loop_pattern_router.rs
- Result: Cleaner core module with routers handling dispatch
- `loop_patterns.rs` → Re-export wrapper (backward compatibility)
**Result**: Clearer code organization
- Monolithic mod.rs split into focused routers
- Large loop_patterns.rs split into per-pattern files
- Better maintainability and testability
### Phase 33: Comprehensive Documentation
**New Architecture Documentation** (+489 lines):
- File: `docs/development/architecture/phase-33-modularization.md`
- Coverage: All three phases (33-10, 33-11, 33-12)
- Content:
- Box Theory principles applied
- Complete statistics table (commits, files, lines)
- Code quality analysis
- Module structure diagrams
- Design patterns explanation
- Testing strategy
- Future work recommendations
- References to implementation details
**Source Code Comments** (+165 lines):
- `exit_line/mod.rs`: Box Theory modularization context
- `exit_line/reconnector.rs`: Design notes on multi-carrier support
- `exit_line/meta_collector.rs`: Pure function philosophy
- `pattern4_with_continue.rs`: Comprehensive stub documentation + migration paths
- `if_lowering_router.rs`: Modularization context
- `loop_pattern_router.rs`: Pattern dispatch documentation
- `loop_patterns/mod.rs`: Per-pattern structure benefits
**Project Documentation** (+45 lines):
- CLAUDE.md: Phase 33 completion summary + links
- CURRENT_TASK.md: Current state and next phases
### Metrics Summary
**Phase 33 Total Impact**:
- Commits: 5 commits (P0, P1, Quick Wins×2, P2)
- Files Changed: 15 files modified/created
- Lines Added: ~1,500 lines (Boxes + documentation + comments)
- Lines Removed: ~200 lines (monolithic extractions)
- Code Organization: 2 monolithic files → 7 focused modules
- Documentation: 1 comprehensive architecture guide created
**mod.rs Impact** (Phase 33-12 P2):
- Before: 511 lines (monolithic)
- After: 221 lines (dispatcher + utilities)
- Reduction: -57% (290 lines extracted)
**loop_patterns.rs Impact** (Phase 33-12 P2):
- Before: 735 lines (monolithic)
- After: 5 files in loop_patterns/ (178 + 225 + 129 + 123 + 129)
- Improvement: Per-pattern organization
### Box Theory Principles Applied
1. **Single Responsibility**: Each Box handles one concern
- ExitLineReconnector: variable_map updates
- ExitMetaCollector: exit_binding construction
- if_lowering_router: if-expression dispatch
- loop_pattern_router: loop pattern dispatch
- Per-pattern files: Individual pattern lowering
2. **Clear Boundaries**: Public/private visibility enforced
- Boxes have explicit input/output contracts
- Module boundaries clearly defined
- Re-exports for backward compatibility
3. **Replaceability**: Boxes can be swapped/upgraded independently
- ExitLineReconnector can be optimized without affecting ExitMetaCollector
- Per-pattern files can be improved individually
- Router logic decoupled from lowering implementations
4. **Testability**: Smaller modules easier to unit test
- ExitMetaCollector can be tested independently
- ExitLineReconnector mockable with simple boundary
- Pattern lowerers isolated in separate files
### Design Patterns Introduced
1. **Facade Pattern**: ExitLineOrchestrator
- Single-entry point for Phase 6 reconnection
- Hides complexity of multi-step process
- Coordinates ExitLineReconnector + other steps
2. **Dispatcher Pattern**: if_lowering_router + loop_pattern_router
- Centralized routing logic
- Easy to add new strategies
- Separates dispatch from implementation
3. **Pure Function Pattern**: ExitMetaCollector::collect()
- No side effects (except reading variable_map)
- Easy to test, reason about, parallelize
- Reusable across all pattern lowerers
### Testing Strategy
- **Unit Tests**: Can test ExitMetaCollector independently
- **Integration Tests**: Verify boundary reconnection works end-to-end
- **Regression Tests**: Pattern 2 simple loop still passes
- **Backward Compatibility**: All existing imports still work
### Future Work
- **Phase 33-13**: Consolidate whitespace utilities (expected -100 lines)
- **Phase 34**: Extract inline_boundary validators (expected 3h effort)
- **Phase 35**: Mark loop_patterns_old.rs as legacy and remove (Phase 35+)
- **Phase 195**: Implement Pattern 4 (continue) fully
- **Phase 200+**: More complex loop patterns and optimizations
🧱 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 04:03:42 +09:00
|
|
|
//! **Phase 33-12 Modularization**: Extracted from `mod.rs` (lines 424-511)
|
|
|
|
|
//!
|
|
|
|
|
//! ## Responsibility
|
|
|
|
|
//! Routes loop patterns to appropriate JoinIR lowering strategies.
|
|
|
|
|
//! This is the **main entry point** for loop → JoinIR lowering.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Pattern Dispatch
|
|
|
|
|
//! Routes to:
|
|
|
|
|
//! - Pattern 1: `loop_patterns::simple_while` (no break/continue)
|
|
|
|
|
//! - Pattern 2: `loop_patterns::with_break` (conditional break)
|
|
|
|
|
//! - Pattern 3: `loop_patterns::with_if_phi` (if + PHI merging)
|
|
|
|
|
//! - Pattern 4: `loop_patterns::with_continue` (deferred to Phase 195)
|
|
|
|
|
//!
|
|
|
|
|
//! ## Why Separate Router?
|
|
|
|
|
//! See `if_lowering_router.rs` for rationale.
|
|
|
|
|
//! Summary: Orthogonal concerns, easier to maintain/extend.
|
2025-12-07 03:26:06 +09:00
|
|
|
//!
|
|
|
|
|
//! # Routing Strategy
|
|
|
|
|
//!
|
|
|
|
|
//! This router uses structure-based pattern classification (Phase 194):
|
|
|
|
|
//! 1. Extract CFG features from LoopForm
|
2025-12-08 22:17:06 +09:00
|
|
|
//! 2. Classify into pattern kind (1-4 or Unknown) using `loop_pattern_detection::classify`
|
2025-12-07 03:26:06 +09:00
|
|
|
//! 3. Route to appropriate pattern lowerer
|
|
|
|
|
//!
|
2025-12-08 22:17:06 +09:00
|
|
|
//! # Phase 183: Unified Detection
|
|
|
|
|
//!
|
|
|
|
|
//! This router shares pattern detection logic with `patterns/router.rs`.
|
|
|
|
|
//! Both use `loop_pattern_detection::classify()` for consistent classification.
|
|
|
|
|
//!
|
2025-12-07 03:26:06 +09:00
|
|
|
//! # Pattern Priority (Phase 188)
|
|
|
|
|
//!
|
|
|
|
|
//! Patterns are tried in complexity order:
|
|
|
|
|
//! - **Pattern 4: Continue** (highest complexity)
|
|
|
|
|
//! - **Pattern 3: If-Else PHI** (leverages If lowering)
|
|
|
|
|
//! - **Pattern 2: Break** (medium complexity)
|
|
|
|
|
//! - **Pattern 1: Simple While** (foundational, easiest)
|
|
|
|
|
//!
|
|
|
|
|
//! # Integration Points
|
|
|
|
|
//!
|
|
|
|
|
//! Called from:
|
feat(llvm): Phase 132-P0 - block_end_values tuple-key fix for cross-function isolation
## Problem
`block_end_values` used block ID only as key, causing collisions when
multiple functions share the same block IDs (e.g., bb0 in both
condition_fn and main).
## Root Cause
- condition_fn's bb0 → block_end_values[0]
- main's bb0 → block_end_values[0] (OVERWRITES!)
- PHI resolution gets wrong snapshot → dominance error
## Solution (Box-First principle)
Change key from `int` to `Tuple[str, int]` (func_name, block_id):
```python
# Before
block_end_values: Dict[int, Dict[int, ir.Value]]
# After
block_end_values: Dict[Tuple[str, int], Dict[int, ir.Value]]
```
## Files Modified (Python - 6 files)
1. `llvm_builder.py` - Type annotation update
2. `function_lower.py` - Pass func_name to lower_blocks
3. `block_lower.py` - Use tuple keys for snapshot save/load
4. `resolver.py` - Add func_name parameter to resolve_incoming
5. `wiring.py` - Thread func_name through PHI wiring
6. `phi_manager.py` - Debug traces
## Files Modified (Rust - cleanup)
- Removed deprecated `loop_to_join.rs` (297 lines deleted)
- Updated pattern lowerers for cleaner exit handling
- Added lifecycle management improvements
## Verification
- ✅ Pattern 1: VM RC: 3, LLVM Result: 3 (no regression)
- ⚠️ Case C: Still has dominance error (separate root cause)
- Needs additional scope fixes (phi_manager, resolver caches)
## Design Principles
- **Box-First**: Each function is an isolated Box with scoped state
- **SSOT**: (func_name, block_id) uniquely identifies block snapshots
- **Fail-Fast**: No cross-function state contamination
## Known Issues (Phase 132-P1)
Other function-local state needs same treatment:
- phi_manager.predeclared
- resolver caches (i64_cache, ptr_cache, etc.)
- builder._jump_only_blocks
## Documentation
- docs/development/current/main/investigations/phase132-p0-case-c-root-cause.md
- docs/development/current/main/investigations/phase132-p0-tuple-key-implementation.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:36:50 +09:00
|
|
|
//! - `loop_to_join::LoopToJoinLowerer::lower_loop()`
|
2025-12-07 03:26:06 +09:00
|
|
|
//! - `loop_form_intake.rs::handle_loop_form()`
|
|
|
|
|
|
|
|
|
|
use crate::mir::join_ir::JoinInst;
|
|
|
|
|
use crate::mir::loop_form::LoopForm;
|
|
|
|
|
|
|
|
|
|
/// Phase 188: Try to lower loop to JoinIR using pattern-based approach
|
|
|
|
|
///
|
|
|
|
|
/// This function routes loop lowering to specific pattern handlers based on
|
|
|
|
|
/// loop structure characteristics. It tries patterns in order of complexity:
|
|
|
|
|
///
|
|
|
|
|
/// 1. **Pattern 1: Simple While** (foundational, easiest)
|
|
|
|
|
/// 2. **Pattern 2: Break** (medium complexity)
|
|
|
|
|
/// 3. **Pattern 3: If-Else PHI** (leverages existing If lowering)
|
|
|
|
|
/// 4. **Pattern 4: Continue** (highest complexity)
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `loop_form` - The loop structure to lower
|
|
|
|
|
/// * `lowerer` - The LoopToJoinLowerer builder (provides ValueId allocation, etc.)
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// * `Some(JoinInst)` - Successfully lowered to JoinIR
|
|
|
|
|
/// * `None` - No pattern matched (fallback to existing lowering)
|
|
|
|
|
///
|
|
|
|
|
/// # Pattern Selection Strategy
|
|
|
|
|
///
|
|
|
|
|
/// Patterns are tried sequentially. First matching pattern wins.
|
|
|
|
|
/// If no pattern matches, returns `None` to trigger fallback.
|
|
|
|
|
///
|
|
|
|
|
/// ## Pattern 1: Simple While Loop
|
|
|
|
|
/// - **Condition**: Empty break/continue targets, single latch
|
|
|
|
|
/// - **Handler**: `loop_patterns::lower_simple_while_to_joinir()`
|
|
|
|
|
/// - **Priority**: First (most common, simplest)
|
|
|
|
|
///
|
|
|
|
|
/// ## Pattern 2: Loop with Conditional Break
|
|
|
|
|
/// - **Condition**: Non-empty break_targets, exactly 1 break
|
|
|
|
|
/// - **Handler**: `loop_patterns::lower_loop_with_break_to_joinir()`
|
|
|
|
|
/// - **Priority**: Second (common, medium complexity)
|
|
|
|
|
///
|
|
|
|
|
/// ## Pattern 3: Loop with If-Else PHI
|
|
|
|
|
/// - **Condition**: Empty break/continue, if-else in body
|
|
|
|
|
/// - **Handler**: `loop_patterns::lower_loop_with_conditional_phi_to_joinir()`
|
|
|
|
|
/// - **Priority**: Third (reuses If lowering infrastructure)
|
|
|
|
|
///
|
|
|
|
|
/// ## Pattern 4: Loop with Continue
|
|
|
|
|
/// - **Condition**: Non-empty continue_targets
|
|
|
|
|
/// - **Handler**: `loop_patterns::lower_loop_with_continue_to_joinir()`
|
|
|
|
|
/// - **Priority**: Fourth (most complex)
|
|
|
|
|
///
|
|
|
|
|
/// # Integration Point
|
|
|
|
|
///
|
|
|
|
|
/// This function should be called from loop lowering entry points:
|
feat(llvm): Phase 132-P0 - block_end_values tuple-key fix for cross-function isolation
## Problem
`block_end_values` used block ID only as key, causing collisions when
multiple functions share the same block IDs (e.g., bb0 in both
condition_fn and main).
## Root Cause
- condition_fn's bb0 → block_end_values[0]
- main's bb0 → block_end_values[0] (OVERWRITES!)
- PHI resolution gets wrong snapshot → dominance error
## Solution (Box-First principle)
Change key from `int` to `Tuple[str, int]` (func_name, block_id):
```python
# Before
block_end_values: Dict[int, Dict[int, ir.Value]]
# After
block_end_values: Dict[Tuple[str, int], Dict[int, ir.Value]]
```
## Files Modified (Python - 6 files)
1. `llvm_builder.py` - Type annotation update
2. `function_lower.py` - Pass func_name to lower_blocks
3. `block_lower.py` - Use tuple keys for snapshot save/load
4. `resolver.py` - Add func_name parameter to resolve_incoming
5. `wiring.py` - Thread func_name through PHI wiring
6. `phi_manager.py` - Debug traces
## Files Modified (Rust - cleanup)
- Removed deprecated `loop_to_join.rs` (297 lines deleted)
- Updated pattern lowerers for cleaner exit handling
- Added lifecycle management improvements
## Verification
- ✅ Pattern 1: VM RC: 3, LLVM Result: 3 (no regression)
- ⚠️ Case C: Still has dominance error (separate root cause)
- Needs additional scope fixes (phi_manager, resolver caches)
## Design Principles
- **Box-First**: Each function is an isolated Box with scoped state
- **SSOT**: (func_name, block_id) uniquely identifies block snapshots
- **Fail-Fast**: No cross-function state contamination
## Known Issues (Phase 132-P1)
Other function-local state needs same treatment:
- phi_manager.predeclared
- resolver caches (i64_cache, ptr_cache, etc.)
- builder._jump_only_blocks
## Documentation
- docs/development/current/main/investigations/phase132-p0-case-c-root-cause.md
- docs/development/current/main/investigations/phase132-p0-tuple-key-implementation.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 05:36:50 +09:00
|
|
|
/// - `loop_to_join::LoopToJoinLowerer::lower_loop()`
|
2025-12-07 03:26:06 +09:00
|
|
|
/// - `loop_form_intake.rs::handle_loop_form()`
|
|
|
|
|
///
|
|
|
|
|
/// # Example Usage
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,ignore
|
|
|
|
|
/// use crate::mir::join_ir::lowering::try_lower_loop_pattern_to_joinir;
|
|
|
|
|
///
|
|
|
|
|
/// // In loop lowering entry point:
|
|
|
|
|
/// if let Some(joinir_inst) = try_lower_loop_pattern_to_joinir(&loop_form, &mut lowerer) {
|
|
|
|
|
/// // Pattern matched, use JoinIR
|
|
|
|
|
/// return Some(joinir_inst);
|
|
|
|
|
/// }
|
|
|
|
|
/// // No pattern matched, use existing lowering
|
|
|
|
|
/// existing_loop_lowering(&loop_form, &mut lowerer)
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Reference
|
|
|
|
|
///
|
|
|
|
|
/// See design.md for complete pattern specifications and transformation rules:
|
|
|
|
|
/// `docs/private/roadmap2/phases/phase-188-joinir-loop-pattern-expansion/design.md`
|
|
|
|
|
pub fn try_lower_loop_pattern_to_joinir(
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
lowerer: &mut crate::mir::join_ir::lowering::LoopToJoinLowerer,
|
|
|
|
|
) -> Option<JoinInst> {
|
|
|
|
|
// Phase 194: Structure-based pattern classification
|
|
|
|
|
// Tries patterns based on CFG structure, not function names
|
|
|
|
|
|
|
|
|
|
use crate::mir::loop_pattern_detection::{classify, extract_features, LoopPatternKind};
|
|
|
|
|
|
|
|
|
|
// Step 1: Extract features from LoopForm (no LoopScope needed for now)
|
|
|
|
|
let features = extract_features(loop_form, None);
|
|
|
|
|
|
|
|
|
|
// Step 2: Classify pattern based on structure
|
|
|
|
|
let pattern = classify(&features);
|
|
|
|
|
|
|
|
|
|
// Step 3: Route to appropriate lowerer based on pattern
|
|
|
|
|
match pattern {
|
|
|
|
|
LoopPatternKind::Pattern4Continue => {
|
2025-12-11 20:54:33 +09:00
|
|
|
if let Some(inst) =
|
|
|
|
|
super::loop_patterns::lower_loop_with_continue_to_joinir(loop_form, lowerer)
|
|
|
|
|
{
|
2025-12-07 03:26:06 +09:00
|
|
|
eprintln!("[try_lower_loop_pattern] ✅ Pattern 4 (Continue) matched");
|
|
|
|
|
return Some(inst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LoopPatternKind::Pattern3IfPhi => {
|
2025-12-11 20:54:33 +09:00
|
|
|
if let Some(inst) =
|
|
|
|
|
super::loop_patterns::lower_loop_with_conditional_phi_to_joinir(loop_form, lowerer)
|
|
|
|
|
{
|
2025-12-07 03:26:06 +09:00
|
|
|
eprintln!("[try_lower_loop_pattern] ✅ Pattern 3 (If-Else PHI) matched");
|
|
|
|
|
return Some(inst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LoopPatternKind::Pattern2Break => {
|
2025-12-11 20:54:33 +09:00
|
|
|
if let Some(inst) =
|
|
|
|
|
super::loop_patterns::lower_loop_with_break_to_joinir(loop_form, lowerer)
|
|
|
|
|
{
|
2025-12-07 03:26:06 +09:00
|
|
|
eprintln!("[try_lower_loop_pattern] ✅ Pattern 2 (Break) matched");
|
|
|
|
|
return Some(inst);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LoopPatternKind::Pattern1SimpleWhile => {
|
2025-12-11 20:54:33 +09:00
|
|
|
if let Some(inst) =
|
|
|
|
|
super::loop_patterns::lower_simple_while_to_joinir(loop_form, lowerer)
|
|
|
|
|
{
|
2025-12-07 03:26:06 +09:00
|
|
|
eprintln!("[try_lower_loop_pattern] ✅ Pattern 1 (Simple While) matched");
|
|
|
|
|
return Some(inst);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-14 09:59:34 +09:00
|
|
|
LoopPatternKind::InfiniteEarlyExit => {
|
|
|
|
|
// Phase 131-11: Not implemented yet in LoopForm-based router
|
|
|
|
|
eprintln!("[try_lower_loop_pattern] ⚠️ Pattern 5 (InfiniteEarlyExit) not implemented in LoopForm router");
|
|
|
|
|
}
|
2025-12-07 03:26:06 +09:00
|
|
|
LoopPatternKind::Unknown => {
|
|
|
|
|
eprintln!("[try_lower_loop_pattern] ❌ Unknown pattern, fallback to existing lowering");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No Pattern Matched (fallback to existing lowering)
|
|
|
|
|
// ===================================================
|
|
|
|
|
eprintln!("[try_lower_loop_pattern] ❌ Pattern lowering failed, fallback to existing lowering");
|
|
|
|
|
None
|
|
|
|
|
}
|