diff --git a/src/mir/loop_builder.rs b/src/mir/loop_builder.rs index ab223291..bba016a1 100644 --- a/src/mir/loop_builder.rs +++ b/src/mir/loop_builder.rs @@ -654,17 +654,42 @@ impl<'a> LoopBuilder<'a> { // Region 情報(entry/exit/slots)をログに出すよ。 crate::mir::region::observer::observe_control_form(self.parent_builder, &form); - // [LoopForm] exit PHI for Case A/B (uses exit_snapshots + exit_preds) - // - Case A: header+break → exit PHI includes both paths - // - Case B: break-only → exit PHI excludes header (not a predecessor) - let exit_snaps = self.exit_snapshots.clone(); - crate::mir::phi_core::loopform_builder::build_exit_phis_for_control( - &loopform, - self, - &form, - &exit_snaps, - branch_source_block, - )?; + // Phase 27.6-2: JoinIR Exit φ バイパスチェック + let fn_name = self + .parent_builder + .current_function + .as_ref() + .map(|f| f.signature.name.as_str()) + .unwrap_or(""); + + let exit_bypass = crate::mir::phi_core::exit_phi_builder::joinir_exit_bypass_enabled() + && crate::mir::phi_core::exit_phi_builder::is_joinir_exit_bypass_target(fn_name); + + if exit_bypass { + // Phase 27.6-2: JoinIR 実験経路では Exit φ を生成しない。 + // ループ内で定義された値だけで exit 後を構成する(JoinIR の k_exit 引数として表現)。 + // + // ⚠️ 重要: このモードでは MIR は不完全(Exit φ 抜け)であり、VM で実行できない。 + // JoinIR runner 専用モードであることに注意。 + if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() { + eprintln!( + "[loopform/exit-bypass] func={} exit={:?} header={:?} (JoinIR experiment only)", + fn_name, exit_id, header_id + ); + } + } else { + // [LoopForm] exit PHI for Case A/B (uses exit_snapshots + exit_preds) + // - Case A: header+break → exit PHI includes both paths + // - Case B: break-only → exit PHI excludes header (not a predecessor) + let exit_snaps = self.exit_snapshots.clone(); + crate::mir::phi_core::loopform_builder::build_exit_phis_for_control( + &loopform, + self, + &form, + &exit_snaps, + branch_source_block, + )?; + } // Pop loop context crate::mir::builder::loops::pop_loop_context(self.parent_builder); diff --git a/src/mir/phi_core/exit_phi_builder.rs b/src/mir/phi_core/exit_phi_builder.rs index 35d1e6c5..c2116c71 100644 --- a/src/mir/phi_core/exit_phi_builder.rs +++ b/src/mir/phi_core/exit_phi_builder.rs @@ -394,6 +394,30 @@ impl LoopFormOps for T { } } +// ============================================================================ +// Phase 27.6-2: JoinIR Exit φ バイパス用ヘルパー関数 +// ============================================================================ + +/// JoinIR Exit φ 縮退実験トグル +/// +/// - NYASH_JOINIR_EXPERIMENT=1 +/// - NYASH_JOINIR_EXIT_EXP=1 +/// +/// の両方が立っているときだけ true。 +pub(crate) fn joinir_exit_bypass_enabled() -> bool { + crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_EXPERIMENT") + && crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_EXIT_EXP") +} + +/// Exit φ バイパス対象の関数かどうか +/// +/// 当面は minimal/trim の 2 本だけ: +/// - Main.skip/1 +/// - FuncScannerBox.trim/1 +pub(crate) fn is_joinir_exit_bypass_target(func_name: &str) -> bool { + matches!(func_name, "Main.skip/1" | "FuncScannerBox.trim/1") +} + // ============================================================================ // Unit Tests // ============================================================================