From d16800741f18ad85cc2d5e3223a49811b9d9cec5 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Mon, 22 Dec 2025 23:18:51 +0900 Subject: [PATCH] feat(plan): Phase 273 P2 Step 1-2 - CoreLoopPlan generalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize CoreLoopPlan for Pattern7+ support: New structures (mod.rs): - CorePhiInfo: PHI info with block, dst, inputs, tag - CoreLoopPlan new optional fields: - block_effects: Vec<(BasicBlockId, Vec)> - phis: Vec - frag: Frag (EdgeCFG) - final_values: Vec<(String, ValueId)> Normalizer (normalizer.rs): - Pattern6 now populates all new fields - Frag construction matches emit_scan_with_init_edgecfg - SSOT ordering: preheader → header → body → step Lowerer (lowerer.rs): - lower_loop() dispatches to generalized or legacy path - lower_loop_generalized(): emit blocks → PHI → emit_frag() - lower_loop_legacy(): backward compatible fallback Test: phase258_p0_index_of_string_vm PASS (exit=6) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/mir/builder/control_flow/plan/lowerer.rs | 150 +++++++++++++++++- src/mir/builder/control_flow/plan/mod.rs | 29 ++++ .../builder/control_flow/plan/normalizer.rs | 84 +++++++++- 3 files changed, 260 insertions(+), 3 deletions(-) diff --git a/src/mir/builder/control_flow/plan/lowerer.rs b/src/mir/builder/control_flow/plan/lowerer.rs index 5f072352..703eb1a6 100644 --- a/src/mir/builder/control_flow/plan/lowerer.rs +++ b/src/mir/builder/control_flow/plan/lowerer.rs @@ -66,6 +66,7 @@ impl PlanLowerer { /// Loop: emit blocks, effects, PHI, and edge CFG /// /// This is pattern-agnostic. All pattern knowledge is in Normalizer. + /// Phase 273 P2: Now supports generalized fields with fallback to legacy. fn lower_loop( builder: &mut MirBuilder, loop_plan: CoreLoopPlan, @@ -80,12 +81,159 @@ impl PlanLowerer { trace_logger.debug( "lowerer/loop", &format!( - "Phase 273 P1: Lowering CoreLoopPlan for {}", + "Phase 273 P2: Lowering CoreLoopPlan for {}", ctx.func_name ), ); } + // Phase 273 P2: Check if using generalized fields + let use_generalized = loop_plan.block_effects.is_some() + && loop_plan.phis.is_some() + && loop_plan.frag.is_some() + && loop_plan.final_values.is_some(); + + if use_generalized { + if debug { + trace_logger.debug("lowerer/loop", "Using generalized fields"); + } + Self::lower_loop_generalized(builder, loop_plan, ctx) + } else { + if debug { + trace_logger.debug("lowerer/loop", "Using legacy fields (fallback)"); + } + Self::lower_loop_legacy(builder, loop_plan, ctx) + } + } + + /// Phase 273 P2: Generalized loop lowering + 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; + + let block_effects = loop_plan.block_effects.as_ref().unwrap(); + let phis = loop_plan.phis.as_ref().unwrap(); + let frag = loop_plan.frag.as_ref().unwrap(); + let final_values = loop_plan.final_values.as_ref().unwrap(); + + // 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 P2: Legacy loop lowering (fallback for old Normalizer) + fn lower_loop_legacy( + 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; + // Step 1: Emit Jump from preheader (current block) to header if builder.current_block.is_some() { builder.emit_instruction(MirInstruction::Jump { diff --git a/src/mir/builder/control_flow/plan/mod.rs b/src/mir/builder/control_flow/plan/mod.rs index f1024cfe..e5da60a0 100644 --- a/src/mir/builder/control_flow/plan/mod.rs +++ b/src/mir/builder/control_flow/plan/mod.rs @@ -25,6 +25,7 @@ use crate::ast::ASTNode; use crate::mir::{BasicBlockId, BinaryOp, CompareOp, ConstValue, EffectMask, ValueId}; +use crate::mir::builder::control_flow::edgecfg::api::Frag; pub(in crate::mir::builder) mod lowerer; pub(in crate::mir::builder) mod normalizer; @@ -104,6 +105,19 @@ pub(in crate::mir::builder) enum CorePlan { Exit(CoreExitPlan), } +/// Phase 273 P2: PHI information for generalized CoreLoopPlan +#[derive(Debug, Clone)] +pub(in crate::mir::builder) struct CorePhiInfo { + /// Block where PHI is located + pub block: BasicBlockId, + /// Destination ValueId for PHI + pub dst: ValueId, + /// PHI inputs: (predecessor_block, value) + pub inputs: Vec<(BasicBlockId, ValueId)>, + /// Tag for debugging (e.g., "loop_carrier_i") + pub tag: String, +} + /// Phase 273 P1: Loop plan with carriers #[derive(Debug, Clone)] pub(in crate::mir::builder) struct CoreLoopPlan { @@ -151,6 +165,21 @@ pub(in crate::mir::builder) struct CoreLoopPlan { /// Loop variable name (for variable_map update after loop) pub loop_var_name: String, + + // === Phase 273 P2: Generalized fields (for Pattern7+ support) === + + /// Block-level effects (generalized for multiple blocks) + /// Order: SSOT - preheader, header, body, step + pub block_effects: Option)>>, + + /// PHI information (generalized for multiple blocks) + pub phis: Option>, + + /// Edge CFG fragment (generalized terminator structure) + pub frag: Option, + + /// Final values for variable_map update (after loop exit) + pub final_values: Option>, } /// Phase 273 P1: Loop carrier (PHI variable) diff --git a/src/mir/builder/control_flow/plan/normalizer.rs b/src/mir/builder/control_flow/plan/normalizer.rs index 6753aea0..3d1847e0 100644 --- a/src/mir/builder/control_flow/plan/normalizer.rs +++ b/src/mir/builder/control_flow/plan/normalizer.rs @@ -12,11 +12,14 @@ //! Lowerer processes CorePlan without any pattern knowledge. use super::{ - CoreCarrierInfo, CoreEffectPlan, CoreLoopPlan, CorePlan, DomainPlan, ScanWithInitPlan, + CoreCarrierInfo, CoreEffectPlan, CoreLoopPlan, CorePhiInfo, CorePlan, DomainPlan, ScanWithInitPlan, }; use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext; use crate::mir::builder::MirBuilder; use crate::mir::{BinaryOp, CompareOp, ConstValue, Effect, EffectMask, MirType}; +use crate::mir::builder::control_flow::edgecfg::api::{BranchStub, EdgeStub, ExitKind, Frag}; +use crate::mir::basic_block::EdgeArgs; +use crate::mir::join_ir::lowering::inline_boundary::JumpArgsLayout; /// Phase 273 P1: PlanNormalizer - DomainPlan → CorePlan 変換 (SSOT) pub(in crate::mir::builder) struct PlanNormalizer; @@ -259,7 +262,79 @@ impl PlanNormalizer { }, ]; - // Step 8: Build CoreLoopPlan + // Step 8: Build block_effects (Phase 273 P2) + // SSOT ordering: preheader (empty), header, body (already in body plan), step + let block_effects = vec![ + (preheader_bb, vec![]), // No effects in preheader + (header_bb, header_effects.clone()), + (body_bb, vec![]), // Body effects are in body CorePlan + (step_bb, step_effects.clone()), + ]; + + // Step 9: Build phis (Phase 273 P2) + let phis = vec![CorePhiInfo { + block: header_bb, + dst: i_current, + inputs: vec![ + (preheader_bb, i_init_val), + (step_bb, i_next_val), + ], + tag: format!("loop_carrier_{}", parts.loop_var), + }]; + + // Step 10: Build Frag (Phase 273 P2) + let empty_args = EdgeArgs { + layout: JumpArgsLayout::CarriersOnly, + values: vec![], + }; + + let ret_found_args = EdgeArgs { + layout: JumpArgsLayout::CarriersOnly, + values: vec![i_current], + }; + + let branches = vec![ + BranchStub { + from: header_bb, + cond: cond_loop, + then_target: body_bb, + then_args: empty_args.clone(), + else_target: after_bb, + else_args: empty_args.clone(), + }, + BranchStub { + from: body_bb, + cond: cond_match, + then_target: found_bb, + then_args: empty_args.clone(), + else_target: step_bb, + else_args: empty_args.clone(), + }, + ]; + + let wires = vec![ + EdgeStub { + from: step_bb, + kind: ExitKind::Normal, + target: Some(header_bb), + args: empty_args, + }, + EdgeStub { + from: found_bb, + kind: ExitKind::Return, + target: None, + args: ret_found_args, + }, + ]; + + let mut frag = Frag::new(header_bb); + frag.branches = branches; + frag.wires = wires; + + // Step 11: Build final_values (Phase 273 P2) + let final_values = vec![(parts.loop_var.clone(), i_current)]; + + // Step 12: Build CoreLoopPlan let loop_plan = CoreLoopPlan { preheader_bb, header_bb, @@ -279,6 +354,11 @@ impl PlanNormalizer { cond_loop, cond_match, loop_var_name: parts.loop_var, + // Phase 273 P2: Generalized fields populated + block_effects: Some(block_effects), + phis: Some(phis), + frag: Some(frag), + final_values: Some(final_values), }; if debug {