ssot(cf): bridge set_branch/set_jump/insert_phi adopted across expr/ternary/match/try_catch/loop; builder emission compare/branch/jump delegate to cf_common; add canaries (ternary/match); docs: note cf_common adoption

This commit is contained in:
nyash-codex
2025-11-04 21:33:09 +09:00
parent 51bf7ff410
commit 0996090d6d
15 changed files with 196 additions and 136 deletions

View File

@ -5,11 +5,20 @@ use crate::mir::builder::MirBuilder;
#[inline] #[inline]
pub fn emit_conditional(b: &mut MirBuilder, cond: crate::mir::ValueId, then_bb: BasicBlockId, else_bb: BasicBlockId) -> Result<(), String> { pub fn emit_conditional(b: &mut MirBuilder, cond: crate::mir::ValueId, then_bb: BasicBlockId, else_bb: BasicBlockId) -> Result<(), String> {
if let (Some(func), Some(cur_bb)) = (b.current_function.as_mut(), b.current_block) {
crate::mir::ssot::cf_common::set_branch(func, cur_bb, cond, then_bb, else_bb);
Ok(())
} else {
b.emit_instruction(MirInstruction::Branch { condition: cond, then_bb, else_bb }) b.emit_instruction(MirInstruction::Branch { condition: cond, then_bb, else_bb })
} }
}
#[inline] #[inline]
pub fn emit_jump(b: &mut MirBuilder, target: BasicBlockId) -> Result<(), String> { pub fn emit_jump(b: &mut MirBuilder, target: BasicBlockId) -> Result<(), String> {
if let (Some(func), Some(cur_bb)) = (b.current_function.as_mut(), b.current_block) {
crate::mir::ssot::cf_common::set_jump(func, cur_bb, target);
Ok(())
} else {
b.emit_instruction(MirInstruction::Jump { target }) b.emit_instruction(MirInstruction::Jump { target })
} }
}

View File

@ -5,7 +5,11 @@ use crate::mir::builder::MirBuilder;
#[inline] #[inline]
pub fn emit_to(b: &mut MirBuilder, dst: ValueId, op: CompareOp, lhs: ValueId, rhs: ValueId) -> Result<(), String> { pub fn emit_to(b: &mut MirBuilder, dst: ValueId, op: CompareOp, lhs: ValueId, rhs: ValueId) -> Result<(), String> {
if let (Some(func), Some(cur_bb)) = (b.current_function.as_mut(), b.current_block) {
crate::mir::ssot::cf_common::emit_compare_func(func, cur_bb, dst, op, lhs, rhs);
} else {
b.emit_instruction(MirInstruction::Compare { dst, op, lhs, rhs })?; b.emit_instruction(MirInstruction::Compare { dst, op, lhs, rhs })?;
}
// 比較結果は Bool 型(既存実装と同じ振る舞い) // 比較結果は Bool 型(既存実装と同じ振る舞い)
b.value_types.insert(dst, MirType::Bool); b.value_types.insert(dst, MirType::Bool);
Ok(()) Ok(())
@ -21,4 +25,3 @@ pub fn emit_eq_to(b: &mut MirBuilder, dst: ValueId, lhs: ValueId, rhs: ValueId)
pub fn emit_ne_to(b: &mut MirBuilder, dst: ValueId, lhs: ValueId, rhs: ValueId) -> Result<(), String> { pub fn emit_ne_to(b: &mut MirBuilder, dst: ValueId, lhs: ValueId, rhs: ValueId) -> Result<(), String> {
emit_to(b, dst, CompareOp::Ne, lhs, rhs) emit_to(b, dst, CompareOp::Ne, lhs, rhs)
} }

57
src/mir/ssot/cf_common.rs Normal file
View File

@ -0,0 +1,57 @@
use crate::mir::{BasicBlockId, CompareOp, MirFunction, MirInstruction, ValueId};
/// Emit a MIR Compare instruction into the current block (function-level SSOT helper)
pub fn emit_compare_func(
f: &mut MirFunction,
cur_bb: BasicBlockId,
dst: ValueId,
op: CompareOp,
lhs: ValueId,
rhs: ValueId,
) {
if let Some(bb) = f.get_block_mut(cur_bb) {
bb.add_instruction(MirInstruction::Compare { dst, op, lhs, rhs });
}
}
/// Set a conditional branch terminator on the current block and register predecessors.
pub fn set_branch(
f: &mut MirFunction,
cur_bb: BasicBlockId,
condition: ValueId,
then_bb: BasicBlockId,
else_bb: BasicBlockId,
) {
if let Some(bb) = f.get_block_mut(cur_bb) {
bb.set_terminator(MirInstruction::Branch { condition, then_bb, else_bb });
}
if let Some(tb) = f.get_block_mut(then_bb) {
tb.add_predecessor(cur_bb);
}
if let Some(eb) = f.get_block_mut(else_bb) {
eb.add_predecessor(cur_bb);
}
}
/// Set an unconditional jump terminator and register predecessor on target block.
pub fn set_jump(f: &mut MirFunction, cur_bb: BasicBlockId, target: BasicBlockId) {
if let Some(bb) = f.get_block_mut(cur_bb) {
bb.set_terminator(MirInstruction::Jump { target });
}
if let Some(tb) = f.get_block_mut(target) {
tb.add_predecessor(cur_bb);
}
}
/// Insert a PHI instruction at block head (after existing PHIs) with normalized inputs order.
pub fn insert_phi_at_head(
f: &mut MirFunction,
bb_id: BasicBlockId,
dst: ValueId,
mut inputs: Vec<(BasicBlockId, ValueId)>,
) {
inputs.sort_by_key(|(bb, _)| bb.0);
if let Some(bb) = f.get_block_mut(bb_id) {
bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs });
}
}

