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:
@ -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 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
57
src/mir/ssot/cf_common.rs
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,2 +1,3 @@
|
|||||||
pub mod binop_lower;
|
pub mod binop_lower;
|
||||||
pub mod loop_common;
|
pub mod loop_common;
|
||||||
|
pub mod cf_common;
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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 } => {
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
Reference in New Issue
Block a user