diff --git a/src/mir/builder/if_form.rs b/src/mir/builder/if_form.rs index 601c7612..69742d07 100644 --- a/src/mir/builder/if_form.rs +++ b/src/mir/builder/if_form.rs @@ -1,6 +1,79 @@ use super::{MirBuilder, ValueId}; use crate::ast::ASTNode; +use crate::mir::control_form::IfShape; use crate::mir::loop_api::LoopBuilderApi; // for current_block() +use crate::mir::phi_core::phi_builder_box::PhiBuilderOps; +use crate::mir::{BasicBlockId, ConstValue, MirInstruction}; + +/// Phase 61-4-F: MirBuilder 用 PhiBuilderOps 実装 +/// +/// ループ外 if の JoinIR 経路で emit_toplevel_phis() を呼ぶためのラッパー。 +struct ToplevelOps<'a>(&'a mut MirBuilder); + +impl<'a> PhiBuilderOps for ToplevelOps<'a> { + fn new_value(&mut self) -> ValueId { + self.0.next_value_id() + } + + fn emit_phi( + &mut self, + block: BasicBlockId, + dst: ValueId, + inputs: Vec<(BasicBlockId, ValueId)>, + ) -> Result<(), String> { + // merge ブロックの先頭に PHI を挿入 + if let (Some(func), Some(_cur_bb)) = (self.0.current_function.as_mut(), self.0.current_block) + { + crate::mir::ssot::cf_common::insert_phi_at_head_spanned( + func, + block, + dst, + inputs, + self.0.current_span, + ); + } else { + self.0.emit_instruction(MirInstruction::Phi { dst, inputs })?; + } + Ok(()) + } + + fn update_var(&mut self, name: String, value: ValueId) { + self.0.variable_map.insert(name, value); + } + + fn get_block_predecessors(&self, block: BasicBlockId) -> Vec { + if let Some(ref func) = self.0.current_function { + func.blocks + .get(&block) + .map(|bb| bb.predecessors.iter().copied().collect()) + .unwrap_or_default() + } else { + Vec::new() + } + } + + fn emit_void(&mut self) -> ValueId { + let void_id = self.0.next_value_id(); + let _ = self.0.emit_instruction(MirInstruction::Const { + dst: void_id, + value: ConstValue::Void, + }); + void_id + } + + fn set_current_block(&mut self, block: BasicBlockId) -> Result<(), String> { + self.0.current_block = Some(block); + Ok(()) + } + + fn block_exists(&self, block: BasicBlockId) -> bool { + if let Some(ref func) = self.0.current_function { + func.blocks.contains_key(&block) + } else { + false + } + } +} impl MirBuilder { /// Lower an if/else using a structured IfForm (header→then/else→merge). @@ -178,15 +251,37 @@ impl MirBuilder { ); } - // 本番経路が有効な場合のみ success = true + // Phase 61-4-F: 本番経路 - emit_toplevel_phis でPHI生成 if joinir_toplevel { - joinir_success = true; - // TODO: Phase 61-4-E 本番経路のPHI生成 - // 現時点では dry-run 的動作(フォールバック経路を使用) + // IfShape 構築 + let if_shape = IfShape { + cond_block: pre_branch_bb, + then_block, + else_block: Some(else_block), + merge_block, + }; + + // PHI 生成 + let phi_count = { + let mut ops = ToplevelOps(self); + crate::mir::loop_builder::IfInLoopPhiEmitter::emit_toplevel_phis( + &phi_spec, + &pre_if_var_map, + &then_var_map_end, + else_var_map_end_opt.as_ref(), + &mut ops, + &if_shape, + )? + }; + if joinir_dryrun { - eprintln!("[Phase 61-4] ⚠️ Production path not yet implemented, using fallback"); + eprintln!( + "[Phase 61-4] ✅ Production path: {} PHIs generated via JoinIR", + phi_count + ); } - joinir_success = false; // フォールバック使用 + + joinir_success = true; } } None => { diff --git a/src/mir/join_ir/lowering/mod.rs b/src/mir/join_ir/lowering/mod.rs index 472c6705..ee2d8c89 100644 --- a/src/mir/join_ir/lowering/mod.rs +++ b/src/mir/join_ir/lowering/mod.rs @@ -157,6 +157,7 @@ pub fn try_lower_if_to_joinir( func.signature.name.starts_with("IfSelectTest.") || func.signature.name.starts_with("IfSelectLocalTest.") || // Phase 33-10 test func.signature.name.starts_with("IfMergeTest.") || + func.signature.name.starts_with("IfToplevelTest.") || // Phase 61-4: loop-outside if test func.signature.name.starts_with("Stage1JsonScannerTestBox.") || // Phase 33-5 test // Stage-1 rollout (env-controlled)