View File

@ -1,2 +1,3 @@
pub mod binop_lower; pub mod binop_lower;
pub mod loop_common; pub mod loop_common;
pub mod cf_common;

View File

@ -118,12 +118,8 @@ impl BridgeEnv {
/// Small helper: set Jump terminator and record predecessor on the target. /// Small helper: set Jump terminator and record predecessor on the target.
fn jump_with_pred(f: &mut MirFunction, cur_bb: BasicBlockId, target: BasicBlockId) { fn jump_with_pred(f: &mut MirFunction, cur_bb: BasicBlockId, target: BasicBlockId) {
if let Some(bb) = f.get_block_mut(cur_bb) { // Delegate to SSOT CF helper for consistency
bb.set_terminator(MirInstruction::Jump { target }); crate::mir::ssot::cf_common::set_jump(f, cur_bb, target);
}
if let Some(succ) = f.get_block_mut(target) {
succ.add_predecessor(cur_bb);
}
} }
/// Strip Phi instructions by inserting edge copies on each predecessor. /// Strip Phi instructions by inserting edge copies on each predecessor.

View File

@ -190,14 +190,7 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
_ => return Err("unsupported compare op".into()), _ => return Err("unsupported compare op".into()),
}; };
let dst = f.next_value_id(); let dst = f.next_value_id();
if let Some(bb) = f.get_block_mut(cur_after_r) { crate::mir::ssot::cf_common::emit_compare_func(f, cur_after_r, dst, cop, l, r);
bb.add_instruction(MirInstruction::Compare {
dst,
op: cop,
lhs: l,
rhs: r,
});
}
Ok((dst, cur_after_r)) Ok((dst, cur_after_r))
} }
ExprV0::Logical { op, lhs, rhs } => { ExprV0::Logical { op, lhs, rhs } => {
@ -206,20 +199,10 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
let fall_bb = new_block(f); let fall_bb = new_block(f);
let merge_bb = new_block(f); let merge_bb = new_block(f);
let is_and = matches!(op.as_str(), "&&" | "and"); let is_and = matches!(op.as_str(), "&&" | "and");
if let Some(bb) = f.get_block_mut(cur_after_l) {
if is_and { if is_and {
bb.set_terminator(MirInstruction::Branch { crate::mir::ssot::cf_common::set_branch(f, cur_after_l, l, rhs_bb, fall_bb);
condition: l,
then_bb: rhs_bb,
else_bb: fall_bb,
});
} else { } else {
bb.set_terminator(MirInstruction::Branch { crate::mir::ssot::cf_common::set_branch(f, cur_after_l, l, fall_bb, rhs_bb);
condition: l,
then_bb: fall_bb,
else_bb: rhs_bb,
});
}
} }
// ARCHIVED: JIT events moved to archive/jit-cranelift/ during Phase 15 // ARCHIVED: JIT events moved to archive/jit-cranelift/ during Phase 15
// crate::jit::events::emit_lower( // crate::jit::events::emit_lower(
@ -229,32 +212,21 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
// ); // );
let cdst = f.next_value_id(); let cdst = f.next_value_id();
if let Some(bb) = f.get_block_mut(fall_bb) { if let Some(bb) = f.get_block_mut(fall_bb) {
let cval = if is_and { let cval = if is_and { ConstValue::Bool(false) } else { ConstValue::Bool(true) };
ConstValue::Bool(false)
} else {
ConstValue::Bool(true)
};
bb.add_instruction(MirInstruction::Const { dst: cdst, value: cval }); bb.add_instruction(MirInstruction::Const { dst: cdst, value: cval });
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
} }
crate::mir::ssot::cf_common::set_jump(f, fall_bb, merge_bb);
let (rval, rhs_end) = lower_expr_with_scope(env, f, rhs_bb, rhs, vars)?; let (rval, rhs_end) = lower_expr_with_scope(env, f, rhs_bb, rhs, vars)?;
if let Some(bb) = f.get_block_mut(rhs_end) { if let Some(bb) = f.get_block_mut(rhs_end) {
if !bb.is_terminated() { if !bb.is_terminated() {
bb.set_terminator(MirInstruction::Jump { target: merge_bb }); crate::mir::ssot::cf_common::set_jump(f, rhs_end, merge_bb);
} }
} }
let out = f.next_value_id(); let out = f.next_value_id();
// フェーズM.2: PHI統一処理no_phi分岐削除 // フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(merge_bb) {
let mut inputs: Vec<(BasicBlockId, ValueId)> = vec![(fall_bb, cdst)]; let mut inputs: Vec<(BasicBlockId, ValueId)> = vec![(fall_bb, cdst)];
if rhs_end != fall_bb { if rhs_end != fall_bb { inputs.push((rhs_end, rval)); } else { inputs.push((fall_bb, rval)); }
inputs.push((rhs_end, rval)); crate::mir::ssot::cf_common::insert_phi_at_head(f, merge_bb, out, inputs);
} else {
inputs.push((fall_bb, rval));
}
inputs.sort_by_key(|(bbid, _)| bbid.0);
bb.insert_instruction_after_phis(MirInstruction::Phi { dst: out, inputs });
}
Ok((out, merge_bb)) Ok((out, merge_bb))
} }
ExprV0::Call { name, args } => { ExprV0::Call { name, args } => {

View File

@ -18,34 +18,26 @@ pub(super) fn lower_if_stmt(
let then_bb = new_block(f); let then_bb = new_block(f);
let else_bb = new_block(f); let else_bb = new_block(f);
let merge_bb = new_block(f); let merge_bb = new_block(f);
f.set_branch_terminator(cur, cval, then_bb, else_bb)?; crate::mir::ssot::cf_common::set_branch(f, cur, cval, then_bb, else_bb);
let base_vars = vars.clone(); let base_vars = vars.clone();
let mut then_vars = base_vars.clone(); let mut then_vars = base_vars.clone();
let tend = lower_stmt_list_with_vars(f, then_bb, then_body, &mut then_vars, loop_stack, env)?; let tend = lower_stmt_list_with_vars(f, then_bb, then_body, &mut then_vars, loop_stack, env)?;
let mut then_terminated = false; let mut then_terminated = false;
if let Some(bb) = f.get_block_mut(tend) { if let Some(bb) = f.get_block_mut(tend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb }); else { then_terminated = true; }
} else {
then_terminated = true;
}
} }
let (else_end_pred, else_vars, else_terminated) = if let Some(elses) = else_body { let (else_end_pred, else_vars, else_terminated) = if let Some(elses) = else_body {
let mut ev = base_vars.clone(); let mut ev = base_vars.clone();
let eend = lower_stmt_list_with_vars(f, else_bb, elses, &mut ev, loop_stack, env)?; let eend = lower_stmt_list_with_vars(f, else_bb, elses, &mut ev, loop_stack, env)?;
let mut term = false; let mut term = false;
if let Some(bb) = f.get_block_mut(eend) { if let Some(bb) = f.get_block_mut(eend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb }); else { term = true; }
} else {
term = true;
}
} }
(eend, ev, term) (eend, ev, term)
} else { } else {
if let Some(bb) = f.get_block_mut(else_bb) { crate::mir::ssot::cf_common::set_jump(f, else_bb, merge_bb);
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
}
(else_bb, base_vars.clone(), false) (else_bb, base_vars.clone(), false)
}; };
// If both branches terminate (e.g., both return/throw), no merge or var-join is needed. // If both branches terminate (e.g., both return/throw), no merge or var-join is needed.

