Files
hakorune/src/mir/builder/control_flow/joinir/merge/mod.rs

310 lines
12 KiB
Rust
Raw Normal View History

refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
//! JoinIR MIR Block Merging Coordinator
//!
//! This module coordinates the merging of JoinIR-generated MIR functions
//! into the host MIR builder. The process is broken into 6 phases:
//!
//! 1. Block ID allocation (block_allocator.rs)
//! 2. Value collection (value_collector.rs)
//! 3. ValueId remapping (uses JoinIrIdRemapper)
//! 4. Instruction rewriting (instruction_rewriter.rs)
//! 5. Exit PHI construction (exit_phi_builder.rs)
//! 6. Boundary reconnection (inline in this file)
//!
//! Phase 4 Refactoring: Breaking down 714-line merge_joinir_mir_blocks() into focused modules
mod block_allocator;
mod value_collector;
mod instruction_rewriter;
mod exit_phi_builder;
pub mod exit_line;
mod loop_header_phi_info;
mod loop_header_phi_builder;
mod tail_call_classifier;
mod merge_result;
// Phase 33-17: Re-export for use by other modules
pub use merge_result::MergeResult;
pub use tail_call_classifier::{TailCallKind, classify_tail_call};
pub use loop_header_phi_info::{LoopHeaderPhiInfo, CarrierPhiEntry};
pub use loop_header_phi_builder::LoopHeaderPhiBuilder;
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
use crate::mir::{BasicBlockId, MirModule, ValueId};
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
/// Phase 49-3.2: Merge JoinIR-generated MIR blocks into current_function
///
/// # Phase 189: Multi-Function MIR Merge
///
/// This merges JoinIR-generated blocks by:
/// 1. Remapping all block IDs across ALL functions to avoid conflicts
/// 2. Remapping all value IDs across ALL functions to avoid conflicts
/// 3. Adding all blocks from all functions to current_function
/// 4. Jumping from current_block to the entry block
/// 5. Converting Return → Jump to exit block for all functions
///
/// **Multi-Function Support** (Phase 189):
/// - Pattern 1 (Simple While) generates 3 functions: entry + loop_step + k_exit
/// - All functions are flattened into current_function with global ID remapping
/// - Single exit block receives all Return instructions from all functions
///
/// # Phase 188-Impl-3: JoinInlineBoundary Support
///
/// When `boundary` is provided, injects Copy instructions at the entry block
/// to connect host ValueIds to JoinIR local ValueIds:
///
/// ```text
/// entry_block:
/// // Injected by boundary
/// ValueId(100) = Copy ValueId(4) // join_input → host_input
/// // Original JoinIR instructions follow...
/// ```
///
/// This enables clean separation: JoinIR uses local IDs (0,1,2...),
/// host uses its own IDs, and Copy instructions bridge the gap.
///
/// # Returns
///
/// Returns `Ok(Some(exit_phi_id))` if the merged JoinIR functions have return values
/// that were collected into an exit block PHI. さらに、`boundary` に
/// host_outputs が指定されている場合は、exit PHI の結果をホスト側の
/// SSA スロットへ再接続するvariable_map 内の ValueId を更新する)。
pub(in crate::mir::builder) fn merge_joinir_mir_blocks(
builder: &mut crate::mir::builder::MirBuilder,
mir_module: &MirModule,
boundary: Option<&JoinInlineBoundary>,
debug: bool,
) -> Result<Option<ValueId>, String> {
if debug {
eprintln!(
"[cf_loop/joinir] merge_joinir_mir_blocks called with {} functions",
mir_module.functions.len()
);
}
// Phase 1: Allocate block IDs for all functions
let mut remapper = block_allocator::allocate_blocks(builder, mir_module, debug)?;
// Phase 2: Collect values from all functions
let (mut used_values, value_to_func_name, function_params) =
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
value_collector::collect_values(mir_module, &remapper, debug)?;
// Phase 171-fix: Add condition_bindings' join_values to used_values for remapping
if let Some(boundary) = boundary {
for binding in &boundary.condition_bindings {
if debug {
eprintln!(
"[cf_loop/joinir] Phase 171-fix: Adding condition binding '{}' JoinIR {:?} to used_values",
binding.name, binding.join_value
);
}
used_values.insert(binding.join_value);
}
// Phase 172-3: Add exit_bindings' join_exit_values to used_values for remapping
for binding in &boundary.exit_bindings {
if debug {
eprintln!(
"[cf_loop/joinir] Phase 172-3: Adding exit binding '{}' JoinIR {:?} to used_values",
binding.carrier_name, binding.join_exit_value
);
}
used_values.insert(binding.join_exit_value);
}
}
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
// Phase 3: Remap ValueIds
remap_values(builder, &used_values, &mut remapper, debug)?;
// Phase 3.5: Build loop header PHIs (if loop pattern with loop_var_name)
//
// We need to know PHI dsts before instruction_rewriter runs, so that:
// 1. Tail call handling can set latch_incoming
// 2. Return handling can use PHI dsts for exit values
let (entry_func_name, entry_func) = mir_module
.functions
.iter()
.next()
.ok_or("JoinIR module has no functions (Phase 3.5)")?;
let entry_block_remapped = remapper
.get_block(entry_func_name, entry_func.entry_block)
.ok_or_else(|| format!("Entry block not found for {} (Phase 3.5)", entry_func_name))?;
// Phase 33-16: Get host's current block as the entry edge (the block that jumps INTO the loop)
let host_entry_block = builder.current_block.ok_or(
"Phase 33-16: No current block when building header PHIs"
)?;
let mut loop_header_phi_info = if let Some(boundary) = boundary {
if let Some(loop_var_name) = &boundary.loop_var_name {
// Phase 33-16: Get loop variable's initial value from HOST (not JoinIR's ValueId(0))
// boundary.host_inputs[0] is the host ValueId that holds the initial loop var value
let loop_var_init = boundary.host_inputs.first().copied().ok_or(
"Phase 33-16: No host_inputs in boundary for loop_var_init"
)?;
if debug {
eprintln!(
"[cf_loop/joinir] Phase 3.5: Building header PHIs for loop_var='{}' at {:?}",
loop_var_name, entry_block_remapped
);
eprintln!(
"[cf_loop/joinir] loop_var_init={:?} (from boundary.host_inputs[0])",
loop_var_init
);
eprintln!(
"[cf_loop/joinir] host_entry_block={:?} (where initial value comes from)",
host_entry_block
);
}
let phi_info = LoopHeaderPhiBuilder::build(
builder,
entry_block_remapped, // header_block (JoinIR's entry block = loop header)
host_entry_block, // entry_block (host's block that jumps to loop header)
loop_var_name,
loop_var_init,
&[], // No other carriers for Pattern 2 (loop var is the only carrier)
boundary.expr_result.is_some(), // expr_result_is_loop_var
debug,
)?;
// Phase 33-16: Override remapper so that JoinIR's loop var parameter (ValueId(0))
// references the PHI dst instead of a separate remapped value.
// This ensures all uses of the loop variable in the loop body use the PHI result.
if let Some(phi_dst) = phi_info.get_carrier_phi(loop_var_name) {
// JoinIR uses ValueId(0) for loop var in loop_step's first parameter
// After remapping, we want those uses to refer to the header PHI dst
remapper.set_value(ValueId(0), phi_dst);
if debug {
eprintln!(
"[cf_loop/joinir] Phase 33-16: Override remap ValueId(0) → {:?} (PHI dst)",
phi_dst
);
}
}
phi_info
} else {
LoopHeaderPhiInfo::empty(entry_block_remapped)
}
} else {
LoopHeaderPhiInfo::empty(entry_block_remapped)
};
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
// Phase 4: Merge blocks and rewrite instructions
// Phase 33-16: Pass mutable loop_header_phi_info for latch_incoming tracking
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
let merge_result = instruction_rewriter::merge_and_rewrite(
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
builder,
mir_module,
&mut remapper,
&value_to_func_name,
&function_params,
boundary,
&mut loop_header_phi_info,
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
debug,
)?;
// Phase 4.5: Finalize loop header PHIs (insert into header block)
//
// By now, instruction_rewriter has set latch_incoming for all carriers.
// We can finalize the PHIs and insert them into the header block.
if !loop_header_phi_info.carrier_phis.is_empty() {
if debug {
eprintln!(
"[cf_loop/joinir] Phase 4.5: Finalizing {} header PHIs",
loop_header_phi_info.carrier_phis.len()
);
}
LoopHeaderPhiBuilder::finalize(
builder,
&loop_header_phi_info,
debug,
)?;
}
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
// Phase 5: Build exit PHI (expr result and carrier PHIs)
// Phase 33-13: Now also builds carrier PHIs and returns their mapping
let (exit_phi_result_id, carrier_phis) = exit_phi_builder::build_exit_phi(
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
builder,
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
merge_result.exit_block_id,
&merge_result.exit_phi_inputs,
&merge_result.carrier_inputs,
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
debug,
)?;
// Phase 6: Reconnect boundary (if specified)
// Phase 197-B: Pass remapper to enable per-carrier exit value lookup
// Phase 33-10-Refactor-P3: Delegate to ExitLineOrchestrator
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
// Phase 33-13: Pass carrier_phis for proper variable_map update
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
if let Some(boundary) = boundary {
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
exit_line::ExitLineOrchestrator::execute(builder, boundary, &carrier_phis, debug)?;
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
}
feat(joinir): Phase 33-14 JoinFragmentMeta for expr/carrier separation Introduces JoinFragmentMeta to distinguish between loop expression results and carrier variable updates, fixing SSA correctness issues. ## Changes ### New: JoinFragmentMeta struct (carrier_info.rs) - `expr_result: Option<ValueId>` - Loop as expression (return loop(...)) - `exit_meta: ExitMeta` - Carrier updates for variable_map - Helper methods: with_expr_result(), carrier_only(), empty() ### Pattern 2 Lowerer Updates - loop_with_break_minimal.rs: Returns (JoinModule, JoinFragmentMeta) - pattern2_with_break.rs: Sets boundary.expr_result from fragment_meta ### instruction_rewriter.rs - Phase 33-14: Only add to exit_phi_inputs when boundary.expr_result is Some - Phase 33-13: MergeResult struct with carrier_inputs map ### JoinInlineBoundary (inline_boundary.rs) - New field: expr_result: Option<ValueId> - All constructors updated with expr_result: None default ## Design Philosophy Previously, exit_phi_inputs mixed expr results with carrier updates, causing: - PHI inputs referencing undefined remapped values - SSA-undef errors in VM execution With JoinFragmentMeta: - expr_result → exit_phi_inputs (generates PHI for expr value) - exit_meta → carrier_inputs (updates variable_map via carrier PHIs) ## Test Results - Pattern 1 (carrier-only): Works correctly (no exit_phi_inputs) - Pattern 2 (expr result): Design complete, SSA-undef fix deferred to Phase 33-15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 05:07:28 +09:00
let exit_block_id = merge_result.exit_block_id;
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
// Jump from current block to entry function's entry block
// (Reuse entry_func_name and entry_block_remapped from Phase 3.5)
let entry_block = entry_block_remapped;
refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4) Phase 4 Implementation Complete: Successfully modularized the 714-line merge_joinir_mir_blocks() function into 6 focused, maintainable modules. ## Changes Made ### 1. Created Module Structure - `src/mir/builder/control_flow/joinir/merge/` directory - 5 sub-modules + 1 coordinator (6 files total) ### 2. Module Breakdown (848 lines total) - **mod.rs** (223 lines) - Coordinator function - Orchestrates all 6 phases - Handles boundary reconnection - Manages entry/exit block jumps - **block_allocator.rs** (70 lines) - Block ID allocation - Allocates new BlockIds for all JoinIR functions - Maintains determinism via sorted iteration - **value_collector.rs** (90 lines) - Value collection - Collects all ValueIds from JoinIR functions - Builds auxiliary maps for Call→Jump conversion - **instruction_rewriter.rs** (405 lines) - Instruction rewriting - Rewrites instructions with remapped IDs - Handles tail call optimization - Converts Return → Jump to exit block - **exit_phi_builder.rs** (60 lines) - Exit PHI construction - Builds PHI node merging return values - Creates exit block ### 3. Updated control_flow/mod.rs - Replaced 714-line function with 18-line delegation - Reduced from 904 lines → 312 lines (65% reduction) - Added documentation explaining Phase 4 refactoring ## Verification Results ✅ **Build**: `cargo build --release` - SUCCESS (23.36s) ✅ **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2) ✅ **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT ✅ **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly ✅ **No Regressions**: Behavior preserved 100% ## Benefits 1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each) 2. **Readability**: Each phase isolated in its own file 3. **Testability**: Individual modules can be tested separately 4. **Future Development**: Easy to modify individual phases 5. **Zero Breaking Changes**: Backward compatible, no API changes ## Technical Notes - Uses JoinIrIdRemapper (already existed) for ID translation - Preserves all debug output and trace functionality - Maintains determinism via BTreeSet/BTreeMap - All Phase 189 features intact (multi-function support, etc.) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
if debug {
eprintln!("[cf_loop/joinir] Entry function name: {}", entry_func_name);
eprintln!(
"[cf_loop/joinir] Entry function's entry_block (JoinIR local): {:?}",
entry_func.entry_block
);
eprintln!("[cf_loop/joinir] Entry block (remapped): {:?}", entry_block);
eprintln!(
"[cf_loop/joinir] Current block before emit_jump: {:?}",
builder.current_block
);
eprintln!("[cf_loop/joinir] Jumping to entry block: {:?}", entry_block);
}
crate::mir::builder::emission::branch::emit_jump(builder, entry_block)?;
if debug {
eprintln!(
"[cf_loop/joinir] After emit_jump, current_block: {:?}",
builder.current_block
);
}
// Switch to exit block for subsequent code
builder.start_new_block(exit_block_id)?;
if debug {
eprintln!(
"[cf_loop/joinir] Phase 189: Merge complete: {} functions merged, continuing from {:?}",
mir_module.functions.len(),
exit_block_id
);
}
Ok(exit_phi_result_id)
}
/// Phase 3: Allocate new ValueIds for all collected values
fn remap_values(
builder: &mut crate::mir::builder::MirBuilder,
used_values: &std::collections::BTreeSet<ValueId>,
remapper: &mut crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper,
debug: bool,
) -> Result<(), String> {
if debug {
eprintln!("[cf_loop/joinir] Phase 3: Remapping {} ValueIds", used_values.len());
}
for old_value in used_values {
let new_value = builder.next_value_id();
remapper.set_value(*old_value, new_value);
if debug {
eprintln!(
"[cf_loop/joinir] Value remap: {:?} → {:?}",
old_value, new_value
);
}
}
Ok(())
}