Improve LLVM IR SSA names

This commit is contained in:
Sofia 2025-07-20 20:49:26 +03:00
parent 71a01dad69
commit 33d5ee03f0
6 changed files with 139 additions and 74 deletions

View File

@ -18,9 +18,9 @@ fn main() {
FunctionFlags::default(), FunctionFlags::default(),
); );
let arg = m_entry.build(Constant(I32(5))).unwrap(); let arg = m_entry.build("const", Constant(I32(5))).unwrap();
let fibonacci_call = m_entry let fibonacci_call = m_entry
.build(FunctionCall(fibonacci.value(), vec![arg])) .build("const", FunctionCall(fibonacci.value(), vec![arg]))
.unwrap(); .unwrap();
m_entry m_entry
.terminate(TerminatorKind::Ret(fibonacci_call)) .terminate(TerminatorKind::Ret(fibonacci_call))
@ -28,10 +28,10 @@ fn main() {
let mut f_entry = fibonacci.block("entry"); let mut f_entry = fibonacci.block("entry");
let num_3 = f_entry.build(Constant(I32(3))).unwrap(); let num_3 = f_entry.build("const", Constant(I32(3))).unwrap();
let param_n = f_entry.build(Param(0)).unwrap(); let param_n = f_entry.build("param", Param(0)).unwrap();
let cond = f_entry let cond = f_entry
.build(ICmp(CmpPredicate::LT, param_n, num_3)) .build("cmp", ICmp(CmpPredicate::LT, param_n, num_3))
.unwrap(); .unwrap();
let mut then_b = fibonacci.block("then"); let mut then_b = fibonacci.block("then");
@ -41,21 +41,21 @@ fn main() {
.terminate(TerminatorKind::CondBr(cond, then_b.value(), else_b.value())) .terminate(TerminatorKind::CondBr(cond, then_b.value(), else_b.value()))
.unwrap(); .unwrap();
let ret_const = then_b.build(Constant(I32(1))).unwrap(); let ret_const = then_b.build("const", Constant(I32(1))).unwrap();
then_b.terminate(TerminatorKind::Ret(ret_const)).unwrap(); then_b.terminate(TerminatorKind::Ret(ret_const)).unwrap();
let const_1 = else_b.build(Constant(I32(1))).unwrap(); let const_1 = else_b.build("const", Constant(I32(1))).unwrap();
let const_2 = else_b.build(Constant(I32(2))).unwrap(); let const_2 = else_b.build("const", Constant(I32(2))).unwrap();
let param_1 = else_b.build(Sub(param_n, const_1)).unwrap(); let param_1 = else_b.build("sub", Sub(param_n, const_1)).unwrap();
let param_2 = else_b.build(Sub(param_n, const_2)).unwrap(); let param_2 = else_b.build("sub", Sub(param_n, const_2)).unwrap();
let call_1 = else_b let call_1 = else_b
.build(FunctionCall(fibonacci.value(), vec![param_1])) .build("fibonacci", FunctionCall(fibonacci.value(), vec![param_1]))
.unwrap(); .unwrap();
let call_2 = else_b let call_2 = else_b
.build(FunctionCall(fibonacci.value(), vec![param_2])) .build("fibonacci", FunctionCall(fibonacci.value(), vec![param_2]))
.unwrap(); .unwrap();
let add = else_b.build(Add(call_1, call_2)).unwrap(); let add = else_b.build("add", Add(call_1, call_2)).unwrap();
else_b.terminate(TerminatorKind::Ret(add)).unwrap(); else_b.terminate(TerminatorKind::Ret(add)).unwrap();

View File

@ -61,6 +61,7 @@ pub struct BlockHolder {
pub struct InstructionHolder { pub struct InstructionHolder {
pub(crate) value: InstructionValue, pub(crate) value: InstructionValue,
pub(crate) data: InstructionData, pub(crate) data: InstructionData,
pub(crate) name: String,
pub(crate) record: Option<InstructionDebugRecordData>, pub(crate) record: Option<InstructionDebugRecordData>,
} }
@ -149,6 +150,7 @@ impl Builder {
&self, &self,
block_val: &BlockValue, block_val: &BlockValue,
data: InstructionData, data: InstructionData,
name: String,
) -> Result<InstructionValue, ()> { ) -> Result<InstructionValue, ()> {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
@ -159,6 +161,7 @@ impl Builder {
block.instructions.push(InstructionHolder { block.instructions.push(InstructionHolder {
value, value,
data, data,
name,
record: None, record: None,
}); });

View File

@ -743,6 +743,7 @@ impl InstructionHolder {
_block: LLVMBasicBlockRef, _block: LLVMBasicBlockRef,
) -> LLVMValue { ) -> LLVMValue {
let _ty = self.value.get_type(module.builder).unwrap(); let _ty = self.value.get_type(module.builder).unwrap();
let name = into_cstring(self.name.clone());
let val = unsafe { let val = unsafe {
use super::Instr::*; use super::Instr::*;
match &self.data.kind { match &self.data.kind {
@ -751,22 +752,22 @@ impl InstructionHolder {
Add(lhs, rhs) => { Add(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref; let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref; let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildAdd(module.builder_ref, lhs_val, rhs_val, c"add".as_ptr()) LLVMBuildAdd(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
} }
Sub(lhs, rhs) => { Sub(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref; let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref; let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildSub(module.builder_ref, lhs_val, rhs_val, c"sub".as_ptr()) LLVMBuildSub(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
} }
Mult(lhs, rhs) => { Mult(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref; let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref; let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildMul(module.builder_ref, lhs_val, rhs_val, c"mul".as_ptr()) LLVMBuildMul(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
} }
And(lhs, rhs) => { And(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref; let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref; let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildAnd(module.builder_ref, lhs_val, rhs_val, c"and".as_ptr()) LLVMBuildAnd(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
} }
ICmp(pred, lhs, rhs) => { ICmp(pred, lhs, rhs) => {
let lhs = module.values.get(&lhs).unwrap(); let lhs = module.values.get(&lhs).unwrap();
@ -777,7 +778,7 @@ impl InstructionHolder {
pred.as_llvm_int(lhs._ty.signed()), pred.as_llvm_int(lhs._ty.signed()),
lhs.value_ref, lhs.value_ref,
rhs_val, rhs_val,
c"icmp".as_ptr(), name.as_ptr(),
) )
} }
FunctionCall(function_value, instruction_values) => { FunctionCall(function_value, instruction_values) => {
@ -797,7 +798,7 @@ impl InstructionHolder {
fun.value_ref, fun.value_ref,
param_list.as_mut_ptr(), param_list.as_mut_ptr(),
param_list.len() as u32, param_list.len() as u32,
c"call".as_ptr(), name.as_ptr(),
); );
if is_void { if is_void {
LLVMContextSetDiscardValueNames(module.context_ref, 0); LLVMContextSetDiscardValueNames(module.context_ref, 0);
@ -814,7 +815,7 @@ impl InstructionHolder {
let phi = LLVMBuildPhi( let phi = LLVMBuildPhi(
module.builder_ref, module.builder_ref,
_ty.as_llvm(module.context_ref, &module.types), _ty.as_llvm(module.context_ref, &module.types),
c"phi".as_ptr(), name.as_ptr(),
); );
LLVMAddIncoming( LLVMAddIncoming(
phi, phi,
@ -827,13 +828,13 @@ impl InstructionHolder {
Alloca(ty) => LLVMBuildAlloca( Alloca(ty) => LLVMBuildAlloca(
module.builder_ref, module.builder_ref,
ty.as_llvm(module.context_ref, &module.types), ty.as_llvm(module.context_ref, &module.types),
c"alloca".as_ptr(), name.as_ptr(),
), ),
Load(ptr, ty) => LLVMBuildLoad2( Load(ptr, ty) => LLVMBuildLoad2(
module.builder_ref, module.builder_ref,
ty.as_llvm(module.context_ref, &module.types), ty.as_llvm(module.context_ref, &module.types),
module.values.get(&ptr).unwrap().value_ref, module.values.get(&ptr).unwrap().value_ref,
c"load".as_ptr(), name.as_ptr(),
), ),
Store(ptr, val) => { Store(ptr, val) => {
let store = LLVMBuildStore( let store = LLVMBuildStore(
@ -849,7 +850,7 @@ impl InstructionHolder {
module.builder_ref, module.builder_ref,
ty.as_llvm(module.context_ref, &module.types), ty.as_llvm(module.context_ref, &module.types),
array_len, array_len,
c"array_alloca".as_ptr(), name.as_ptr(),
) )
} }
GetElemPtr(arr, indices) => { GetElemPtr(arr, indices) => {
@ -867,32 +868,26 @@ impl InstructionHolder {
module.values.get(arr).unwrap().value_ref, module.values.get(arr).unwrap().value_ref,
llvm_indices.as_mut_ptr(), llvm_indices.as_mut_ptr(),
llvm_indices.len() as u32, llvm_indices.len() as u32,
into_cstring(format!("array_gep")).as_ptr(), name.as_ptr(),
) )
} }
GetStructElemPtr(struct_val, idx) => { GetStructElemPtr(struct_val, idx) => {
let t = struct_val.get_type(module.builder).unwrap(); let t = struct_val.get_type(module.builder).unwrap();
let Type::Ptr(struct_t) = t else { panic!() }; let Type::Ptr(struct_t) = t else { panic!() };
let type_fmt = if let Type::CustomType(type_val) = *struct_t {
format!("M{}T{}", type_val.0.0, type_val.1)
} else {
format!("{:?}", struct_t)
};
LLVMBuildStructGEP2( LLVMBuildStructGEP2(
module.builder_ref, module.builder_ref,
struct_t.as_llvm(module.context_ref, &module.types), struct_t.as_llvm(module.context_ref, &module.types),
module.values.get(struct_val).unwrap().value_ref, module.values.get(struct_val).unwrap().value_ref,
*idx, *idx,
into_cstring(format!("struct.{}.{}.gep", type_fmt, idx)).as_ptr(), name.as_ptr(),
) )
} }
ExtractValue(agg_val, idx) => LLVMBuildExtractValue( ExtractValue(agg_val, idx) => LLVMBuildExtractValue(
module.builder_ref, module.builder_ref,
module.values.get(agg_val).unwrap().value_ref, module.values.get(agg_val).unwrap().value_ref,
*idx, *idx,
c"extract".as_ptr(), name.as_ptr(),
), ),
} }
}; };

View File

@ -71,6 +71,7 @@ impl Debug for BlockHolder {
impl Debug for InstructionHolder { impl Debug for InstructionHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.value.fmt(f)?; self.value.fmt(f)?;
write!(f, " ({})", self.name)?;
f.write_str(" = ")?; f.write_str(" = ")?;
self.data.fmt(f) self.data.fmt(f)
} }

View File

@ -204,7 +204,11 @@ pub struct Block<'builder> {
} }
impl<'builder> Block<'builder> { impl<'builder> Block<'builder> {
pub fn build(&mut self, instruction: Instr) -> Result<InstructionValue, ()> { pub fn build<T: Into<String>>(
&mut self,
name: T,
instruction: Instr,
) -> Result<InstructionValue, ()> {
unsafe { unsafe {
self.builder.add_instruction( self.builder.add_instruction(
&self.value, &self.value,
@ -213,6 +217,7 @@ impl<'builder> Block<'builder> {
location: None, location: None,
meta: None, meta: None,
}, },
name.into(),
) )
} }
} }

View File

@ -343,11 +343,19 @@ impl mir::Module {
let mut stack_values = HashMap::new(); let mut stack_values = HashMap::new();
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() { for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
// Codegen actual parameters // Codegen actual parameters
let param = entry.build(Instr::Param(i)).unwrap(); let arg_name = format!("arg.{}", p_name);
let alloca = entry let param = entry
.build(Instr::Alloca(p_ty.get_type(&type_values, &types))) .build(format!("{}.get", arg_name), Instr::Param(i))
.unwrap();
let alloca = entry
.build(
&arg_name,
Instr::Alloca(p_ty.get_type(&type_values, &types)),
)
.unwrap();
entry
.build(format!("{}.store", arg_name), Instr::Store(alloca, param))
.unwrap(); .unwrap();
entry.build(Instr::Store(alloca, param)).unwrap();
stack_values.insert( stack_values.insert(
p_name.clone(), p_name.clone(),
StackValue( StackValue(
@ -470,15 +478,22 @@ impl mir::Statement {
mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => { mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => {
let value = expression.codegen(scope, &state).unwrap(); let value = expression.codegen(scope, &state).unwrap();
dbg!(&name);
let alloca = scope let alloca = scope
.block .block
.build(Instr::Alloca(ty.get_type(scope.type_values, scope.types))) .build(
name,
Instr::Alloca(ty.get_type(scope.type_values, scope.types)),
)
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
let store = scope let store = scope
.block .block
.build(Instr::Store(alloca, value.instr())) .build(
format!("{}.store", name),
Instr::Store(alloca, value.instr()),
)
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
@ -522,6 +537,12 @@ impl mir::Statement {
let rhs_value = rhs.codegen(scope, state)?; let rhs_value = rhs.codegen(scope, state)?;
let backing_var = if let Some(var) = lhs.backing_var() {
&format!("store.{}", var.1)
} else {
"store"
};
match lhs_value.0 { match lhs_value.0 {
StackValueKind::Immutable(_) => { StackValueKind::Immutable(_) => {
panic!("Tried to assign to immutable!") panic!("Tried to assign to immutable!")
@ -529,7 +550,7 @@ impl mir::Statement {
StackValueKind::Mutable(instr) => { StackValueKind::Mutable(instr) => {
scope scope
.block .block
.build(Instr::Store(instr, rhs_value.instr())) .build(backing_var, Instr::Store(instr, rhs_value.instr()))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
} }
@ -572,10 +593,13 @@ impl mir::Expression {
v.0.derive( v.0.derive(
scope scope
.block .block
.build(Instr::Load( .build(
v.0.instr(), format!("{}", varref.1),
inner.get_type(scope.type_values, scope.types), Instr::Load(
)) v.0.instr(),
inner.get_type(scope.type_values, scope.types),
),
)
.unwrap(), .unwrap(),
), ),
*inner.clone(), *inner.clone(),
@ -604,20 +628,20 @@ impl mir::Expression {
Some(StackValue( Some(StackValue(
StackValueKind::Immutable(match binop { StackValueKind::Immutable(match binop {
mir::BinaryOperator::Add => { mir::BinaryOperator::Add => {
scope.block.build(Instr::Add(lhs, rhs)).unwrap() scope.block.build("add", Instr::Add(lhs, rhs)).unwrap()
} }
mir::BinaryOperator::Minus => { mir::BinaryOperator::Minus => {
scope.block.build(Instr::Sub(lhs, rhs)).unwrap() scope.block.build("sub", Instr::Sub(lhs, rhs)).unwrap()
} }
mir::BinaryOperator::Mult => { mir::BinaryOperator::Mult => {
scope.block.build(Instr::Mult(lhs, rhs)).unwrap() scope.block.build("mul", Instr::Mult(lhs, rhs)).unwrap()
} }
mir::BinaryOperator::And => { mir::BinaryOperator::And => {
scope.block.build(Instr::And(lhs, rhs)).unwrap() scope.block.build("and", Instr::And(lhs, rhs)).unwrap()
} }
mir::BinaryOperator::Cmp(l) => scope mir::BinaryOperator::Cmp(l) => scope
.block .block
.build(Instr::ICmp(l.int_predicate(), lhs, rhs)) .build("cmp", Instr::ICmp(l.int_predicate(), lhs, rhs))
.unwrap(), .unwrap(),
}), }),
TypeKind::U32, TypeKind::U32,
@ -643,7 +667,10 @@ impl mir::Expression {
StackValueKind::Immutable( StackValueKind::Immutable(
scope scope
.block .block
.build(Instr::FunctionCall(callee.ir.value(), params)) .build(
call.name.clone(),
Instr::FunctionCall(callee.ir.value(), params),
)
.unwrap(), .unwrap(),
), ),
ret_type, ret_type,
@ -673,12 +700,15 @@ impl mir::Expression {
let first = scope let first = scope
.block .block
.build(Instr::Constant(ConstValue::U32(0))) .build("array.zero", Instr::Constant(ConstValue::U32(0)))
.unwrap(); .unwrap();
let ptr = scope let ptr = scope
.block .block
.build(Instr::GetElemPtr(kind.instr(), vec![first, idx])) .build(
format!("array.gep"),
Instr::GetElemPtr(kind.instr(), vec![first, idx]),
)
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
@ -694,10 +724,13 @@ impl mir::Expression {
kind.derive( kind.derive(
scope scope
.block .block
.build(Instr::Load( .build(
ptr, "array.load",
val_t.get_type(scope.type_values, scope.types), Instr::Load(
)) ptr,
val_t.get_type(scope.type_values, scope.types),
),
)
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location), .maybe_location(&mut scope.block, location),
), ),
@ -727,37 +760,45 @@ impl mir::Expression {
Box::new(elem_ty_kind.get_type(scope.type_values, scope.types)), Box::new(elem_ty_kind.get_type(scope.type_values, scope.types)),
instr_list.len() as u64, instr_list.len() as u64,
); );
let array_name = format!("{}.{}", elem_ty_kind, instr_list.len());
let load_n = format!("{}.load", array_name);
let array = scope let array = scope
.block .block
.build(Instr::Alloca(array_ty.clone())) .build(&array_name, Instr::Alloca(array_ty.clone()))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
for (index, instr) in instr_list.iter().enumerate() { for (index, instr) in instr_list.iter().enumerate() {
let gep_n = format!("{}.{}.gep", array_name, index);
let store_n = format!("{}.{}.store", array_name, index);
let index_expr = scope let index_expr = scope
.block .block
.build(Instr::Constant(ConstValue::U32(index as u32))) .build(
index.to_string(),
Instr::Constant(ConstValue::U32(index as u32)),
)
.unwrap(); .unwrap();
let first = scope let first = scope
.block .block
.build(Instr::Constant(ConstValue::U32(0))) .build("zero", Instr::Constant(ConstValue::U32(0)))
.unwrap(); .unwrap();
let ptr = scope let ptr = scope
.block .block
.build(Instr::GetElemPtr(array, vec![first, index_expr])) .build(gep_n, Instr::GetElemPtr(array, vec![first, index_expr]))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
scope scope
.block .block
.build(Instr::Store(ptr, *instr)) .build(store_n, Instr::Store(ptr, *instr))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
} }
let array_val = scope let array_val = scope
.block .block
.build(Instr::Load(array, array_ty)) .build(load_n, Instr::Load(array, array_ty))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
@ -779,9 +820,15 @@ impl mir::Expression {
scope.get_typedef(&name).unwrap().kind.clone(); scope.get_typedef(&name).unwrap().kind.clone();
let idx = struct_ty.find_index(field).unwrap(); let idx = struct_ty.find_index(field).unwrap();
let gep_n = format!("{}.{}.gep", name, field);
let load_n = format!("{}.{}.load", name, field);
let value = scope let value = scope
.block .block
.build(Instr::GetStructElemPtr(struct_val.instr(), idx as u32)) .build(
gep_n,
Instr::GetStructElemPtr(struct_val.instr(), idx as u32),
)
.unwrap(); .unwrap();
// value.maybe_location(&mut scope.block, location); // value.maybe_location(&mut scope.block, location);
@ -791,10 +838,13 @@ impl mir::Expression {
struct_val.0.derive( struct_val.0.derive(
scope scope
.block .block
.build(Instr::Load( .build(
value, load_n,
type_kind.get_type(scope.type_values, scope.types), Instr::Load(
)) value,
type_kind.get_type(scope.type_values, scope.types),
),
)
.unwrap(), .unwrap(),
), ),
struct_ty.get_field_ty(&field).unwrap().clone(), struct_ty.get_field_ty(&field).unwrap().clone(),
@ -808,22 +858,28 @@ impl mir::Expression {
} }
mir::ExprKind::Struct(name, items) => { mir::ExprKind::Struct(name, items) => {
let struct_ty = Type::CustomType(*scope.type_values.get(name)?); let struct_ty = Type::CustomType(*scope.type_values.get(name)?);
let load_n = format!("{}.load", name);
let struct_ptr = scope let struct_ptr = scope
.block .block
.build(Instr::Alloca(struct_ty.clone())) .build(name, Instr::Alloca(struct_ty.clone()))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
for (i, (_, exp)) in items.iter().enumerate() { for (i, (field_n, exp)) in items.iter().enumerate() {
let gep_n = format!("{}.{}.gep", name, field_n);
let store_n = format!("{}.{}.store", name, field_n);
let elem_ptr = scope let elem_ptr = scope
.block .block
.build(Instr::GetStructElemPtr(struct_ptr, i as u32)) .build(gep_n, Instr::GetStructElemPtr(struct_ptr, i as u32))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
if let Some(val) = exp.codegen(scope, state) { if let Some(val) = exp.codegen(scope, state) {
scope scope
.block .block
.build(Instr::Store(elem_ptr, val.instr())) .build(store_n, Instr::Store(elem_ptr, val.instr()))
.unwrap() .unwrap()
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
} }
@ -831,7 +887,7 @@ impl mir::Expression {
let struct_val = scope let struct_val = scope
.block .block
.build(Instr::Load(struct_ptr, struct_ty)) .build(load_n, Instr::Load(struct_ptr, struct_ty))
.unwrap(); .unwrap();
Some(StackValue( Some(StackValue(
@ -919,7 +975,10 @@ impl mir::IfExpression {
incoming.extend(else_res.clone()); incoming.extend(else_res.clone());
let instr = scope let instr = scope
.block .block
.build(Instr::Phi(incoming.iter().map(|i| i.instr()).collect())) .build(
"phi",
Instr::Phi(incoming.iter().map(|i| i.instr()).collect()),
)
.unwrap(); .unwrap();
use StackValueKind::*; use StackValueKind::*;
@ -957,7 +1016,9 @@ impl mir::CmpOperator {
impl mir::Literal { impl mir::Literal {
fn as_const(&self, block: &mut Block) -> InstructionValue { fn as_const(&self, block: &mut Block) -> InstructionValue {
block.build(self.as_const_kind()).unwrap() block
.build(format!("{}", self), self.as_const_kind())
.unwrap()
} }
fn as_const_kind(&self) -> Instr { fn as_const_kind(&self) -> Instr {