View File

@ -33,9 +33,7 @@ pub(super) fn lower_loop_stmt(
// 2) preheader → header へ Jumpヘッダで Phi を組む前に制御を渡す) // 2) preheader → header へ Jumpヘッダで Phi を組む前に制御を渡す)
if let Some(bb) = f.get_block_mut(cur_bb) { if let Some(bb) = f.get_block_mut(cur_bb) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, cur_bb, cond_bb); }
bb.add_instruction(MirInstruction::Jump { target: cond_bb });
}
} }
// 3) LoopPhiOps アダプタ(準備用: preheader seed 専用) // 3) LoopPhiOps アダプタ(準備用: preheader seed 専用)
@ -115,13 +113,7 @@ pub(super) fn lower_loop_stmt(
let header_vars_snapshot = ops.vars.clone(); let header_vars_snapshot = ops.vars.clone();
let (cval, _cend) = super::expr::lower_expr_with_vars(env, ops.f, cond_bb, cond, ops.vars)?; let (cval, _cend) = super::expr::lower_expr_with_vars(env, ops.f, cond_bb, cond, ops.vars)?;
if let Some(bb) = ops.f.get_block_mut(cond_bb) { crate::mir::ssot::cf_common::set_branch(ops.f, cond_bb, cval, body_bb, exit_bb);
bb.set_terminator(MirInstruction::Branch {
condition: cval,
then_bb: body_bb,
else_bb: exit_bb,
});
}
let mut body_vars = ops.vars.clone(); let mut body_vars = ops.vars.clone();
// open snapshot frames for nested break/continue // open snapshot frames for nested break/continue
super::push_loop_snapshot_frames(); super::push_loop_snapshot_frames();
@ -140,9 +132,7 @@ pub(super) fn lower_loop_stmt(
block_var_maps2.insert(cur_bb, base_vars.clone()); block_var_maps2.insert(cur_bb, base_vars.clone());
block_var_maps2.insert(bend, body_vars.clone()); block_var_maps2.insert(bend, body_vars.clone());
if let Some(bb) = ops.f.get_block_mut(bend) { if let Some(bb) = ops.f.get_block_mut(bend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(ops.f, bend, cond_bb); }
bb.set_terminator(MirInstruction::Jump { target: cond_bb });
}
} }
let backedge_to_cond = matches!( let backedge_to_cond = matches!(
ops.f.blocks ops.f.blocks

View File

@ -21,9 +21,7 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
// Set up blocks // Set up blocks
let dispatch_bb = new_block(f); let dispatch_bb = new_block(f);
if let Some(bb) = f.get_block_mut(start_bb) { if let Some(bb) = f.get_block_mut(start_bb) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, start_bb, dispatch_bb); }
bb.set_terminator(MirInstruction::Jump { target: dispatch_bb });
}
} }
let else_bb = new_block(f); let else_bb = new_block(f);
let merge_bb = new_block(f); let merge_bb = new_block(f);
@ -42,16 +40,14 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
if let Some(bb) = f.get_block_mut(cur_dispatch) { if let Some(bb) = f.get_block_mut(cur_dispatch) {
// compare scr_val == label // compare scr_val == label
bb.add_instruction(MirInstruction::Const { dst: ldst, value: ConstValue::String(arm.label.clone()) }); bb.add_instruction(MirInstruction::Const { dst: ldst, value: ConstValue::String(arm.label.clone()) });
bb.add_instruction(MirInstruction::Compare { dst: cond, op: CompareOp::Eq, lhs: scr_val, rhs: ldst });
bb.set_terminator(MirInstruction::Branch { condition: cond, then_bb, else_bb: fall_bb });
} }
crate::mir::ssot::cf_common::emit_compare_func(f, cur_dispatch, cond, CompareOp::Eq, scr_val, ldst);
crate::mir::ssot::cf_common::set_branch(f, cur_dispatch, cond, then_bb, fall_bb);
// Then arm body // Then arm body
let (tval, tend) = lower_expr_with_scope(env, f, then_bb, &arm.expr, vars)?; let (tval, tend) = lower_expr_with_scope(env, f, then_bb, &arm.expr, vars)?;
if let Some(bb) = f.get_block_mut(tend) { if let Some(bb) = f.get_block_mut(tend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
}
} }
phi_inputs.push((tend, tval)); phi_inputs.push((tend, tval));
@ -61,19 +57,14 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
// Else body // Else body
let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_expr, vars)?; let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_expr, vars)?;
if let Some(bb) = f.get_block_mut(eend) { if let Some(bb) = f.get_block_mut(eend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
}
} }
phi_inputs.push((eend, eval)); phi_inputs.push((eend, eval));
// Merge result // Merge result
let out = f.next_value_id(); let out = f.next_value_id();
// フェーズM.2: PHI統一処理no_phi分岐削除 // フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(merge_bb) { let inputs = phi_inputs;
let mut inputs = phi_inputs; crate::mir::ssot::cf_common::insert_phi_at_head(f, merge_bb, out, inputs);
inputs.sort_by_key(|(bbid, _)| bbid.0);
bb.insert_instruction_after_phis(MirInstruction::Phi { dst: out, inputs });
}
Ok((out, merge_bb)) Ok((out, merge_bb))
} }

