use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext}; use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId}; use std::collections::HashMap; use super::super::ast::StmtV0; use super::super::ast::ExprV0; pub(super) fn lower_loop_stmt( f: &mut MirFunction, cur_bb: BasicBlockId, cond: &ExprV0, body: &[StmtV0], vars: &mut HashMap, loop_stack: &mut Vec, env: &BridgeEnv, ) -> Result { let cond_bb = new_block(f); let body_bb = new_block(f); let exit_bb = new_block(f); // フェーズM.2: no_phi変数削除 + PHI UseBeforeDef修正 let base_vars = vars.clone(); let orig_names: Vec = base_vars.keys().cloned().collect(); // Step 1: cur_bbでCopy命令を先に生成(PHI inputsの定義を確保) let mut copy_map: HashMap = HashMap::new(); for name in &orig_names { if let Some(&bval) = base_vars.get(name) { let copy_dst = f.next_value_id(); if let Some(bb) = f.get_block_mut(cur_bb) { bb.add_instruction(MirInstruction::Copy { dst: copy_dst, src: bval, }); } copy_map.insert(name.clone(), copy_dst); } } // Step 2: cur_bbからcond_bbへのJumpを挿入 if let Some(bb) = f.get_block_mut(cur_bb) { if !bb.is_terminated() { bb.add_instruction(MirInstruction::Jump { target: cond_bb }); } } // Step 3: cond_bbでPHI命令生成(copy_mapの値を使用) let mut phi_map: HashMap = HashMap::new(); for name in &orig_names { if let Some(©_val) = copy_map.get(name) { let dst = f.next_value_id(); if let Some(bb) = f.get_block_mut(cond_bb) { bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs: vec![(cur_bb, copy_val)], }); } // 開発時検証(SSOTと同等の不変条件チェック) #[cfg(debug_assertions)] { crate::mir::phi_core::common::debug_verify_phi_inputs( f, cond_bb, &[(cur_bb, copy_val)], ); } phi_map.insert(name.clone(), dst); } } for (name, &phi) in &phi_map { vars.insert(name.clone(), phi); } let (cval, _cend) = super::expr::lower_expr_with_vars(env, f, cond_bb, cond, vars)?; if let Some(bb) = f.get_block_mut(cond_bb) { bb.set_terminator(MirInstruction::Branch { condition: cval, then_bb: body_bb, else_bb: exit_bb, }); } let mut body_vars = vars.clone(); loop_stack.push(LoopContext { cond_bb, exit_bb }); let bend_res = lower_stmt_list_with_vars(f, body_bb, body, &mut body_vars, loop_stack, env); loop_stack.pop(); let bend = bend_res?; if let Some(bb) = f.get_block_mut(bend) { if !bb.is_terminated() { bb.set_terminator(MirInstruction::Jump { target: cond_bb }); } } let backedge_to_cond = matches!( f.blocks .get(&bend) .and_then(|bb| bb.terminator.as_ref()), Some(MirInstruction::Jump { target, .. }) if *target == cond_bb ); if backedge_to_cond { // フェーズM.2: PHI統一処理(no_phi分岐削除) if let Some(bb) = f.get_block_mut(cond_bb) { for (name, &phi_dst) in &phi_map { if let Some(&latch_val) = body_vars.get(name) { bb.update_phi_input(phi_dst, (bend, latch_val))?; // 2要素目(preheader copy + latch)の到達検証 #[cfg(debug_assertions)] { if let Some(&pre_copy) = copy_map.get(name) { crate::mir::phi_core::common::debug_verify_phi_inputs( f, cond_bb, &[(cur_bb, pre_copy), (bend, latch_val)], ); } } } } } } for (name, &phi) in &phi_map { vars.insert(name.clone(), phi); } Ok(exit_bb) }