feat(mir): Phase 63-6-1/2 MIR Phi type_hint field & JoinIR propagation
Phase 63-6-1: MirInstruction::Phi に type_hint フィールド追加 - Added `type_hint: Option<MirType>` field to Phi instruction - Updated 21 files with type_hint initialization (all set to None for legacy paths) - Pattern matching updated across codebase (11 files) - Test code updated (basic_block.rs) Phase 63-6-2: JoinIR→MIR Bridge で型ヒント伝播実装 - Modified convert.rs: Select → MIR now creates PHI with type_hint - Removed Copy instructions from then/else blocks - PHI instruction at merge block receives type_hint from JoinIR Select - Test verification: ✅ Type hint propagation successful (Some(Integer)) Modified files: - instruction.rs: Added type_hint field definition - join_ir_vm_bridge/convert.rs: Select lowering with PHI + type_hint - 19 other files: type_hint field initialization Test results: - ✅ test_type_hint_propagation_simple: Type hint = Some(Integer) confirmed - ✅ 7/8 if_select tests passing (1 race condition, passes individually) Next: Phase 63-6-3 (lifecycle.rs で型ヒント使用) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -172,7 +172,7 @@ impl MirInterpreter {
|
|||||||
self.last_block = Some(block.id);
|
self.last_block = Some(block.id);
|
||||||
self.last_inst_index = Some(idx);
|
self.last_inst_index = Some(idx);
|
||||||
self.last_inst = Some(inst.clone());
|
self.last_inst = Some(inst.clone());
|
||||||
if let MirInstruction::Phi { dst, inputs } = inst {
|
if let MirInstruction::Phi { dst, inputs, .. } = inst {
|
||||||
let dst_id = *dst;
|
let dst_id = *dst;
|
||||||
if trace_phi {
|
if trace_phi {
|
||||||
let in_preds: Vec<_> = inputs.iter().map(|(bb, _)| *bb).collect();
|
let in_preds: Vec<_> = inputs.iter().map(|(bb, _)| *bb).collect();
|
||||||
|
|||||||
@ -324,7 +324,7 @@ impl BasicBlock {
|
|||||||
incoming: (BasicBlockId, ValueId),
|
incoming: (BasicBlockId, ValueId),
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
for inst in &mut self.instructions {
|
for inst in &mut self.instructions {
|
||||||
if let MirInstruction::Phi { dst, inputs } = inst {
|
if let MirInstruction::Phi { dst, inputs, .. } = inst {
|
||||||
if *dst == phi_dst {
|
if *dst == phi_dst {
|
||||||
inputs.push(incoming);
|
inputs.push(incoming);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -580,6 +580,7 @@ mod tests {
|
|||||||
let phi_inst = MirInstruction::Phi {
|
let phi_inst = MirInstruction::Phi {
|
||||||
dst: ValueId::new(0),
|
dst: ValueId::new(0),
|
||||||
inputs: vec![(BasicBlockId::new(1), ValueId::new(1))],
|
inputs: vec![(BasicBlockId::new(1), ValueId::new(1))],
|
||||||
|
type_hint: None, // Phase 63-6: Test code, no type hint
|
||||||
};
|
};
|
||||||
bb.add_instruction(phi_inst);
|
bb.add_instruction(phi_inst);
|
||||||
|
|
||||||
|
|||||||
@ -604,7 +604,7 @@ impl MirBuilder {
|
|||||||
.map(|f| f.signature.name.clone());
|
.map(|f| f.signature.name.clone());
|
||||||
let _dbg_region_id = self.debug_current_region_id();
|
let _dbg_region_id = self.debug_current_region_id();
|
||||||
// P0: PHI の軽量補強と観測は、関数ブロック取得前に実施して借用競合を避ける
|
// P0: PHI の軽量補強と観測は、関数ブロック取得前に実施して借用競合を避ける
|
||||||
if let MirInstruction::Phi { dst, inputs } = &instruction {
|
if let MirInstruction::Phi { dst, inputs, .. } = &instruction {
|
||||||
origin::phi::propagate_phi_meta(self, *dst, inputs);
|
origin::phi::propagate_phi_meta(self, *dst, inputs);
|
||||||
observe::ssa::emit_phi(self, *dst, inputs);
|
observe::ssa::emit_phi(self, *dst, inputs);
|
||||||
}
|
}
|
||||||
@ -815,7 +815,7 @@ impl MirBuilder {
|
|||||||
if let Some(block_data) = function.get_block_mut(block) {
|
if let Some(block_data) = function.get_block_mut(block) {
|
||||||
// Find PHI instruction with matching dst
|
// Find PHI instruction with matching dst
|
||||||
for inst in &mut block_data.instructions {
|
for inst in &mut block_data.instructions {
|
||||||
if let MirInstruction::Phi { dst, inputs } = inst {
|
if let MirInstruction::Phi { dst, inputs, .. } = inst {
|
||||||
if *dst == phi_id {
|
if *dst == phi_id {
|
||||||
*inputs = new_inputs;
|
*inputs = new_inputs;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|||||||
@ -542,7 +542,7 @@ impl super::MirBuilder {
|
|||||||
values.insert(*v);
|
values.insert(*v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MirInstruction::Phi { dst, inputs } => {
|
MirInstruction::Phi { dst, inputs, type_hint: None } => {
|
||||||
values.insert(*dst);
|
values.insert(*dst);
|
||||||
for (_, val) in inputs {
|
for (_, val) in inputs {
|
||||||
values.insert(*val);
|
values.insert(*val);
|
||||||
@ -651,12 +651,13 @@ impl super::MirBuilder {
|
|||||||
MirInstruction::Return { value } => MirInstruction::Return {
|
MirInstruction::Return { value } => MirInstruction::Return {
|
||||||
value: value.map(remap_value),
|
value: value.map(remap_value),
|
||||||
},
|
},
|
||||||
MirInstruction::Phi { dst, inputs } => MirInstruction::Phi {
|
MirInstruction::Phi { dst, inputs, type_hint: None } => MirInstruction::Phi {
|
||||||
dst: remap_value(*dst),
|
dst: remap_value(*dst),
|
||||||
inputs: inputs
|
inputs: inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(bb, val)| (remap_block(*bb), remap_value(*val)))
|
.map(|(bb, val)| (remap_block(*bb), remap_value(*val)))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
type_hint: None, // Phase 63-6: Preserve no type hint during remapping
|
||||||
},
|
},
|
||||||
MirInstruction::Copy { dst, src } => MirInstruction::Copy {
|
MirInstruction::Copy { dst, src } => MirInstruction::Copy {
|
||||||
dst: remap_value(*dst),
|
dst: remap_value(*dst),
|
||||||
|
|||||||
@ -130,6 +130,7 @@ impl super::MirBuilder {
|
|||||||
self.emit_instruction(super::MirInstruction::Phi {
|
self.emit_instruction(super::MirInstruction::Phi {
|
||||||
dst: result_val,
|
dst: result_val,
|
||||||
inputs: phi_inputs,
|
inputs: phi_inputs,
|
||||||
|
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(result_val)
|
Ok(result_val)
|
||||||
|
|||||||
@ -32,7 +32,7 @@ impl<'a> PhiBuilderOps for ToplevelOps<'a> {
|
|||||||
self.0.current_span,
|
self.0.current_span,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
self.0.emit_instruction(MirInstruction::Phi { dst, inputs })?;
|
self.0.emit_instruction(MirInstruction::Phi { dst, inputs, type_hint: None })?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,6 +91,7 @@ impl MirBuilder {
|
|||||||
self.emit_instruction(MirInstruction::Phi {
|
self.emit_instruction(MirInstruction::Phi {
|
||||||
dst: merged,
|
dst: merged,
|
||||||
inputs,
|
inputs,
|
||||||
|
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
self.variable_map.insert(pin_name.clone(), merged);
|
self.variable_map.insert(pin_name.clone(), merged);
|
||||||
|
|||||||
@ -129,9 +129,17 @@ pub enum MirInstruction {
|
|||||||
// === SSA Phi Function ===
|
// === SSA Phi Function ===
|
||||||
/// SSA phi function for merging values from different paths
|
/// SSA phi function for merging values from different paths
|
||||||
/// `%dst = phi [%val1 from %bb1, %val2 from %bb2, ...]`
|
/// `%dst = phi [%val1 from %bb1, %val2 from %bb2, ...]`
|
||||||
|
///
|
||||||
|
/// # Phase 63-6: Type Hint Support
|
||||||
|
///
|
||||||
|
/// `type_hint` field stores type information from JoinIR (Select/IfMerge)
|
||||||
|
/// to enable type inference without scanning PHI inputs.
|
||||||
|
/// - `Some(MirType)`: Type is known from JoinIR (P1 cases: IfSelectTest.simple/local)
|
||||||
|
/// - `None`: Type must be inferred from PHI inputs (legacy behavior)
|
||||||
Phi {
|
Phi {
|
||||||
dst: ValueId,
|
dst: ValueId,
|
||||||
inputs: Vec<(super::BasicBlockId, ValueId)>,
|
inputs: Vec<(super::BasicBlockId, ValueId)>,
|
||||||
|
type_hint: Option<super::MirType>, // Phase 63-6: JoinIR type hint
|
||||||
},
|
},
|
||||||
|
|
||||||
// === Box Operations ===
|
// === Box Operations ===
|
||||||
|
|||||||
@ -541,7 +541,7 @@ inst_meta! {
|
|||||||
inst_meta! {
|
inst_meta! {
|
||||||
pub struct PhiInst { dst: ValueId, inputs: Vec<(BasicBlockId, ValueId)> }
|
pub struct PhiInst { dst: ValueId, inputs: Vec<(BasicBlockId, ValueId)> }
|
||||||
=> {
|
=> {
|
||||||
from_mir = |i| match i { MirInstruction::Phi { dst, inputs } => Some(PhiInst { dst: *dst, inputs: inputs.clone() }), _ => None };
|
from_mir = |i| match i { MirInstruction::Phi { dst, inputs, .. } => Some(PhiInst { dst: *dst, inputs: inputs.clone() }), _ => None };
|
||||||
effects = |_: &Self| EffectMask::PURE;
|
effects = |_: &Self| EffectMask::PURE;
|
||||||
dst = |s: &Self| Some(s.dst);
|
dst = |s: &Self| Some(s.dst);
|
||||||
used = |s: &Self| s.inputs.iter().map(|(_, v)| *v).collect();
|
used = |s: &Self| s.inputs.iter().map(|(_, v)| *v).collect();
|
||||||
|
|||||||
@ -94,7 +94,7 @@ pub(crate) fn intake_loop_form(
|
|||||||
let mut carrier_hint: Vec<String> = Vec::new();
|
let mut carrier_hint: Vec<String> = Vec::new();
|
||||||
|
|
||||||
for inst in query.insts_in_block(loop_form.header) {
|
for inst in query.insts_in_block(loop_form.header) {
|
||||||
if let MirInstruction::Phi { dst, inputs } = inst {
|
if let MirInstruction::Phi { dst, inputs, .. } = inst {
|
||||||
let name = inputs
|
let name = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(_, v)| value_to_name.get(v).cloned())
|
.find_map(|(_, v)| value_to_name.get(v).cloned())
|
||||||
|
|||||||
@ -491,17 +491,18 @@ Call {{\n\
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
type_hint: _, // Phase 63-3: MIR変換では現時点で未使用
|
type_hint, // Phase 63-6: Type hint propagated to MIR Phi
|
||||||
} => {
|
} => {
|
||||||
// Phase 33-2: Select を MIR の if/phi に変換
|
// Phase 33-2: Select を MIR の if/phi に変換
|
||||||
// 最小実装: cond/then/else/merge の 4 ブロック構造
|
// Phase 63-6: PHI instruction with type hint from JoinIR
|
||||||
|
|
||||||
debug_log!(
|
debug_log!(
|
||||||
"[joinir_vm_bridge] Converting Select: dst={:?}, cond={:?}, then={:?}, else={:?}",
|
"[joinir_vm_bridge] Converting Select: dst={:?}, cond={:?}, then={:?}, else={:?}, type_hint={:?}",
|
||||||
dst,
|
dst,
|
||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val
|
else_val,
|
||||||
|
type_hint
|
||||||
);
|
);
|
||||||
|
|
||||||
// 1. cond ブロック(現在のブロック)
|
// 1. cond ブロック(現在のブロック)
|
||||||
@ -532,32 +533,29 @@ Call {{\n\
|
|||||||
branch_terminator,
|
branch_terminator,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 6. then ブロック: dst = then_val; jump merge
|
// 6. then ブロック: jump merge (no Copy, PHI will handle it)
|
||||||
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
|
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
|
||||||
then_block_obj.instructions.push(MirInstruction::Copy {
|
|
||||||
dst: *dst,
|
|
||||||
src: *then_val,
|
|
||||||
});
|
|
||||||
then_block_obj.instruction_spans.push(Span::unknown());
|
|
||||||
then_block_obj.terminator = Some(MirInstruction::Jump {
|
then_block_obj.terminator = Some(MirInstruction::Jump {
|
||||||
target: merge_block,
|
target: merge_block,
|
||||||
});
|
});
|
||||||
mir_func.blocks.insert(then_block, then_block_obj);
|
mir_func.blocks.insert(then_block, then_block_obj);
|
||||||
|
|
||||||
// 7. else ブロック: dst = else_val; jump merge
|
// 7. else ブロック: jump merge (no Copy, PHI will handle it)
|
||||||
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
|
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
|
||||||
else_block_obj.instructions.push(MirInstruction::Copy {
|
|
||||||
dst: *dst,
|
|
||||||
src: *else_val,
|
|
||||||
});
|
|
||||||
else_block_obj.instruction_spans.push(Span::unknown());
|
|
||||||
else_block_obj.terminator = Some(MirInstruction::Jump {
|
else_block_obj.terminator = Some(MirInstruction::Jump {
|
||||||
target: merge_block,
|
target: merge_block,
|
||||||
});
|
});
|
||||||
mir_func.blocks.insert(else_block, else_block_obj);
|
mir_func.blocks.insert(else_block, else_block_obj);
|
||||||
|
|
||||||
// 8. merge ブロック作成(空)
|
// 8. merge ブロック: PHI instruction with type hint
|
||||||
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
|
let mut merge_block_obj = crate::mir::BasicBlock::new(merge_block);
|
||||||
|
// Phase 63-6: Create PHI with type hint from JoinIR Select
|
||||||
|
merge_block_obj.instructions.push(MirInstruction::Phi {
|
||||||
|
dst: *dst,
|
||||||
|
inputs: vec![(then_block, *then_val), (else_block, *else_val)],
|
||||||
|
type_hint: type_hint.clone(), // Phase 63-6: Propagate type hint from JoinIR
|
||||||
|
});
|
||||||
|
merge_block_obj.instruction_spans.push(Span::unknown());
|
||||||
mir_func.blocks.insert(merge_block, merge_block_obj);
|
mir_func.blocks.insert(merge_block, merge_block_obj);
|
||||||
|
|
||||||
// 9. merge ブロックに移動
|
// 9. merge ブロックに移動
|
||||||
|
|||||||
@ -395,6 +395,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
merge_block.add_instruction(MirInstruction::Phi {
|
merge_block.add_instruction(MirInstruction::Phi {
|
||||||
dst: phi_id,
|
dst: phi_id,
|
||||||
inputs: final_inputs,
|
inputs: final_inputs,
|
||||||
|
type_hint: None, // Phase 63-6
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
MirInstruction::Phi {
|
MirInstruction::Phi {
|
||||||
dst: d,
|
dst: d,
|
||||||
inputs: ins,
|
inputs: ins,
|
||||||
|
.. // Phase 63-6: Ignore type_hint in pattern matching
|
||||||
} if *d == dst => {
|
} if *d == dst => {
|
||||||
*ins = inputs.clone();
|
*ins = inputs.clone();
|
||||||
if block.instruction_spans.len() <= idx {
|
if block.instruction_spans.len() <= idx {
|
||||||
@ -58,6 +59,7 @@ impl<'a> LoopBuilder<'a> {
|
|||||||
let phi_inst = MirInstruction::Phi {
|
let phi_inst = MirInstruction::Phi {
|
||||||
dst,
|
dst,
|
||||||
inputs: inputs.clone(),
|
inputs: inputs.clone(),
|
||||||
|
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||||||
};
|
};
|
||||||
block.instructions.insert(0, phi_inst);
|
block.instructions.insert(0, phi_inst);
|
||||||
block.instruction_spans.insert(0, span);
|
block.instruction_spans.insert(0, span);
|
||||||
|
|||||||
@ -136,7 +136,8 @@ pub fn infer_type_from_phi(
|
|||||||
) -> Option<MirType> {
|
) -> Option<MirType> {
|
||||||
for (_bid, bb) in function.blocks.iter() {
|
for (_bid, bb) in function.blocks.iter() {
|
||||||
for inst in bb.instructions.iter() {
|
for inst in bb.instructions.iter() {
|
||||||
if let MirInstruction::Phi { dst, inputs } = inst {
|
if let MirInstruction::Phi { dst, inputs, .. } = inst {
|
||||||
|
// Phase 63-6: type_hint is ignored here, will be used in lifecycle.rs
|
||||||
if *dst == ret_val {
|
if *dst == ret_val {
|
||||||
let mut it = inputs.iter().filter_map(|(_, v)| types.get(v));
|
let mut it = inputs.iter().filter_map(|(_, v)| types.get(v));
|
||||||
if let Some(first) = it.next() {
|
if let Some(first) = it.next() {
|
||||||
|
|||||||
@ -248,7 +248,7 @@ pub fn format_instruction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MirInstruction::Phi { dst, inputs } => {
|
MirInstruction::Phi { dst, inputs, .. } => {
|
||||||
let inputs_str = inputs
|
let inputs_str = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(bb, val)| format!("[{}, {}]", val, bb))
|
.map(|(bb, val)| format!("[{}, {}]", val, bb))
|
||||||
|
|||||||
@ -72,7 +72,7 @@ pub fn insert_phi_at_head_spanned(
|
|||||||
inputs.sort_by_key(|(bb, _)| bb.0);
|
inputs.sort_by_key(|(bb, _)| bb.0);
|
||||||
if let Some(bb) = f.get_block_mut(bb_id) {
|
if let Some(bb) = f.get_block_mut(bb_id) {
|
||||||
bb.insert_spanned_after_phis(SpannedInstruction {
|
bb.insert_spanned_after_phis(SpannedInstruction {
|
||||||
inst: MirInstruction::Phi { dst, inputs },
|
inst: MirInstruction::Phi { dst, inputs, type_hint: None },
|
||||||
span,
|
span,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,7 @@ impl MirBuilder {
|
|||||||
self.emit_instruction(MirInstruction::Phi {
|
self.emit_instruction(MirInstruction::Phi {
|
||||||
dst: phi_val,
|
dst: phi_val,
|
||||||
inputs,
|
inputs,
|
||||||
|
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +147,11 @@ impl MirBuilder {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// フォールバック: 直接emit(主にテストや特殊ケース用)
|
// フォールバック: 直接emit(主にテストや特殊ケース用)
|
||||||
self.emit_instruction(MirInstruction::Phi { dst, inputs })?;
|
self.emit_instruction(MirInstruction::Phi {
|
||||||
|
dst,
|
||||||
|
inputs,
|
||||||
|
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -163,6 +163,7 @@ impl LoopFormOps for LoopFormJsonOps<'_> {
|
|||||||
if let MirInstruction::Phi {
|
if let MirInstruction::Phi {
|
||||||
dst,
|
dst,
|
||||||
inputs: phi_inputs,
|
inputs: phi_inputs,
|
||||||
|
.. // Phase 63-6: Ignore type_hint
|
||||||
} = inst
|
} = inst
|
||||||
{
|
{
|
||||||
if *dst == phi_id {
|
if *dst == phi_id {
|
||||||
|
|||||||
@ -273,6 +273,7 @@ pub fn try_parse_v1_to_module(json: &str) -> Result<Option<MirModule>, String> {
|
|||||||
block_ref.add_instruction(MirInstruction::Phi {
|
block_ref.add_instruction(MirInstruction::Phi {
|
||||||
dst: ValueId::new(dst),
|
dst: ValueId::new(dst),
|
||||||
inputs: pairs,
|
inputs: pairs,
|
||||||
|
type_hint: None, // Phase 63-6
|
||||||
});
|
});
|
||||||
max_value_id = max_value_id.max(dst + 1);
|
max_value_id = max_value_id.max(dst + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -227,7 +227,7 @@ pub fn emit_mir_json_for_harness(
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let I::Phi { dst, inputs } = inst {
|
if let I::Phi { dst, inputs, .. } = inst {
|
||||||
let incoming: Vec<_> = inputs
|
let incoming: Vec<_> = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(b, v)| json!([v.as_u32(), b.as_u32()]))
|
.map(|(b, v)| json!([v.as_u32(), b.as_u32()]))
|
||||||
@ -642,7 +642,7 @@ pub fn emit_mir_json_for_harness_bin(
|
|||||||
let mut emitted_defs: std::collections::HashSet<u32> =
|
let mut emitted_defs: std::collections::HashSet<u32> =
|
||||||
std::collections::HashSet::new();
|
std::collections::HashSet::new();
|
||||||
for inst in &bb.instructions {
|
for inst in &bb.instructions {
|
||||||
if let I::Phi { dst, inputs } = inst {
|
if let I::Phi { dst, inputs, .. } = inst {
|
||||||
let incoming: Vec<_> = inputs
|
let incoming: Vec<_> = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(b, v)| json!([v.as_u32(), b.as_u32()]))
|
.map(|(b, v)| json!([v.as_u32(), b.as_u32()]))
|
||||||
|
|||||||
@ -179,6 +179,7 @@ pub fn parse_mir_v0_to_module(json: &str) -> Result<MirModule, String> {
|
|||||||
block_ref.add_instruction(MirInstruction::Phi {
|
block_ref.add_instruction(MirInstruction::Phi {
|
||||||
dst: ValueId::new(dst),
|
dst: ValueId::new(dst),
|
||||||
inputs: pairs,
|
inputs: pairs,
|
||||||
|
type_hint: None, // Phase 63-6
|
||||||
});
|
});
|
||||||
max_value_id = max_value_id.max(dst + 1);
|
max_value_id = max_value_id.max(dst + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user