From 33d5ee03f09c7fffff62359de7d324b84991f275 Mon Sep 17 00:00:00 2001 From: sofia Date: Sun, 20 Jul 2025 20:49:26 +0300 Subject: [PATCH] Improve LLVM IR SSA names --- reid-llvm-lib/examples/libtest.rs | 26 +++--- reid-llvm-lib/src/builder.rs | 3 + reid-llvm-lib/src/compile.rs | 33 +++---- reid-llvm-lib/src/debug.rs | 1 + reid-llvm-lib/src/lib.rs | 7 +- reid/src/codegen.rs | 143 +++++++++++++++++++++--------- 6 files changed, 139 insertions(+), 74 deletions(-) diff --git a/reid-llvm-lib/examples/libtest.rs b/reid-llvm-lib/examples/libtest.rs index 0903a8f..223d490 100644 --- a/reid-llvm-lib/examples/libtest.rs +++ b/reid-llvm-lib/examples/libtest.rs @@ -18,9 +18,9 @@ fn main() { 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 - .build(FunctionCall(fibonacci.value(), vec![arg])) + .build("const", FunctionCall(fibonacci.value(), vec![arg])) .unwrap(); m_entry .terminate(TerminatorKind::Ret(fibonacci_call)) @@ -28,10 +28,10 @@ fn main() { let mut f_entry = fibonacci.block("entry"); - let num_3 = f_entry.build(Constant(I32(3))).unwrap(); - let param_n = f_entry.build(Param(0)).unwrap(); + let num_3 = f_entry.build("const", Constant(I32(3))).unwrap(); + let param_n = f_entry.build("param", Param(0)).unwrap(); let cond = f_entry - .build(ICmp(CmpPredicate::LT, param_n, num_3)) + .build("cmp", ICmp(CmpPredicate::LT, param_n, num_3)) .unwrap(); let mut then_b = fibonacci.block("then"); @@ -41,21 +41,21 @@ fn main() { .terminate(TerminatorKind::CondBr(cond, then_b.value(), else_b.value())) .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(); - let const_1 = else_b.build(Constant(I32(1))).unwrap(); - let const_2 = else_b.build(Constant(I32(2))).unwrap(); - let param_1 = else_b.build(Sub(param_n, const_1)).unwrap(); - let param_2 = else_b.build(Sub(param_n, const_2)).unwrap(); + let const_1 = else_b.build("const", Constant(I32(1))).unwrap(); + let const_2 = else_b.build("const", Constant(I32(2))).unwrap(); + let param_1 = else_b.build("sub", Sub(param_n, const_1)).unwrap(); + let param_2 = else_b.build("sub", Sub(param_n, const_2)).unwrap(); let call_1 = else_b - .build(FunctionCall(fibonacci.value(), vec![param_1])) + .build("fibonacci", FunctionCall(fibonacci.value(), vec![param_1])) .unwrap(); let call_2 = else_b - .build(FunctionCall(fibonacci.value(), vec![param_2])) + .build("fibonacci", FunctionCall(fibonacci.value(), vec![param_2])) .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(); diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index eb9f24e..14c0cbd 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -61,6 +61,7 @@ pub struct BlockHolder { pub struct InstructionHolder { pub(crate) value: InstructionValue, pub(crate) data: InstructionData, + pub(crate) name: String, pub(crate) record: Option, } @@ -149,6 +150,7 @@ impl Builder { &self, block_val: &BlockValue, data: InstructionData, + name: String, ) -> Result { unsafe { let mut modules = self.modules.borrow_mut(); @@ -159,6 +161,7 @@ impl Builder { block.instructions.push(InstructionHolder { value, data, + name, record: None, }); diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index e860d21..7d1ef92 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -743,6 +743,7 @@ impl InstructionHolder { _block: LLVMBasicBlockRef, ) -> LLVMValue { let _ty = self.value.get_type(module.builder).unwrap(); + let name = into_cstring(self.name.clone()); let val = unsafe { use super::Instr::*; match &self.data.kind { @@ -751,22 +752,22 @@ impl InstructionHolder { Add(lhs, rhs) => { let lhs_val = module.values.get(&lhs).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) => { let lhs_val = module.values.get(&lhs).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) => { let lhs_val = module.values.get(&lhs).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) => { let lhs_val = module.values.get(&lhs).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) => { let lhs = module.values.get(&lhs).unwrap(); @@ -777,7 +778,7 @@ impl InstructionHolder { pred.as_llvm_int(lhs._ty.signed()), lhs.value_ref, rhs_val, - c"icmp".as_ptr(), + name.as_ptr(), ) } FunctionCall(function_value, instruction_values) => { @@ -797,7 +798,7 @@ impl InstructionHolder { fun.value_ref, param_list.as_mut_ptr(), param_list.len() as u32, - c"call".as_ptr(), + name.as_ptr(), ); if is_void { LLVMContextSetDiscardValueNames(module.context_ref, 0); @@ -814,7 +815,7 @@ impl InstructionHolder { let phi = LLVMBuildPhi( module.builder_ref, _ty.as_llvm(module.context_ref, &module.types), - c"phi".as_ptr(), + name.as_ptr(), ); LLVMAddIncoming( phi, @@ -827,13 +828,13 @@ impl InstructionHolder { Alloca(ty) => LLVMBuildAlloca( module.builder_ref, ty.as_llvm(module.context_ref, &module.types), - c"alloca".as_ptr(), + name.as_ptr(), ), Load(ptr, ty) => LLVMBuildLoad2( module.builder_ref, ty.as_llvm(module.context_ref, &module.types), module.values.get(&ptr).unwrap().value_ref, - c"load".as_ptr(), + name.as_ptr(), ), Store(ptr, val) => { let store = LLVMBuildStore( @@ -849,7 +850,7 @@ impl InstructionHolder { module.builder_ref, ty.as_llvm(module.context_ref, &module.types), array_len, - c"array_alloca".as_ptr(), + name.as_ptr(), ) } GetElemPtr(arr, indices) => { @@ -867,32 +868,26 @@ impl InstructionHolder { module.values.get(arr).unwrap().value_ref, llvm_indices.as_mut_ptr(), llvm_indices.len() as u32, - into_cstring(format!("array_gep")).as_ptr(), + name.as_ptr(), ) } GetStructElemPtr(struct_val, idx) => { let t = struct_val.get_type(module.builder).unwrap(); 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( module.builder_ref, struct_t.as_llvm(module.context_ref, &module.types), module.values.get(struct_val).unwrap().value_ref, *idx, - into_cstring(format!("struct.{}.{}.gep", type_fmt, idx)).as_ptr(), + name.as_ptr(), ) } ExtractValue(agg_val, idx) => LLVMBuildExtractValue( module.builder_ref, module.values.get(agg_val).unwrap().value_ref, *idx, - c"extract".as_ptr(), + name.as_ptr(), ), } }; diff --git a/reid-llvm-lib/src/debug.rs b/reid-llvm-lib/src/debug.rs index 092dcf0..f6dd478 100644 --- a/reid-llvm-lib/src/debug.rs +++ b/reid-llvm-lib/src/debug.rs @@ -71,6 +71,7 @@ impl Debug for BlockHolder { impl Debug for InstructionHolder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.value.fmt(f)?; + write!(f, " ({})", self.name)?; f.write_str(" = ")?; self.data.fmt(f) } diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index edfe2df..03140a5 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -204,7 +204,11 @@ pub struct Block<'builder> { } impl<'builder> Block<'builder> { - pub fn build(&mut self, instruction: Instr) -> Result { + pub fn build>( + &mut self, + name: T, + instruction: Instr, + ) -> Result { unsafe { self.builder.add_instruction( &self.value, @@ -213,6 +217,7 @@ impl<'builder> Block<'builder> { location: None, meta: None, }, + name.into(), ) } } diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index d1be997..836a9d9 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -343,11 +343,19 @@ impl mir::Module { let mut stack_values = HashMap::new(); for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() { // Codegen actual parameters - let param = entry.build(Instr::Param(i)).unwrap(); - let alloca = entry - .build(Instr::Alloca(p_ty.get_type(&type_values, &types))) + let arg_name = format!("arg.{}", p_name); + let param = entry + .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(); - entry.build(Instr::Store(alloca, param)).unwrap(); stack_values.insert( p_name.clone(), StackValue( @@ -470,15 +478,22 @@ impl mir::Statement { mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => { let value = expression.codegen(scope, &state).unwrap(); + dbg!(&name); let alloca = scope .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() .maybe_location(&mut scope.block, location); let store = scope .block - .build(Instr::Store(alloca, value.instr())) + .build( + format!("{}.store", name), + Instr::Store(alloca, value.instr()), + ) .unwrap() .maybe_location(&mut scope.block, location); @@ -522,6 +537,12 @@ impl mir::Statement { 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 { StackValueKind::Immutable(_) => { panic!("Tried to assign to immutable!") @@ -529,7 +550,7 @@ impl mir::Statement { StackValueKind::Mutable(instr) => { scope .block - .build(Instr::Store(instr, rhs_value.instr())) + .build(backing_var, Instr::Store(instr, rhs_value.instr())) .unwrap() .maybe_location(&mut scope.block, location); } @@ -572,10 +593,13 @@ impl mir::Expression { v.0.derive( scope .block - .build(Instr::Load( - v.0.instr(), - inner.get_type(scope.type_values, scope.types), - )) + .build( + format!("{}", varref.1), + Instr::Load( + v.0.instr(), + inner.get_type(scope.type_values, scope.types), + ), + ) .unwrap(), ), *inner.clone(), @@ -604,20 +628,20 @@ impl mir::Expression { Some(StackValue( StackValueKind::Immutable(match binop { mir::BinaryOperator::Add => { - scope.block.build(Instr::Add(lhs, rhs)).unwrap() + scope.block.build("add", Instr::Add(lhs, rhs)).unwrap() } mir::BinaryOperator::Minus => { - scope.block.build(Instr::Sub(lhs, rhs)).unwrap() + scope.block.build("sub", Instr::Sub(lhs, rhs)).unwrap() } mir::BinaryOperator::Mult => { - scope.block.build(Instr::Mult(lhs, rhs)).unwrap() + scope.block.build("mul", Instr::Mult(lhs, rhs)).unwrap() } 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 .block - .build(Instr::ICmp(l.int_predicate(), lhs, rhs)) + .build("cmp", Instr::ICmp(l.int_predicate(), lhs, rhs)) .unwrap(), }), TypeKind::U32, @@ -643,7 +667,10 @@ impl mir::Expression { StackValueKind::Immutable( scope .block - .build(Instr::FunctionCall(callee.ir.value(), params)) + .build( + call.name.clone(), + Instr::FunctionCall(callee.ir.value(), params), + ) .unwrap(), ), ret_type, @@ -673,12 +700,15 @@ impl mir::Expression { let first = scope .block - .build(Instr::Constant(ConstValue::U32(0))) + .build("array.zero", Instr::Constant(ConstValue::U32(0))) .unwrap(); let ptr = scope .block - .build(Instr::GetElemPtr(kind.instr(), vec![first, idx])) + .build( + format!("array.gep"), + Instr::GetElemPtr(kind.instr(), vec![first, idx]), + ) .unwrap() .maybe_location(&mut scope.block, location); @@ -694,10 +724,13 @@ impl mir::Expression { kind.derive( scope .block - .build(Instr::Load( - ptr, - val_t.get_type(scope.type_values, scope.types), - )) + .build( + "array.load", + Instr::Load( + ptr, + val_t.get_type(scope.type_values, scope.types), + ), + ) .unwrap() .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)), 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 .block - .build(Instr::Alloca(array_ty.clone())) + .build(&array_name, Instr::Alloca(array_ty.clone())) .unwrap() .maybe_location(&mut scope.block, location); 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 .block - .build(Instr::Constant(ConstValue::U32(index as u32))) + .build( + index.to_string(), + Instr::Constant(ConstValue::U32(index as u32)), + ) .unwrap(); let first = scope .block - .build(Instr::Constant(ConstValue::U32(0))) + .build("zero", Instr::Constant(ConstValue::U32(0))) .unwrap(); let ptr = scope .block - .build(Instr::GetElemPtr(array, vec![first, index_expr])) + .build(gep_n, Instr::GetElemPtr(array, vec![first, index_expr])) .unwrap() .maybe_location(&mut scope.block, location); scope .block - .build(Instr::Store(ptr, *instr)) + .build(store_n, Instr::Store(ptr, *instr)) .unwrap() .maybe_location(&mut scope.block, location); } let array_val = scope .block - .build(Instr::Load(array, array_ty)) + .build(load_n, Instr::Load(array, array_ty)) .unwrap() .maybe_location(&mut scope.block, location); @@ -779,9 +820,15 @@ impl mir::Expression { scope.get_typedef(&name).unwrap().kind.clone(); 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 .block - .build(Instr::GetStructElemPtr(struct_val.instr(), idx as u32)) + .build( + gep_n, + Instr::GetStructElemPtr(struct_val.instr(), idx as u32), + ) .unwrap(); // value.maybe_location(&mut scope.block, location); @@ -791,10 +838,13 @@ impl mir::Expression { struct_val.0.derive( scope .block - .build(Instr::Load( - value, - type_kind.get_type(scope.type_values, scope.types), - )) + .build( + load_n, + Instr::Load( + value, + type_kind.get_type(scope.type_values, scope.types), + ), + ) .unwrap(), ), struct_ty.get_field_ty(&field).unwrap().clone(), @@ -808,22 +858,28 @@ impl mir::Expression { } mir::ExprKind::Struct(name, items) => { let struct_ty = Type::CustomType(*scope.type_values.get(name)?); + + let load_n = format!("{}.load", name); + let struct_ptr = scope .block - .build(Instr::Alloca(struct_ty.clone())) + .build(name, Instr::Alloca(struct_ty.clone())) .unwrap() .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 .block - .build(Instr::GetStructElemPtr(struct_ptr, i as u32)) + .build(gep_n, Instr::GetStructElemPtr(struct_ptr, i as u32)) .unwrap() .maybe_location(&mut scope.block, location); if let Some(val) = exp.codegen(scope, state) { scope .block - .build(Instr::Store(elem_ptr, val.instr())) + .build(store_n, Instr::Store(elem_ptr, val.instr())) .unwrap() .maybe_location(&mut scope.block, location); } @@ -831,7 +887,7 @@ impl mir::Expression { let struct_val = scope .block - .build(Instr::Load(struct_ptr, struct_ty)) + .build(load_n, Instr::Load(struct_ptr, struct_ty)) .unwrap(); Some(StackValue( @@ -919,7 +975,10 @@ impl mir::IfExpression { incoming.extend(else_res.clone()); let instr = scope .block - .build(Instr::Phi(incoming.iter().map(|i| i.instr()).collect())) + .build( + "phi", + Instr::Phi(incoming.iter().map(|i| i.instr()).collect()), + ) .unwrap(); use StackValueKind::*; @@ -957,7 +1016,9 @@ impl mir::CmpOperator { impl mir::Literal { 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 {