View File

@ -42,11 +42,13 @@ pub(super) fn merge_values(
if let Some(bb) = f.get_block_mut(pred_b) { if let Some(bb) = f.get_block_mut(pred_b) {
bb.add_instruction_before_terminator(MirInstruction::Copy { dst, src: val_b }); bb.add_instruction_before_terminator(MirInstruction::Copy { dst, src: val_b });
} }
} else if let Some(bb) = f.get_block_mut(merge_bb) { } else {
bb.insert_instruction_after_phis(MirInstruction::Phi { crate::mir::ssot::cf_common::insert_phi_at_head(
f,
merge_bb,
dst, dst,
inputs: vec![(pred_a, val_a), (pred_b, val_b)], vec![(pred_a, val_a), (pred_b, val_b)],
}); );
} }
dst dst
} }
@ -97,4 +99,3 @@ pub(super) fn merge_var_maps(
} }
} }
} }

View File

@ -24,31 +24,18 @@ pub(super) fn lower_ternary_expr_with_scope<S: VarScope>(
let then_bb = new_block(f); let then_bb = new_block(f);
let else_bb = new_block(f); let else_bb = new_block(f);
let merge_bb = new_block(f); let merge_bb = new_block(f);
if let Some(bb) = f.get_block_mut(cur) { crate::mir::ssot::cf_common::set_branch(f, cur, cval, then_bb, else_bb);
bb.set_terminator(MirInstruction::Branch {
condition: cval,
then_bb,
else_bb,
});
}
let (tval, tend) = lower_expr_with_scope(env, f, then_bb, then_e, vars)?; let (tval, tend) = lower_expr_with_scope(env, f, then_bb, then_e, vars)?;
if let Some(bb) = f.get_block_mut(tend) { if let Some(bb) = f.get_block_mut(tend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
}
} }
let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_e, vars)?; let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_e, vars)?;
if let Some(bb) = f.get_block_mut(eend) { if let Some(bb) = f.get_block_mut(eend) {
if !bb.is_terminated() { if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
bb.set_terminator(MirInstruction::Jump { target: merge_bb });
}
} }
let out = f.next_value_id(); let out = f.next_value_id();
// フェーズM.2: PHI統一処理no_phi分岐削除 // フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(merge_bb) {
let mut inputs = vec![(tend, tval), (eend, eval)]; let mut inputs = vec![(tend, tval), (eend, eval)];
inputs.sort_by_key(|(bbid, _)| bbid.0); crate::mir::ssot::cf_common::insert_phi_at_head(f, merge_bb, out, inputs);
bb.insert_instruction_after_phis(MirInstruction::Phi { dst: out, inputs });
}
Ok((out, merge_bb)) Ok((out, merge_bb))
} }

