diff --git a/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs b/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs index 2cf2bde7..01c60a77 100644 --- a/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs +++ b/src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs @@ -51,13 +51,19 @@ impl LoopHeaderPhiBuilder { /// /// LoopHeaderPhiInfo with allocated PHI dsts. /// Note: latch_incoming is not yet set - that happens in instruction_rewriter. + /// + /// # Phase 228 Update + /// + /// Added CarrierInit and CarrierRole to carrier tuples: + /// * `CarrierInit::FromHost` - Use host_id directly as PHI init value + /// * `CarrierInit::BoolConst(val)` - Generate explicit bool constant for ConditionOnly carriers pub fn build( builder: &mut crate::mir::builder::MirBuilder, header_block: BasicBlockId, entry_block: BasicBlockId, loop_var_name: &str, loop_var_init: ValueId, - carriers: &[(String, ValueId)], // (name, init_value) pairs + carriers: &[(String, ValueId, crate::mir::join_ir::lowering::carrier_info::CarrierInit, crate::mir::join_ir::lowering::carrier_info::CarrierRole)], // Phase 228: Added CarrierInit and CarrierRole expr_result_is_loop_var: bool, debug: bool, ) -> Result { @@ -96,15 +102,35 @@ impl LoopHeaderPhiBuilder { } // Allocate PHIs for other carriers - for (name, init_value) in carriers { + for (name, host_id, init, role) in carriers { + // Phase 228-5: Generate explicit const for BoolConst, use host_id for FromHost + let init_value = match init { + crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost => *host_id, + crate::mir::join_ir::lowering::carrier_info::CarrierInit::BoolConst(val) => { + // Phase 228: Generate explicit bool constant for ConditionOnly carriers + let const_id = builder.next_value_id(); + builder.emit_instruction(MirInstruction::Const { + dst: const_id, + value: crate::mir::types::ConstValue::Bool(*val), + }); + if debug { + eprintln!( + "[cf_loop/joinir] Phase 228: Generated const {:?} = Bool({}) for ConditionOnly carrier '{}'", + const_id, val, name + ); + } + const_id + } + }; + let phi_dst = builder.next_value_id(); info.carrier_phis.insert( name.clone(), CarrierPhiEntry { phi_dst, - entry_incoming: (entry_block, *init_value), + entry_incoming: (entry_block, init_value), latch_incoming: None, - role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Default to LoopState (will be updated later if needed) + role: *role, // Phase 228: Use role from carrier_info }, ); // Phase 177-STRUCT-2: Record insertion order @@ -112,8 +138,8 @@ impl LoopHeaderPhiBuilder { if debug { eprintln!( - "[cf_loop/joinir] Carrier '{}' PHI: {:?} = phi [(from {:?}, {:?}), (latch TBD)]", - name, phi_dst, entry_block, init_value + "[cf_loop/joinir] Carrier '{}' PHI: {:?} = phi [(from {:?}, {:?}), (latch TBD)], role={:?}", + name, phi_dst, entry_block, init_value, role ); } } diff --git a/src/mir/builder/control_flow/joinir/merge/mod.rs b/src/mir/builder/control_flow/joinir/merge/mod.rs index ce14cfaa..75687b36 100644 --- a/src/mir/builder/control_flow/joinir/merge/mod.rs +++ b/src/mir/builder/control_flow/joinir/merge/mod.rs @@ -141,12 +141,23 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks( "Phase 201-A: No host_inputs in boundary for loop_var_init" )?; - // Extract other carriers from exit_bindings - let other_carriers: Vec<(String, ValueId)> = boundary.exit_bindings - .iter() - .filter(|b| b.carrier_name != *loop_var_name) - .map(|b| (b.carrier_name.clone(), b.host_slot)) - .collect(); + // Phase 228-4: Extract carriers with their initialization strategy + let other_carriers: Vec<(String, ValueId, crate::mir::join_ir::lowering::carrier_info::CarrierInit, crate::mir::join_ir::lowering::carrier_info::CarrierRole)> = + if let Some(ref carrier_info) = boundary.carrier_info { + // Use carrier_info if available (Phase 228) + carrier_info.carriers + .iter() + .filter(|c| c.name != *loop_var_name) + .map(|c| (c.name.clone(), c.host_id, c.init, c.role)) + .collect() + } else { + // Fallback: exit_bindings から取得(既存動作) + boundary.exit_bindings + .iter() + .filter(|b| b.carrier_name != *loop_var_name) + .map(|b| (b.carrier_name.clone(), b.host_slot, crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState)) + .collect() + }; if debug { eprintln!( @@ -156,7 +167,7 @@ pub(in crate::mir::builder) fn merge_joinir_mir_blocks( eprintln!( "[cf_loop/joinir] loop_var_init={:?}, carriers={:?}", loop_var_init, - other_carriers.iter().map(|(n, _)| n.as_str()).collect::>() + other_carriers.iter().map(|(n, _, _, _)| n.as_str()).collect::>() ); } diff --git a/src/mir/builder/control_flow/joinir/patterns/common_init.rs b/src/mir/builder/control_flow/joinir/patterns/common_init.rs index 091f472d..8f4b4c8f 100644 --- a/src/mir/builder/control_flow/joinir/patterns/common_init.rs +++ b/src/mir/builder/control_flow/joinir/patterns/common_init.rs @@ -163,6 +163,7 @@ impl CommonPatternInitializer { host_id: ValueId(0), // Dummy join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, // Phase 227: Default + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228: Default }) } else { None diff --git a/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs b/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs index 4f9274fb..4899e16b 100644 --- a/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs +++ b/src/mir/builder/control_flow/joinir/patterns/exit_binding.rs @@ -143,6 +143,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -183,12 +184,14 @@ mod tests { host_id: ValueId(11), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "sum".to_string(), host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, ], ); @@ -232,6 +235,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -261,6 +265,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -290,6 +295,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -322,6 +328,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -352,6 +359,7 @@ mod tests { condition_bindings: vec![], // Phase 171-fix: Add missing field expr_result: None, // Phase 33-14: Add missing field loop_var_name: None, // Phase 33-16: Add missing field + carrier_info: None, // Phase 228: Add missing field }; builder.apply_to_boundary(&mut boundary) diff --git a/src/mir/builder/control_flow/joinir/patterns/exit_binding_applicator.rs b/src/mir/builder/control_flow/joinir/patterns/exit_binding_applicator.rs index 27ef22b4..3606cef1 100644 --- a/src/mir/builder/control_flow/joinir/patterns/exit_binding_applicator.rs +++ b/src/mir/builder/control_flow/joinir/patterns/exit_binding_applicator.rs @@ -108,6 +108,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -134,6 +135,7 @@ mod tests { condition_bindings: vec![], // Phase 171-fix: Add missing field expr_result: None, // Phase 33-14: Add missing field loop_var_name: None, // Phase 33-16: Add missing field + carrier_info: None, // Phase 228: Add missing field }; apply_exit_bindings_to_boundary(&carrier_info, &exit_meta, &variable_map, &mut boundary) diff --git a/src/mir/builder/control_flow/joinir/patterns/exit_binding_constructor.rs b/src/mir/builder/control_flow/joinir/patterns/exit_binding_constructor.rs index aee8e7f7..40284cc3 100644 --- a/src/mir/builder/control_flow/joinir/patterns/exit_binding_constructor.rs +++ b/src/mir/builder/control_flow/joinir/patterns/exit_binding_constructor.rs @@ -92,6 +92,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -130,12 +131,14 @@ mod tests { host_id: ValueId(11), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "sum".to_string(), host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, ], ); diff --git a/src/mir/builder/control_flow/joinir/patterns/exit_binding_validator.rs b/src/mir/builder/control_flow/joinir/patterns/exit_binding_validator.rs index 42b18b8b..d1d03f51 100644 --- a/src/mir/builder/control_flow/joinir/patterns/exit_binding_validator.rs +++ b/src/mir/builder/control_flow/joinir/patterns/exit_binding_validator.rs @@ -70,6 +70,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -90,12 +91,14 @@ mod tests { host_id: ValueId(11), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "sum".to_string(), host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, ], ); @@ -119,6 +122,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -140,6 +144,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); @@ -161,6 +166,7 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }], ); diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs b/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs index cc648adb..d5b14ced 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs @@ -578,6 +578,7 @@ impl MirBuilder { .with_exit_bindings(exit_bindings.clone()) .with_expr_result(fragment_meta.expr_result) // Phase 33-14: Pass expr_result to merger .with_loop_var_name(Some(loop_var_name.clone())) // Phase 33-16: For LoopHeaderPhiBuilder + .with_carrier_info(carrier_info.clone()) // Phase 228-6: Pass carrier_info for ConditionOnly header PHI init .build(); // Phase 33-22: Use JoinIRConversionPipeline for unified conversion flow diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern4_carrier_analyzer.rs b/src/mir/builder/control_flow/joinir/patterns/pattern4_carrier_analyzer.rs index 9a6f5ea0..b2c84602 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern4_carrier_analyzer.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern4_carrier_analyzer.rs @@ -277,18 +277,21 @@ mod tests { host_id: ValueId(1), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "sum".to_string(), host_id: ValueId(2), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "M".to_string(), host_id: ValueId(3), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, ], trim_helper: None, diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs b/src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs index 3e850a79..d0b9a9b1 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern4_with_continue.rs @@ -378,6 +378,7 @@ impl MirBuilder { .with_inputs(join_inputs, host_inputs) // Dynamic carrier count .with_exit_bindings(exit_bindings) .with_loop_var_name(Some(loop_var_name.clone())) // Phase 33-19: Enable exit PHI collection + .with_carrier_info(carrier_info.clone()) // Phase 228-6: Pass carrier_info for ConditionOnly header PHI init .build(); // Phase 33-22: Use JoinIRConversionPipeline for unified conversion flow diff --git a/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs b/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs index 9b3b4812..4ec2c346 100644 --- a/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs +++ b/src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs @@ -397,12 +397,14 @@ mod tests { host_id: ValueId(10), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, CarrierVar { name: "count".to_string(), host_id: ValueId(11), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }, ], trim_helper: None, diff --git a/src/mir/join_ir/lowering/carrier_info.rs b/src/mir/join_ir/lowering/carrier_info.rs index 2e8f8662..2c267e5b 100644 --- a/src/mir/join_ir/lowering/carrier_info.rs +++ b/src/mir/join_ir/lowering/carrier_info.rs @@ -54,6 +54,29 @@ pub enum CarrierRole { ConditionOnly, } +/// Phase 228: Initialization policy for carrier variables +/// +/// When carriers participate in header PHI, they need an initial value. +/// Most carriers use their host_id value (FromHost), but promoted LoopBodyLocal +/// carriers need explicit bool initialization (BoolConst). +/// +/// # Example +/// +/// ```ignore +/// // Regular carrier (sum): Use host_id value +/// CarrierVar { name: "sum", host_id: ValueId(10), init: FromHost, .. } +/// +/// // ConditionOnly carrier (is_digit_pos): Initialize with false +/// CarrierVar { name: "is_digit_pos", host_id: ValueId(15), init: BoolConst(false), .. } +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum CarrierInit { + /// No explicit initialization (use host_id value) + FromHost, + /// Initialize with bool constant (for ConditionOnly carriers) + BoolConst(bool), +} + /// Phase 224-D: Alias for promoted LoopBodyLocal in condition expressions /// /// When a LoopBodyLocal variable is promoted to a carrier, the original variable @@ -97,6 +120,11 @@ pub struct CarrierVar { /// - `LoopState`: Value needed after loop (participates in exit PHI) /// - `ConditionOnly`: Only used for loop condition (no exit PHI) pub role: CarrierRole, + /// Phase 228: Initialization policy for header PHI + /// + /// - `FromHost`: Use host_id value (regular carriers) + /// - `BoolConst(false)`: Initialize with false (promoted LoopBodyLocal carriers) + pub init: CarrierInit, } impl CarrierVar { @@ -110,6 +138,7 @@ impl CarrierVar { host_id, join_id: None, role: CarrierRole::LoopState, + init: CarrierInit::FromHost, // Phase 228: Default to FromHost } } @@ -120,6 +149,23 @@ impl CarrierVar { host_id, join_id: None, role, + init: CarrierInit::FromHost, // Phase 228: Default to FromHost + } + } + + /// Phase 228: Create a CarrierVar with explicit role and init policy + pub fn with_role_and_init( + name: String, + host_id: ValueId, + role: CarrierRole, + init: CarrierInit, + ) -> Self { + Self { + name, + host_id, + join_id: None, + role, + init, } } } @@ -197,6 +243,7 @@ impl CarrierInfo { host_id: id, join_id: None, // Phase 177-STRUCT-1: Set by header PHI generation role: CarrierRole::LoopState, // Phase 227: Default to LoopState + init: CarrierInit::FromHost, // Phase 228: Default to FromHost }) .collect(); @@ -257,6 +304,7 @@ impl CarrierInfo { host_id, join_id: None, // Phase 177-STRUCT-1: Set by header PHI generation role: CarrierRole::LoopState, // Phase 227: Default to LoopState + init: CarrierInit::FromHost, // Phase 228: Default to FromHost }); } @@ -576,6 +624,7 @@ mod tests { host_id: ValueId(id), join_id: None, // Phase 177-STRUCT-1 role: CarrierRole::LoopState, // Phase 227: Default to LoopState + init: CarrierInit::FromHost, // Phase 228: Default to FromHost } } diff --git a/src/mir/join_ir/lowering/carrier_update_emitter.rs b/src/mir/join_ir/lowering/carrier_update_emitter.rs index d961e6c3..172ce3a7 100644 --- a/src/mir/join_ir/lowering/carrier_update_emitter.rs +++ b/src/mir/join_ir/lowering/carrier_update_emitter.rs @@ -422,6 +422,7 @@ mod tests { host_id: ValueId(host_id), join_id: None, // Phase 177-STRUCT-1 role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 } } diff --git a/src/mir/join_ir/lowering/inline_boundary.rs b/src/mir/join_ir/lowering/inline_boundary.rs index c9d8320b..f5b09618 100644 --- a/src/mir/join_ir/lowering/inline_boundary.rs +++ b/src/mir/join_ir/lowering/inline_boundary.rs @@ -246,6 +246,16 @@ pub struct JoinInlineBoundary { /// The name of the loop control variable (e.g., "i" in `loop(i < 3)`). /// Used to track which PHI corresponds to the loop variable. pub loop_var_name: Option, + + /// Phase 228: Carrier metadata (for header PHI generation) + /// + /// Contains full carrier information including initialization policies. + /// This allows header PHI generation to handle ConditionOnly carriers + /// with explicit bool initialization. + /// + /// - `Some(CarrierInfo)`: Full carrier metadata available + /// - `None`: Legacy path (derive carriers from exit_bindings) + pub carrier_info: Option, } impl JoinInlineBoundary { @@ -272,6 +282,7 @@ impl JoinInlineBoundary { condition_bindings: vec![], // Phase 171-fix: Default to empty expr_result: None, // Phase 33-14: Default to carrier-only pattern loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228: Default to None } } @@ -314,6 +325,7 @@ impl JoinInlineBoundary { condition_bindings: vec![], // Phase 171-fix: Default to empty expr_result: None, // Phase 33-14 loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228 } } @@ -373,6 +385,7 @@ impl JoinInlineBoundary { condition_bindings: vec![], // Phase 171-fix: Default to empty expr_result: None, // Phase 33-14 loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228 } } @@ -418,6 +431,7 @@ impl JoinInlineBoundary { condition_bindings: vec![], // Phase 171-fix: Will be populated by new constructor expr_result: None, // Phase 33-14 loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228 } } @@ -467,6 +481,7 @@ impl JoinInlineBoundary { condition_bindings: vec![], // Phase 171-fix: Will be populated by new constructor expr_result: None, // Phase 33-14 loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228 } } @@ -523,6 +538,7 @@ impl JoinInlineBoundary { condition_bindings, expr_result: None, // Phase 33-14 loop_var_name: None, // Phase 33-16 + carrier_info: None, // Phase 228 } } } diff --git a/src/mir/join_ir/lowering/inline_boundary_builder.rs b/src/mir/join_ir/lowering/inline_boundary_builder.rs index 24a5ce5a..aaf9ac9c 100644 --- a/src/mir/join_ir/lowering/inline_boundary_builder.rs +++ b/src/mir/join_ir/lowering/inline_boundary_builder.rs @@ -27,7 +27,7 @@ use crate::mir::ValueId; use super::inline_boundary::{JoinInlineBoundary, LoopExitBinding}; use super::condition_to_joinir::ConditionBinding; -use super::carrier_info::CarrierRole; +use super::carrier_info::CarrierRole; // Phase 228: Restored for test code /// Role of a parameter in JoinIR lowering (Phase 200-A) /// @@ -96,6 +96,7 @@ impl JoinInlineBoundaryBuilder { condition_bindings: vec![], expr_result: None, loop_var_name: None, + carrier_info: None, // Phase 228: Initialize as None } } } @@ -261,6 +262,29 @@ impl JoinInlineBoundaryBuilder { .find(|b| b.name == name) .map(|b| b.join_value) } + + /// Phase 228: Set carrier metadata + /// + /// Provides full carrier information including initialization policies. + /// This allows header PHI generation to handle ConditionOnly carriers + /// with explicit bool initialization. + /// + /// # Arguments + /// + /// * `carrier_info` - Complete carrier metadata from pattern lowerer + /// + /// # Example + /// + /// ```ignore + /// let boundary = JoinInlineBoundaryBuilder::new() + /// .with_inputs(join_inputs, host_inputs) + /// .with_carrier_info(ctx.carrier_info.clone()) + /// .build(); + /// ``` + pub fn with_carrier_info(mut self, carrier_info: super::carrier_info::CarrierInfo) -> Self { + self.boundary.carrier_info = Some(carrier_info); + self + } } impl Default for JoinInlineBoundaryBuilder { diff --git a/src/mir/join_ir/lowering/loop_update_analyzer.rs b/src/mir/join_ir/lowering/loop_update_analyzer.rs index a47be65d..7354303b 100644 --- a/src/mir/join_ir/lowering/loop_update_analyzer.rs +++ b/src/mir/join_ir/lowering/loop_update_analyzer.rs @@ -299,6 +299,7 @@ mod tests { host_id: crate::mir::ValueId(0), join_id: None, // Phase 177-STRUCT-1 role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }]; let updates = LoopUpdateAnalyzer::analyze_carrier_updates(&body, &carriers); @@ -357,6 +358,7 @@ mod tests { host_id: crate::mir::ValueId(0), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }]; let updates = LoopUpdateAnalyzer::analyze_carrier_updates(&body, &carriers); @@ -416,6 +418,7 @@ mod tests { host_id: crate::mir::ValueId(0), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }]; let updates = LoopUpdateAnalyzer::analyze_carrier_updates(&body, &carriers); @@ -475,6 +478,7 @@ mod tests { host_id: crate::mir::ValueId(0), join_id: None, role: crate::mir::join_ir::lowering::carrier_info::CarrierRole::LoopState, + init: crate::mir::join_ir::lowering::carrier_info::CarrierInit::FromHost, // Phase 228 }]; let updates = LoopUpdateAnalyzer::analyze_carrier_updates(&body, &carriers); diff --git a/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs b/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs index ac9c1216..cae5e732 100644 --- a/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs +++ b/src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs @@ -183,12 +183,13 @@ impl DigitPosPromoter { // For DigitPos pattern, we add a NEW carrier (not replace loop_var) let carrier_name = format!("is_{}", var_in_cond); - use crate::mir::join_ir::lowering::carrier_info::{CarrierVar, CarrierRole}; + use crate::mir::join_ir::lowering::carrier_info::{CarrierVar, CarrierRole, CarrierInit}; let promoted_carrier = CarrierVar { name: carrier_name.clone(), host_id: ValueId(0), // Placeholder (will be remapped) join_id: None, // Will be allocated later role: CarrierRole::ConditionOnly, // Phase 227: DigitPos is condition-only + init: CarrierInit::BoolConst(false), // Phase 228: Initialize with false }; // Create CarrierInfo with a dummy loop_var_name (will be ignored during merge)