refactor: Extract pattern lowerers from control_flow.rs (Phase 2)
- Created joinir/patterns/ subdirectory - Extracted Pattern 1: pattern1_minimal.rs (Simple While) - Extracted Pattern 2: pattern2_with_break.rs (Loop with Break) - Extracted Pattern 3: pattern3_with_if_phi.rs (Loop with If-Else PHI) - Created patterns/mod.rs dispatcher - Removed ~410 lines from main control_flow.rs - Zero breaking changes, all tests pass
This commit is contained in:
7
src/mir/builder/control_flow/joinir/mod.rs
Normal file
7
src/mir/builder/control_flow/joinir/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! JoinIR integration for control flow
|
||||||
|
//!
|
||||||
|
//! This module contains JoinIR-related control flow logic:
|
||||||
|
//! - Pattern lowerers (patterns/)
|
||||||
|
//! - Routing logic (future Phase 3)
|
||||||
|
|
||||||
|
pub(in crate::mir::builder) mod patterns;
|
||||||
10
src/mir/builder/control_flow/joinir/patterns/mod.rs
Normal file
10
src/mir/builder/control_flow/joinir/patterns/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//! Pattern lowerers for different loop constructs
|
||||||
|
//!
|
||||||
|
//! Phase 2: Extracted from control_flow.rs
|
||||||
|
//! - Pattern 1: Simple While Loop (pattern1_minimal.rs)
|
||||||
|
//! - Pattern 2: Loop with Conditional Break (pattern2_with_break.rs)
|
||||||
|
//! - Pattern 3: Loop with If-Else PHI (pattern3_with_if_phi.rs)
|
||||||
|
|
||||||
|
pub(in crate::mir::builder) mod pattern1_minimal;
|
||||||
|
pub(in crate::mir::builder) mod pattern2_with_break;
|
||||||
|
pub(in crate::mir::builder) mod pattern3_with_if_phi;
|
||||||
156
src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs
Normal file
156
src/mir/builder/control_flow/joinir/patterns/pattern1_minimal.rs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
//! Pattern 1: Simple While Loop minimal lowerer
|
||||||
|
|
||||||
|
use crate::ast::ASTNode;
|
||||||
|
use crate::mir::builder::MirBuilder;
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
|
impl MirBuilder {
|
||||||
|
/// Phase 188-Impl-1-F: Pattern 1 (Simple While Loop) minimal lowerer
|
||||||
|
///
|
||||||
|
/// This bypasses the LoopFrontendBinding JSON path and directly calls
|
||||||
|
/// the Pattern 1 minimal lowerer for apps/tests/loop_min_while.hako
|
||||||
|
///
|
||||||
|
/// # Phase 188-Impl-2: Host Variable Integration
|
||||||
|
///
|
||||||
|
/// Extracts the loop variable from the host function (e.g., `i` from `i < 3`)
|
||||||
|
/// and passes it to the Pattern 1 lowerer along with a ValueId allocator.
|
||||||
|
///
|
||||||
|
/// # Pipeline
|
||||||
|
/// 1. Extract loop variable name from condition
|
||||||
|
/// 2. Look up ValueId in host variable_map
|
||||||
|
/// 3. Create Pattern1Context with host variable + allocator
|
||||||
|
/// 4. Call simple_while_minimal::lower_simple_while_minimal() → JoinModule
|
||||||
|
/// 5. convert_join_module_to_mir_with_meta() → MirModule
|
||||||
|
/// 6. Merge MIR blocks into current_function
|
||||||
|
pub(in crate::mir::builder) fn cf_loop_pattern1_minimal(
|
||||||
|
&mut self,
|
||||||
|
condition: &ASTNode,
|
||||||
|
_body: &[ASTNode],
|
||||||
|
_func_name: &str,
|
||||||
|
debug: bool,
|
||||||
|
) -> Result<Option<ValueId>, String> {
|
||||||
|
use crate::mir::join_ir::lowering::simple_while_minimal::{
|
||||||
|
lower_simple_while_minimal, Pattern1Context,
|
||||||
|
};
|
||||||
|
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
||||||
|
use crate::mir::BasicBlockId;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern1] Calling Pattern 1 minimal lowerer");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 188-Impl-2: Extract loop variable from condition
|
||||||
|
// For `i < 3`, extract `i` and look up its ValueId in variable_map
|
||||||
|
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
||||||
|
let loop_var_id = self
|
||||||
|
.variable_map
|
||||||
|
.get(&loop_var_name)
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[cf_loop/pattern1] Loop variable '{}' not found in variable_map",
|
||||||
|
loop_var_name
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern1] Loop variable '{}' → {:?}",
|
||||||
|
loop_var_name, loop_var_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a minimal LoopScopeShape (Phase 188: hardcoded for loop_min_while.hako)
|
||||||
|
// Pattern 1 lowerer ignores the scope anyway, so this is just a placeholder
|
||||||
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
||||||
|
let scope = LoopScopeShape {
|
||||||
|
header: BasicBlockId(0),
|
||||||
|
body: BasicBlockId(0),
|
||||||
|
latch: BasicBlockId(0),
|
||||||
|
exit: BasicBlockId(0),
|
||||||
|
pinned: BTreeSet::new(),
|
||||||
|
carriers: BTreeSet::new(),
|
||||||
|
body_locals: BTreeSet::new(),
|
||||||
|
exit_live: BTreeSet::new(),
|
||||||
|
progress_carrier: None,
|
||||||
|
variable_definitions: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Phase 188-Impl-2: Create Pattern1Context with host variable + allocator
|
||||||
|
// Clone value_gen to move into closure
|
||||||
|
let mut value_gen_clone = self.value_gen.clone();
|
||||||
|
let ctx = Pattern1Context {
|
||||||
|
loop_var: loop_var_id,
|
||||||
|
value_allocator: Box::new(move || value_gen_clone.next()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call Pattern 1 lowerer with host context
|
||||||
|
let join_module = match lower_simple_while_minimal(scope, Some(ctx)) {
|
||||||
|
Some(module) => module,
|
||||||
|
None => {
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern1] Pattern 1 lowerer returned None");
|
||||||
|
}
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern1] JoinModule generated with {} functions",
|
||||||
|
join_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JoinModule to MirModule
|
||||||
|
// Phase 188: Pass empty meta map since Pattern 1 lowerer doesn't use metadata
|
||||||
|
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
||||||
|
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
||||||
|
|
||||||
|
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
||||||
|
.map_err(|e| format!("[cf_loop/joinir/pattern1] MIR conversion failed: {:?}", e))?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern1] MirModule generated with {} functions",
|
||||||
|
mir_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge JoinIR blocks into current function
|
||||||
|
// Phase 188-Impl-3: Create and pass JoinInlineBoundary for Pattern 1
|
||||||
|
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_inputs_only(
|
||||||
|
vec![ValueId(0)], // JoinIR's main() parameter (loop variable)
|
||||||
|
vec![loop_var_id], // Host's loop variable
|
||||||
|
);
|
||||||
|
// Phase 189: Discard exit PHI result (Pattern 1 returns void)
|
||||||
|
let _ = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
||||||
|
|
||||||
|
// Phase 188-Impl-4-FIX: Return Void instead of trying to emit Const
|
||||||
|
//
|
||||||
|
// PROBLEM: Emitting instructions after merge_joinir_mir_blocks is fragile because:
|
||||||
|
// 1. merge creates exit block and switches to it
|
||||||
|
// 2. We try to add Const to exit block
|
||||||
|
// 3. But subsequent code (return statement) might overwrite the block
|
||||||
|
//
|
||||||
|
// SOLUTION: Loops don't produce values - they return Void.
|
||||||
|
// The subsequent "return 0" statement will emit its own Const + Return.
|
||||||
|
//
|
||||||
|
// This is cleaner because:
|
||||||
|
// - Loop lowering doesn't need to know about the return value
|
||||||
|
// - The return statement handles its own code generation
|
||||||
|
// - No risk of instructions being lost due to block management issues
|
||||||
|
|
||||||
|
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern1] Loop complete, returning Void {:?}",
|
||||||
|
void_val
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(void_val))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
//! Pattern 2: Loop with Conditional Break minimal lowerer
|
||||||
|
|
||||||
|
use crate::ast::ASTNode;
|
||||||
|
use crate::mir::builder::MirBuilder;
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
|
impl MirBuilder {
|
||||||
|
/// Phase 188-Impl-2: Pattern 2 (Loop with Conditional Break) minimal lowerer
|
||||||
|
///
|
||||||
|
/// Similar to Pattern 1, but handles loops with break statements.
|
||||||
|
///
|
||||||
|
/// # Steps
|
||||||
|
/// 1. Extract loop variable from condition
|
||||||
|
/// 2. Generate JoinIR using loop_with_break_minimal
|
||||||
|
/// 3. Convert JoinModule → MirModule
|
||||||
|
/// 4. Create JoinInlineBoundary for input mapping
|
||||||
|
/// 5. Merge MIR blocks into current_function
|
||||||
|
/// 6. Return Void (loop doesn't produce values)
|
||||||
|
pub(in crate::mir::builder) fn cf_loop_pattern2_with_break(
|
||||||
|
&mut self,
|
||||||
|
condition: &ASTNode,
|
||||||
|
_body: &[ASTNode],
|
||||||
|
_func_name: &str,
|
||||||
|
debug: bool,
|
||||||
|
) -> Result<Option<ValueId>, String> {
|
||||||
|
use crate::mir::join_ir::lowering::loop_with_break_minimal::lower_loop_with_break_minimal;
|
||||||
|
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
||||||
|
use crate::mir::BasicBlockId;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern2] Calling Pattern 2 minimal lowerer");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 188-Impl-2: Extract loop variable from condition
|
||||||
|
// For `i < 3`, extract `i` and look up its ValueId in variable_map
|
||||||
|
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
||||||
|
let loop_var_id = self
|
||||||
|
.variable_map
|
||||||
|
.get(&loop_var_name)
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[cf_loop/pattern2] Loop variable '{}' not found in variable_map",
|
||||||
|
loop_var_name
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern2] Loop variable '{}' → {:?}",
|
||||||
|
loop_var_name, loop_var_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a minimal LoopScopeShape (Phase 188: hardcoded for joinir_min_loop.hako)
|
||||||
|
// Pattern 2 lowerer ignores the scope anyway, so this is just a placeholder
|
||||||
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
||||||
|
let scope = LoopScopeShape {
|
||||||
|
header: BasicBlockId(0),
|
||||||
|
body: BasicBlockId(0),
|
||||||
|
latch: BasicBlockId(0),
|
||||||
|
exit: BasicBlockId(0),
|
||||||
|
pinned: BTreeSet::new(),
|
||||||
|
carriers: BTreeSet::new(),
|
||||||
|
body_locals: BTreeSet::new(),
|
||||||
|
exit_live: BTreeSet::new(),
|
||||||
|
progress_carrier: None,
|
||||||
|
variable_definitions: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call Pattern 2 lowerer
|
||||||
|
let join_module = match lower_loop_with_break_minimal(scope) {
|
||||||
|
Some(module) => module,
|
||||||
|
None => {
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern2] Pattern 2 lowerer returned None");
|
||||||
|
}
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern2] JoinModule generated with {} functions",
|
||||||
|
join_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JoinModule to MirModule
|
||||||
|
// Phase 188: Pass empty meta map since Pattern 2 lowerer doesn't use metadata
|
||||||
|
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
||||||
|
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
||||||
|
|
||||||
|
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
||||||
|
.map_err(|e| format!("[cf_loop/joinir/pattern2] MIR conversion failed: {:?}", e))?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern2] MirModule generated with {} functions",
|
||||||
|
mir_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge JoinIR blocks into current function
|
||||||
|
// Phase 188-Impl-2: Create and pass JoinInlineBoundary for Pattern 2
|
||||||
|
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_inputs_only(
|
||||||
|
vec![ValueId(0)], // JoinIR's main() parameter (loop variable init)
|
||||||
|
vec![loop_var_id], // Host's loop variable
|
||||||
|
);
|
||||||
|
// Phase 189: Discard exit PHI result (Pattern 2 returns void)
|
||||||
|
let _ = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
||||||
|
|
||||||
|
// Phase 188-Impl-2: Return Void (loops don't produce values)
|
||||||
|
// The subsequent "return i" statement will emit its own Load + Return
|
||||||
|
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern2] Loop complete, returning Void {:?}",
|
||||||
|
void_val
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(void_val))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
//! Pattern 3: Loop with If-Else PHI minimal lowerer
|
||||||
|
|
||||||
|
use crate::ast::ASTNode;
|
||||||
|
use crate::mir::builder::MirBuilder;
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
|
impl MirBuilder {
|
||||||
|
/// Phase 188-Impl-3: Pattern 3 (Loop with If-Else PHI) minimal lowerer
|
||||||
|
///
|
||||||
|
/// Handles loops with if-else statements that assign to carrier variables.
|
||||||
|
///
|
||||||
|
/// # Steps
|
||||||
|
/// 1. Extract loop variables (carriers: i + sum)
|
||||||
|
/// 2. Generate JoinIR using loop_with_if_phi_minimal
|
||||||
|
/// 3. Convert JoinModule → MirModule
|
||||||
|
/// 4. Create JoinInlineBoundary for input mapping
|
||||||
|
/// 5. Merge MIR blocks into current_function
|
||||||
|
/// 6. Return Void (loop doesn't produce values)
|
||||||
|
pub(in crate::mir::builder) fn cf_loop_pattern3_with_if_phi(
|
||||||
|
&mut self,
|
||||||
|
condition: &ASTNode,
|
||||||
|
_body: &[ASTNode],
|
||||||
|
_func_name: &str,
|
||||||
|
debug: bool,
|
||||||
|
) -> Result<Option<ValueId>, String> {
|
||||||
|
use crate::mir::join_ir::lowering::loop_with_if_phi_minimal::lower_loop_with_if_phi_pattern;
|
||||||
|
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
||||||
|
use crate::mir::BasicBlockId;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern3] Calling Pattern 3 minimal lowerer");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 188-Impl-3: Extract loop variable from condition
|
||||||
|
// For `i <= 5`, extract `i` and look up its ValueId in variable_map
|
||||||
|
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
||||||
|
let loop_var_id = self
|
||||||
|
.variable_map
|
||||||
|
.get(&loop_var_name)
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[cf_loop/pattern3] Loop variable '{}' not found in variable_map",
|
||||||
|
loop_var_name
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Phase 188-Impl-3: Also get the accumulator variable (sum)
|
||||||
|
// For Pattern 3, we need both i and sum
|
||||||
|
let sum_var_id = self
|
||||||
|
.variable_map
|
||||||
|
.get("sum")
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[cf_loop/pattern3] Accumulator variable 'sum' not found in variable_map"
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern3] Loop variables: '{}' → {:?}, 'sum' → {:?}",
|
||||||
|
loop_var_name, loop_var_id, sum_var_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a minimal LoopScopeShape (Phase 188: hardcoded for loop_if_phi.hako)
|
||||||
|
// Pattern 3 lowerer ignores the scope anyway, so this is just a placeholder
|
||||||
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
||||||
|
let scope = LoopScopeShape {
|
||||||
|
header: BasicBlockId(0),
|
||||||
|
body: BasicBlockId(0),
|
||||||
|
latch: BasicBlockId(0),
|
||||||
|
exit: BasicBlockId(0),
|
||||||
|
pinned: BTreeSet::new(),
|
||||||
|
carriers: BTreeSet::new(),
|
||||||
|
body_locals: BTreeSet::new(),
|
||||||
|
exit_live: BTreeSet::new(),
|
||||||
|
progress_carrier: None,
|
||||||
|
variable_definitions: BTreeMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call Pattern 3 lowerer
|
||||||
|
let join_module = match lower_loop_with_if_phi_pattern(scope) {
|
||||||
|
Some(module) => module,
|
||||||
|
None => {
|
||||||
|
if debug {
|
||||||
|
eprintln!("[cf_loop/joinir/pattern3] Pattern 3 lowerer returned None");
|
||||||
|
}
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern3] JoinModule generated with {} functions",
|
||||||
|
join_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert JoinModule to MirModule
|
||||||
|
// Phase 188: Pass empty meta map since Pattern 3 lowerer doesn't use metadata
|
||||||
|
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
||||||
|
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
||||||
|
|
||||||
|
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
||||||
|
.map_err(|e| format!("[cf_loop/joinir/pattern3] MIR conversion failed: {:?}", e))?;
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern3] MirModule generated with {} functions",
|
||||||
|
mir_module.functions.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge JoinIR blocks into current function
|
||||||
|
// Phase 190: Use explicit LoopExitBinding for Pattern 3
|
||||||
|
// Pattern 3 has TWO carriers: i and sum
|
||||||
|
self.trace_varmap("pattern3_before_merge");
|
||||||
|
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_with_exit_bindings(
|
||||||
|
vec![ValueId(0), ValueId(1)], // JoinIR's main() parameters (i, sum init)
|
||||||
|
vec![loop_var_id, sum_var_id], // Host's loop variables
|
||||||
|
vec![
|
||||||
|
crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding {
|
||||||
|
carrier_name: "sum".to_string(),
|
||||||
|
join_exit_value: ValueId(18), // k_exit's parameter (sum_final)
|
||||||
|
host_slot: sum_var_id, // variable_map["sum"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let _exit_phi_result = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
||||||
|
self.trace_varmap("pattern3_after_merge");
|
||||||
|
|
||||||
|
// Phase 189-Refine: variable_map の更新は merge_joinir_mir_blocks 内で
|
||||||
|
// JoinInlineBoundary.host_outputs を用いて行われる。
|
||||||
|
// この関数では Void を返すだけでよい(戻り値は後続の `return sum` が扱う)。
|
||||||
|
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
eprintln!(
|
||||||
|
"[cf_loop/joinir/pattern3] Loop complete, returning Void {:?}",
|
||||||
|
void_val
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(void_val))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
//! Control-flow entrypoints (if/loop/try/throw) centralized here.
|
//! Control-flow entrypoints (if/loop/try/throw) centralized here.
|
||||||
//!
|
//!
|
||||||
//! This module is being modularized in phases:
|
//! This module is being modularized in phases:
|
||||||
//! - Phase 1: Debug utilities
|
//! - Phase 1: Debug utilities (debug.rs) ✅
|
||||||
//! - Phase 2: Pattern lowerers
|
//! - Phase 2: Pattern lowerers (joinir/patterns/) ✅
|
||||||
//! - Phase 3: JoinIR routing
|
//! - Phase 3: JoinIR routing (future)
|
||||||
//! - Phase 4-19: Additional modularization (future)
|
//! - Phase 4-19: Additional modularization (future)
|
||||||
|
|
||||||
use super::{Effect, EffectMask, MirInstruction, ValueId};
|
use super::{Effect, EffectMask, MirInstruction, ValueId};
|
||||||
@ -12,6 +12,9 @@ use crate::ast::ASTNode;
|
|||||||
// Phase 1: Debug utilities
|
// Phase 1: Debug utilities
|
||||||
pub(in crate::mir::builder) mod debug;
|
pub(in crate::mir::builder) mod debug;
|
||||||
|
|
||||||
|
// Phase 2: JoinIR integration (patterns)
|
||||||
|
pub(in crate::mir::builder) mod joinir;
|
||||||
|
|
||||||
impl super::MirBuilder {
|
impl super::MirBuilder {
|
||||||
/// Control-flow: block
|
/// Control-flow: block
|
||||||
pub(super) fn cf_block(&mut self, statements: Vec<ASTNode>) -> Result<ValueId, String> {
|
pub(super) fn cf_block(&mut self, statements: Vec<ASTNode>) -> Result<ValueId, String> {
|
||||||
@ -412,416 +415,6 @@ impl super::MirBuilder {
|
|||||||
Ok(Some(void_val))
|
Ok(Some(void_val))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Phase 188-Impl-1-F: Pattern 1 (Simple While Loop) minimal lowerer
|
|
||||||
///
|
|
||||||
/// This bypasses the LoopFrontendBinding JSON path and directly calls
|
|
||||||
/// the Pattern 1 minimal lowerer for apps/tests/loop_min_while.hako
|
|
||||||
///
|
|
||||||
/// # Phase 188-Impl-2: Host Variable Integration
|
|
||||||
///
|
|
||||||
/// Extracts the loop variable from the host function (e.g., `i` from `i < 3`)
|
|
||||||
/// and passes it to the Pattern 1 lowerer along with a ValueId allocator.
|
|
||||||
///
|
|
||||||
/// # Pipeline
|
|
||||||
/// 1. Extract loop variable name from condition
|
|
||||||
/// 2. Look up ValueId in host variable_map
|
|
||||||
/// 3. Create Pattern1Context with host variable + allocator
|
|
||||||
/// 4. Call simple_while_minimal::lower_simple_while_minimal() → JoinModule
|
|
||||||
/// 5. convert_join_module_to_mir_with_meta() → MirModule
|
|
||||||
/// 6. Merge MIR blocks into current_function
|
|
||||||
fn cf_loop_pattern1_minimal(
|
|
||||||
&mut self,
|
|
||||||
condition: &ASTNode,
|
|
||||||
_body: &[ASTNode],
|
|
||||||
_func_name: &str,
|
|
||||||
debug: bool,
|
|
||||||
) -> Result<Option<ValueId>, String> {
|
|
||||||
use crate::mir::join_ir::lowering::simple_while_minimal::{
|
|
||||||
lower_simple_while_minimal, Pattern1Context,
|
|
||||||
};
|
|
||||||
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
|
||||||
use crate::mir::BasicBlockId;
|
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern1] Calling Pattern 1 minimal lowerer");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 188-Impl-2: Extract loop variable from condition
|
|
||||||
// For `i < 3`, extract `i` and look up its ValueId in variable_map
|
|
||||||
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
|
||||||
let loop_var_id = self
|
|
||||||
.variable_map
|
|
||||||
.get(&loop_var_name)
|
|
||||||
.copied()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"[cf_loop/pattern1] Loop variable '{}' not found in variable_map",
|
|
||||||
loop_var_name
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern1] Loop variable '{}' → {:?}",
|
|
||||||
loop_var_name, loop_var_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a minimal LoopScopeShape (Phase 188: hardcoded for loop_min_while.hako)
|
|
||||||
// Pattern 1 lowerer ignores the scope anyway, so this is just a placeholder
|
|
||||||
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
|
||||||
let scope = LoopScopeShape {
|
|
||||||
header: BasicBlockId(0),
|
|
||||||
body: BasicBlockId(0),
|
|
||||||
latch: BasicBlockId(0),
|
|
||||||
exit: BasicBlockId(0),
|
|
||||||
pinned: BTreeSet::new(),
|
|
||||||
carriers: BTreeSet::new(),
|
|
||||||
body_locals: BTreeSet::new(),
|
|
||||||
exit_live: BTreeSet::new(),
|
|
||||||
progress_carrier: None,
|
|
||||||
variable_definitions: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Phase 188-Impl-2: Create Pattern1Context with host variable + allocator
|
|
||||||
// Clone value_gen to move into closure
|
|
||||||
let mut value_gen_clone = self.value_gen.clone();
|
|
||||||
let ctx = Pattern1Context {
|
|
||||||
loop_var: loop_var_id,
|
|
||||||
value_allocator: Box::new(move || value_gen_clone.next()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call Pattern 1 lowerer with host context
|
|
||||||
let join_module = match lower_simple_while_minimal(scope, Some(ctx)) {
|
|
||||||
Some(module) => module,
|
|
||||||
None => {
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern1] Pattern 1 lowerer returned None");
|
|
||||||
}
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern1] JoinModule generated with {} functions",
|
|
||||||
join_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert JoinModule to MirModule
|
|
||||||
// Phase 188: Pass empty meta map since Pattern 1 lowerer doesn't use metadata
|
|
||||||
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
|
||||||
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
|
||||||
|
|
||||||
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
|
||||||
.map_err(|e| format!("[cf_loop/joinir/pattern1] MIR conversion failed: {:?}", e))?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern1] MirModule generated with {} functions",
|
|
||||||
mir_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge JoinIR blocks into current function
|
|
||||||
// Phase 188-Impl-3: Create and pass JoinInlineBoundary for Pattern 1
|
|
||||||
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_inputs_only(
|
|
||||||
vec![ValueId(0)], // JoinIR's main() parameter (loop variable)
|
|
||||||
vec![loop_var_id], // Host's loop variable
|
|
||||||
);
|
|
||||||
// Phase 189: Discard exit PHI result (Pattern 1 returns void)
|
|
||||||
let _ = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
|
||||||
|
|
||||||
// Phase 188-Impl-4-FIX: Return Void instead of trying to emit Const
|
|
||||||
//
|
|
||||||
// PROBLEM: Emitting instructions after merge_joinir_mir_blocks is fragile because:
|
|
||||||
// 1. merge creates exit block and switches to it
|
|
||||||
// 2. We try to add Const to exit block
|
|
||||||
// 3. But subsequent code (return statement) might overwrite the block
|
|
||||||
//
|
|
||||||
// SOLUTION: Loops don't produce values - they return Void.
|
|
||||||
// The subsequent "return 0" statement will emit its own Const + Return.
|
|
||||||
//
|
|
||||||
// This is cleaner because:
|
|
||||||
// - Loop lowering doesn't need to know about the return value
|
|
||||||
// - The return statement handles its own code generation
|
|
||||||
// - No risk of instructions being lost due to block management issues
|
|
||||||
|
|
||||||
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern1] Loop complete, returning Void {:?}",
|
|
||||||
void_val
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(void_val))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Phase 188-Impl-2: Pattern 2 (Loop with Conditional Break) minimal lowerer
|
|
||||||
///
|
|
||||||
/// Similar to Pattern 1, but handles loops with break statements.
|
|
||||||
///
|
|
||||||
/// # Steps
|
|
||||||
/// 1. Extract loop variable from condition
|
|
||||||
/// 2. Generate JoinIR using loop_with_break_minimal
|
|
||||||
/// 3. Convert JoinModule → MirModule
|
|
||||||
/// 4. Create JoinInlineBoundary for input mapping
|
|
||||||
/// 5. Merge MIR blocks into current_function
|
|
||||||
/// 6. Return Void (loop doesn't produce values)
|
|
||||||
fn cf_loop_pattern2_with_break(
|
|
||||||
&mut self,
|
|
||||||
condition: &ASTNode,
|
|
||||||
_body: &[ASTNode],
|
|
||||||
_func_name: &str,
|
|
||||||
debug: bool,
|
|
||||||
) -> Result<Option<ValueId>, String> {
|
|
||||||
use crate::mir::join_ir::lowering::loop_with_break_minimal::lower_loop_with_break_minimal;
|
|
||||||
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
|
||||||
use crate::mir::BasicBlockId;
|
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern2] Calling Pattern 2 minimal lowerer");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 188-Impl-2: Extract loop variable from condition
|
|
||||||
// For `i < 3`, extract `i` and look up its ValueId in variable_map
|
|
||||||
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
|
||||||
let loop_var_id = self
|
|
||||||
.variable_map
|
|
||||||
.get(&loop_var_name)
|
|
||||||
.copied()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"[cf_loop/pattern2] Loop variable '{}' not found in variable_map",
|
|
||||||
loop_var_name
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern2] Loop variable '{}' → {:?}",
|
|
||||||
loop_var_name, loop_var_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a minimal LoopScopeShape (Phase 188: hardcoded for joinir_min_loop.hako)
|
|
||||||
// Pattern 2 lowerer ignores the scope anyway, so this is just a placeholder
|
|
||||||
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
|
||||||
let scope = LoopScopeShape {
|
|
||||||
header: BasicBlockId(0),
|
|
||||||
body: BasicBlockId(0),
|
|
||||||
latch: BasicBlockId(0),
|
|
||||||
exit: BasicBlockId(0),
|
|
||||||
pinned: BTreeSet::new(),
|
|
||||||
carriers: BTreeSet::new(),
|
|
||||||
body_locals: BTreeSet::new(),
|
|
||||||
exit_live: BTreeSet::new(),
|
|
||||||
progress_carrier: None,
|
|
||||||
variable_definitions: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call Pattern 2 lowerer
|
|
||||||
let join_module = match lower_loop_with_break_minimal(scope) {
|
|
||||||
Some(module) => module,
|
|
||||||
None => {
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern2] Pattern 2 lowerer returned None");
|
|
||||||
}
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern2] JoinModule generated with {} functions",
|
|
||||||
join_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert JoinModule to MirModule
|
|
||||||
// Phase 188: Pass empty meta map since Pattern 2 lowerer doesn't use metadata
|
|
||||||
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
|
||||||
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
|
||||||
|
|
||||||
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
|
||||||
.map_err(|e| format!("[cf_loop/joinir/pattern2] MIR conversion failed: {:?}", e))?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern2] MirModule generated with {} functions",
|
|
||||||
mir_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge JoinIR blocks into current function
|
|
||||||
// Phase 188-Impl-2: Create and pass JoinInlineBoundary for Pattern 2
|
|
||||||
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_inputs_only(
|
|
||||||
vec![ValueId(0)], // JoinIR's main() parameter (loop variable init)
|
|
||||||
vec![loop_var_id], // Host's loop variable
|
|
||||||
);
|
|
||||||
// Phase 189: Discard exit PHI result (Pattern 2 returns void)
|
|
||||||
let _ = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
|
||||||
|
|
||||||
// Phase 188-Impl-2: Return Void (loops don't produce values)
|
|
||||||
// The subsequent "return i" statement will emit its own Load + Return
|
|
||||||
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern2] Loop complete, returning Void {:?}",
|
|
||||||
void_val
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(void_val))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Phase 188-Impl-3: Pattern 3 (Loop with If-Else PHI) minimal lowerer
|
|
||||||
///
|
|
||||||
/// Handles loops with if-else statements that assign to carrier variables.
|
|
||||||
///
|
|
||||||
/// # Steps
|
|
||||||
/// 1. Extract loop variables (carriers: i + sum)
|
|
||||||
/// 2. Generate JoinIR using loop_with_if_phi_minimal
|
|
||||||
/// 3. Convert JoinModule → MirModule
|
|
||||||
/// 4. Create JoinInlineBoundary for input mapping
|
|
||||||
/// 5. Merge MIR blocks into current_function
|
|
||||||
/// 6. Return Void (loop doesn't produce values)
|
|
||||||
fn cf_loop_pattern3_with_if_phi(
|
|
||||||
&mut self,
|
|
||||||
condition: &ASTNode,
|
|
||||||
_body: &[ASTNode],
|
|
||||||
_func_name: &str,
|
|
||||||
debug: bool,
|
|
||||||
) -> Result<Option<ValueId>, String> {
|
|
||||||
use crate::mir::join_ir::lowering::loop_with_if_phi_minimal::lower_loop_with_if_phi_pattern;
|
|
||||||
use crate::mir::join_ir_vm_bridge::convert_join_module_to_mir_with_meta;
|
|
||||||
use crate::mir::BasicBlockId;
|
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern3] Calling Pattern 3 minimal lowerer");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 188-Impl-3: Extract loop variable from condition
|
|
||||||
// For `i <= 5`, extract `i` and look up its ValueId in variable_map
|
|
||||||
let loop_var_name = self.extract_loop_variable_from_condition(condition)?;
|
|
||||||
let loop_var_id = self
|
|
||||||
.variable_map
|
|
||||||
.get(&loop_var_name)
|
|
||||||
.copied()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"[cf_loop/pattern3] Loop variable '{}' not found in variable_map",
|
|
||||||
loop_var_name
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Phase 188-Impl-3: Also get the accumulator variable (sum)
|
|
||||||
// For Pattern 3, we need both i and sum
|
|
||||||
let sum_var_id = self
|
|
||||||
.variable_map
|
|
||||||
.get("sum")
|
|
||||||
.copied()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"[cf_loop/pattern3] Accumulator variable 'sum' not found in variable_map"
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern3] Loop variables: '{}' → {:?}, 'sum' → {:?}",
|
|
||||||
loop_var_name, loop_var_id, sum_var_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a minimal LoopScopeShape (Phase 188: hardcoded for loop_if_phi.hako)
|
|
||||||
// Pattern 3 lowerer ignores the scope anyway, so this is just a placeholder
|
|
||||||
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
|
||||||
let scope = LoopScopeShape {
|
|
||||||
header: BasicBlockId(0),
|
|
||||||
body: BasicBlockId(0),
|
|
||||||
latch: BasicBlockId(0),
|
|
||||||
exit: BasicBlockId(0),
|
|
||||||
pinned: BTreeSet::new(),
|
|
||||||
carriers: BTreeSet::new(),
|
|
||||||
body_locals: BTreeSet::new(),
|
|
||||||
exit_live: BTreeSet::new(),
|
|
||||||
progress_carrier: None,
|
|
||||||
variable_definitions: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call Pattern 3 lowerer
|
|
||||||
let join_module = match lower_loop_with_if_phi_pattern(scope) {
|
|
||||||
Some(module) => module,
|
|
||||||
None => {
|
|
||||||
if debug {
|
|
||||||
eprintln!("[cf_loop/joinir/pattern3] Pattern 3 lowerer returned None");
|
|
||||||
}
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern3] JoinModule generated with {} functions",
|
|
||||||
join_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert JoinModule to MirModule
|
|
||||||
// Phase 188: Pass empty meta map since Pattern 3 lowerer doesn't use metadata
|
|
||||||
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
|
|
||||||
let empty_meta: JoinFuncMetaMap = BTreeMap::new();
|
|
||||||
|
|
||||||
let mir_module = convert_join_module_to_mir_with_meta(&join_module, &empty_meta)
|
|
||||||
.map_err(|e| format!("[cf_loop/joinir/pattern3] MIR conversion failed: {:?}", e))?;
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern3] MirModule generated with {} functions",
|
|
||||||
mir_module.functions.len()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge JoinIR blocks into current function
|
|
||||||
// Phase 190: Use explicit LoopExitBinding for Pattern 3
|
|
||||||
// Pattern 3 has TWO carriers: i and sum
|
|
||||||
self.trace_varmap("pattern3_before_merge");
|
|
||||||
let boundary = crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary::new_with_exit_bindings(
|
|
||||||
vec![ValueId(0), ValueId(1)], // JoinIR's main() parameters (i, sum init)
|
|
||||||
vec![loop_var_id, sum_var_id], // Host's loop variables
|
|
||||||
vec![
|
|
||||||
crate::mir::join_ir::lowering::inline_boundary::LoopExitBinding {
|
|
||||||
carrier_name: "sum".to_string(),
|
|
||||||
join_exit_value: ValueId(18), // k_exit's parameter (sum_final)
|
|
||||||
host_slot: sum_var_id, // variable_map["sum"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
);
|
|
||||||
let exit_phi_result = self.merge_joinir_mir_blocks(&mir_module, Some(&boundary), debug)?;
|
|
||||||
self.trace_varmap("pattern3_after_merge");
|
|
||||||
|
|
||||||
// Phase 189-Refine: variable_map の更新は merge_joinir_mir_blocks 内で
|
|
||||||
// JoinInlineBoundary.host_outputs を用いて行われる。
|
|
||||||
// この関数では Void を返すだけでよい(戻り値は後続の `return sum` が扱う)。
|
|
||||||
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
eprintln!(
|
|
||||||
"[cf_loop/joinir/pattern3] Loop complete, returning Void {:?}",
|
|
||||||
void_val
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(void_val))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Phase 49-3.2: Merge JoinIR-generated MIR blocks into current_function
|
/// Phase 49-3.2: Merge JoinIR-generated MIR blocks into current_function
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user