View File

@ -37,12 +37,7 @@ pub(super) fn record_throw(f: &mut MirFunction, from_bb: BasicBlockId, exc_val:
THROW_CTX.with(|slot| { THROW_CTX.with(|slot| {
if let Some(ctx) = slot.borrow_mut().as_mut() { if let Some(ctx) = slot.borrow_mut().as_mut() {
let target = ctx.catch_bb; let target = ctx.catch_bb;
if let Some(bb) = f.get_block_mut(from_bb) { crate::mir::ssot::cf_common::set_jump(f, from_bb, target);
bb.set_terminator(MirInstruction::Jump { target });
}
if let Some(succ) = f.get_block_mut(target) {
succ.add_predecessor(from_bb);
}
ctx.incoming.push((from_bb, exc_val)); ctx.incoming.push((from_bb, exc_val));
Some(target) Some(target)
} else { } else {

View File

@ -69,10 +69,10 @@ pub(super) fn lower_try_stmt(
// フェーズM.2: PHI統一処理no_phi条件削除 // フェーズM.2: PHI統一処理no_phi条件削除
if !incoming_exc.is_empty() { if !incoming_exc.is_empty() {
let phi_dst = f.next_value_id(); let phi_dst = f.next_value_id();
if let Some(bb) = f.get_block_mut(catch_bb) { if let Some(_bb) = f.get_block_mut(catch_bb) {
let mut inputs = incoming_exc.clone(); let mut inputs = incoming_exc.clone();
inputs.sort_by_key(|(bbid, _)| bbid.0); inputs.sort_by_key(|(bbid, _)| bbid.0);
bb.insert_instruction_after_phis(MirInstruction::Phi { dst: phi_dst, inputs }); crate::mir::ssot::cf_common::insert_phi_at_head(f, catch_bb, phi_dst, inputs);
} }
catch_vars.insert(param.clone(), phi_dst); catch_vars.insert(param.clone(), phi_dst);
} }
@ -125,8 +125,8 @@ pub(super) fn lower_try_stmt(
phi_entries.push((dst, inputs)); phi_entries.push((dst, inputs));
merged_vars.insert(name.clone(), dst); merged_vars.insert(name.clone(), dst);
} }
if let Some(bb) = f.get_block_mut(finally_block) { if let Some(_bb) = f.get_block_mut(finally_block) {
for (dst, inputs) in phi_entries { bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs }); } for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
} }
let mut finally_vars = merged_vars.clone(); let mut finally_vars = merged_vars.clone();
let final_end = super::lower_stmt_list_with_vars(f, finally_block, finally, &mut finally_vars, loop_stack, env)?; let final_end = super::lower_stmt_list_with_vars(f, finally_block, finally, &mut finally_vars, loop_stack, env)?;
@ -156,8 +156,8 @@ pub(super) fn lower_try_stmt(
phi_entries.push((dst, inputs)); phi_entries.push((dst, inputs));
merged_vars.insert(name.clone(), dst); merged_vars.insert(name.clone(), dst);
} }
if let Some(bb) = f.get_block_mut(exit_bb) { if let Some(_bb) = f.get_block_mut(exit_bb) {
for (dst, inputs) in phi_entries { bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs }); } for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
} }
*vars = merged_vars; *vars = merged_vars;
return Ok(exit_bb); return Ok(exit_bb);
@ -259,10 +259,8 @@ pub(super) fn lower_try_stmt(
merged_vars.insert(name.clone(), dst); merged_vars.insert(name.clone(), dst);
} }
// フェーズM.2: PHI統一処理no_phi分岐削除 // フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(finally_block) { if let Some(_bb) = f.get_block_mut(finally_block) {
for (dst, inputs) in phi_entries { for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs });
}
} }
let mut finally_vars = merged_vars.clone(); let mut finally_vars = merged_vars.clone();
let final_end = lower_stmt_list_with_vars( let final_end = lower_stmt_list_with_vars(
@ -310,10 +308,8 @@ pub(super) fn lower_try_stmt(
merged_vars.insert(name.clone(), dst); merged_vars.insert(name.clone(), dst);
} }
// フェーズM.2: PHI統一処理no_phi分岐削除 // フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(exit_bb) { if let Some(_bb) = f.get_block_mut(exit_bb) {
for (dst, inputs) in phi_entries { for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
bb.insert_instruction_after_phis(MirInstruction::Phi { dst, inputs });
}
} }
*vars = merged_vars; *vars = merged_vars;
Ok(exit_bb) Ok(exit_bb)

