//! Phase 273 P3: PlanLowerer - CorePlan → MIR 生成 (SSOT) //! //! # Responsibilities //! //! - Receive CorePlan from PlanNormalizer //! - Emit MIR instructions using pre-allocated ValueIds //! - No pattern-specific knowledge (pattern-agnostic) //! //! # Key Design Decision //! //! Lowerer processes CorePlan ONLY. It does not know about scan, split, or //! any other pattern-specific semantics. All pattern knowledge is in Normalizer. //! //! # Phase 273 P3: SSOT Finalization //! //! - Generalized fields (block_effects/phis/frag/final_values) are now REQUIRED //! - Legacy fallback has been removed (Fail-Fast on missing fields) //! - Pattern-specific emission functions (emit_scan_with_init_edgecfg) no longer used use super::{CoreEffectPlan, CoreLoopPlan, CorePlan}; use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext; use crate::mir::builder::MirBuilder; use crate::mir::{MirInstruction, ValueId}; /// Phase 273 P1: PlanLowerer - CorePlan → MIR 生成 (SSOT) pub(in crate::mir::builder) struct PlanLowerer; impl PlanLowerer { /// CorePlan を受け取り、MIR を生成 /// /// # Arguments /// /// * `builder` - MIR builder (mutable access for instruction emission) /// * `plan` - CorePlan from Normalizer (pre-allocated ValueIds) /// * `ctx` - Loop pattern context for debug/func_name pub(in crate::mir::builder) fn lower( builder: &mut MirBuilder, plan: CorePlan, ctx: &LoopPatternContext, ) -> Result, String> { match plan { CorePlan::Seq(plans) => Self::lower_seq(builder, plans, ctx), CorePlan::Loop(loop_plan) => Self::lower_loop(builder, loop_plan, ctx), CorePlan::If(_if_plan) => { // P1: If is handled inline in Loop body Err("[lowerer] Standalone CorePlan::If not yet supported".to_string()) } CorePlan::Effect(effect) => { Self::emit_effect(builder, &effect)?; Ok(None) } CorePlan::Exit(_exit) => { // P1: Exit is handled by edge CFG in Loop Err("[lowerer] Standalone CorePlan::Exit not yet supported".to_string()) } } } /// Seq: process plans in order fn lower_seq( builder: &mut MirBuilder, plans: Vec, ctx: &LoopPatternContext, ) -> Result, String> { let mut result = None; for plan in plans { result = Self::lower(builder, plan, ctx)?; } Ok(result) } /// Loop: emit blocks, effects, PHI, and edge CFG /// /// This is pattern-agnostic. All pattern knowledge is in Normalizer. /// Phase 273 P3: Generalized fields are now REQUIRED (Fail-Fast). fn lower_loop( builder: &mut MirBuilder, loop_plan: CoreLoopPlan, ctx: &LoopPatternContext, ) -> Result, String> { use crate::mir::builder::control_flow::joinir::trace; let trace_logger = trace::trace(); let debug = ctx.debug; if debug { trace_logger.debug( "lowerer/loop", &format!( "Phase 273 P3: Lowering CoreLoopPlan for {}", ctx.func_name ), ); } // Phase 273 P3: Generalized fields are now struct fields (not Option) // No validation needed - type system guarantees presence if debug { trace_logger.debug("lowerer/loop", "Processing generalized fields (SSOT)"); } Self::lower_loop_generalized(builder, loop_plan, ctx) } /// Phase 273 P3: Generalized loop lowering (SSOT) fn lower_loop_generalized( builder: &mut MirBuilder, loop_plan: CoreLoopPlan, ctx: &LoopPatternContext, ) -> Result, String> { use crate::mir::builder::control_flow::joinir::trace; use crate::mir::builder::control_flow::edgecfg::api::emit_frag; let trace_logger = trace::trace(); let debug = ctx.debug; // Phase 273 P3: Direct access (not Option - type system guarantees presence) let block_effects = &loop_plan.block_effects; let phis = &loop_plan.phis; let frag = &loop_plan.frag; let final_values = &loop_plan.final_values; // Step 1: Emit Jump from current block to loop entry if builder.current_block.is_some() { builder.emit_instruction(MirInstruction::Jump { target: frag.entry, edge_args: None, })?; } // Step 2: Emit block effects in SSOT order (preheader, header, body, step) // Note: Body effects are handled separately via body CorePlan for (block_id, effects) in block_effects { builder.start_new_block(*block_id)?; // Special handling for body block: emit body CorePlan instead of effects if *block_id == loop_plan.body_bb { for plan in &loop_plan.body { match plan { CorePlan::Effect(effect) => { Self::emit_effect(builder, effect)?; } _ => { return Err("[lowerer] Non-Effect plan in Loop body not yet supported".to_string()); } } } } else { // Normal block: emit effects for effect in effects { Self::emit_effect(builder, effect)?; } } } if debug { trace_logger.debug( "lowerer/loop_generalized", &format!("Block effects emitted: {} blocks", block_effects.len()), ); } // Step 3: Ensure non-effect blocks exist (after_bb, found_bb, etc.) builder.ensure_block_exists(loop_plan.after_bb)?; builder.ensure_block_exists(loop_plan.found_bb)?; // Step 4: Insert PHIs use crate::mir::builder::emission::phi::insert_loop_phi; for phi in phis { insert_loop_phi( builder, phi.block, phi.dst, phi.inputs.clone(), &phi.tag, )?; } if debug { trace_logger.debug( "lowerer/loop_generalized", &format!("PHI inserted: {} PHIs", phis.len()), ); } // Step 5: Emit Frag (terminators) if let Some(ref mut func) = builder.scope_ctx.current_function { emit_frag(func, frag)?; } else { return Err("[lowerer] current_function is None".to_string()); } if debug { trace_logger.debug("lowerer/loop_generalized", "Frag emitted"); } // Step 6: Update variable_map for final values for (name, value_id) in final_values { builder .variable_ctx .variable_map .insert(name.clone(), *value_id); } // Step 7: Setup after_bb for subsequent AST lowering builder.start_new_block(loop_plan.after_bb)?; // Step 8: Return Void (pattern applied successfully) use crate::mir::builder::emission::constant::emit_void; let void_val = emit_void(builder); if debug { trace_logger.debug( "lowerer/loop_generalized", &format!("Loop complete, returning Void {:?}", void_val), ); } Ok(Some(void_val)) } // Phase 273 P3: lower_loop_legacy() has been REMOVED // All patterns must use generalized fields (block_effects/phis/frag/final_values) // Pattern-specific emission functions (emit_scan_with_init_edgecfg) are no longer used /// Emit a single CoreEffectPlan as MirInstruction fn emit_effect(builder: &mut MirBuilder, effect: &CoreEffectPlan) -> Result<(), String> { match effect { CoreEffectPlan::Const { dst, value } => { builder.emit_instruction(MirInstruction::Const { dst: *dst, value: value.clone(), })?; } CoreEffectPlan::MethodCall { dst, object, method, args, effects } => { // P2: dst and effects are now specified by Normalizer builder.emit_instruction(MirInstruction::BoxCall { dst: *dst, box_val: *object, method: method.clone(), method_id: None, args: args.clone(), effects: *effects, })?; } CoreEffectPlan::BinOp { dst, lhs, op, rhs } => { builder.emit_instruction(MirInstruction::BinOp { dst: *dst, lhs: *lhs, op: *op, rhs: *rhs, })?; } CoreEffectPlan::Compare { dst, lhs, op, rhs } => { builder.emit_instruction(MirInstruction::Compare { dst: *dst, lhs: *lhs, op: *op, rhs: *rhs, })?; } } Ok(()) } }