View File

@ -0,0 +1,38 @@
#!/bin/bash
# Match lowering via JSON v0 bridge (SSOT cf_common) → expect rc=2
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
tmp_json="/tmp/program_match_$$.json"
cat > "$tmp_json" <<'JSON'
{
"version": 0,
"kind": "Program",
"body": [
{ "type":"Local", "name":"s", "expr": {"type":"Str","value":"b"} },
{ "type":"Local", "name":"x", "expr": {"type":"Match","scrutinee":{"type":"Var","name":"s"},
"arms":[
{"label":"a","expr":{"type":"Int","value":1}},
{"label":"b","expr":{"type":"Int","value":2}}
],
"else":{"type":"Int","value":9}
} },
{ "type":"Return", "expr": {"type":"Var","name":"x"} }
]
}
JSON
set +e
HAKO_VERIFY_PRIMARY=core verify_mir_rc "$tmp_json" >/dev/null 2>&1
rc=$?
set -e
rm -f "$tmp_json" || true
if [ "$rc" -eq 2 ]; then
echo "[PASS] mirbuilder_match_core_exec_canary_vm"
exit 0
fi
echo "[FAIL] mirbuilder_match_core_exec_canary_vm (rc=$rc, expect 2)" >&2; exit 1

View File

@ -0,0 +1,32 @@
#!/bin/bash
# Ternary lowering via JSON v0 bridge (SSOT cf_common) → expect rc=1
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"; if ROOT_GIT=$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null); then ROOT="$ROOT_GIT"; else ROOT="$(cd "$SCRIPT_DIR/../../../../../../../../.." && pwd)"; fi
source "$ROOT/tools/smokes/v2/lib/test_runner.sh"; require_env || exit 2
tmp_json="/tmp/program_ternary_$$.json"
cat > "$tmp_json" <<'JSON'
{
"version": 0,
"kind": "Program",
"body": [
{ "type":"Local", "name":"c", "expr": {"type":"Bool","value":true} },
{ "type":"Local", "name":"x", "expr": {"type":"Ternary", "cond":{"type":"Var","name":"c"}, "then":{"type":"Int","value":1}, "else":{"type":"Int","value":2}} },
{ "type":"Return", "expr": {"type":"Var","name":"x"} }
]
}
JSON
set +e
HAKO_VERIFY_PRIMARY=core verify_mir_rc "$tmp_json" >/dev/null 2>&1
rc=$?
set -e
rm -f "$tmp_json" || true
if [ "$rc" -eq 1 ]; then
echo "[PASS] mirbuilder_ternary_core_exec_canary_vm"
exit 0
fi
echo "[FAIL] mirbuilder_ternary_core_exec_canary_vm (rc=$rc, expect 1)" >&2; exit 1