Add debug locations to returns

This commit is contained in:
Sofia 2025-07-18 18:36:04 +03:00
parent 1967cadbc0
commit b169e67ca4
8 changed files with 135 additions and 18 deletions

View File

@ -228,6 +228,25 @@ impl Builder {
} }
} }
pub(crate) unsafe fn set_terminator_location(
&self,
block: &BlockValue,
location: DebugLocationValue,
) -> Result<(), ()> {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(block.0.0.0);
let function = module.functions.get_unchecked_mut(block.0.1);
let block = function.blocks.get_unchecked_mut(block.1);
if let Some(_) = &block.data.terminator_location {
Err(())
} else {
block.data.terminator_location = Some(location);
Ok(())
}
}
}
pub(crate) unsafe fn delete_block(&self, block: &BlockValue) -> Result<(), ()> { pub(crate) unsafe fn delete_block(&self, block: &BlockValue) -> Result<(), ()> {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();

View File

@ -95,14 +95,6 @@ impl CompiledModule {
LLVMSetTarget(self.module_ref, triple); LLVMSetTarget(self.module_ref, triple);
LLVMSetModuleDataLayout(self.module_ref, data_layout); LLVMSetModuleDataLayout(self.module_ref, data_layout);
let mut err = ErrorMessageHolder::null();
LLVMVerifyModule(
self.module_ref,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
err.borrow_mut(),
);
err.into_result().unwrap();
let mut asm_buffer = MemoryBufferHolder::empty("asm"); let mut asm_buffer = MemoryBufferHolder::empty("asm");
let mut err = ErrorMessageHolder::null(); let mut err = ErrorMessageHolder::null();
LLVMTargetMachineEmitToMemoryBuffer( LLVMTargetMachineEmitToMemoryBuffer(
@ -125,14 +117,28 @@ impl CompiledModule {
); );
err.into_result().unwrap(); err.into_result().unwrap();
let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref))
.expect("Unable to print LLVM IR to string");
let mut err = ErrorMessageHolder::null();
LLVMVerifyModule(
self.module_ref,
llvm_sys::analysis::LLVMVerifierFailureAction::LLVMPrintMessageAction,
err.borrow_mut(),
);
if let Err(e) = err.into_result() {
println!("{}", llvm_ir);
panic!("{}", e);
}
CompileOutput { CompileOutput {
triple: from_cstring(triple).expect("Unable to convert triple from cstring"), triple: from_cstring(triple).expect("Unable to convert triple from cstring"),
assembly: asm_buffer assembly: asm_buffer
.as_string() .as_string()
.expect("Error while converting assembly-buffer to string"), .expect("Error while converting assembly-buffer to string"),
obj_buffer: obj_buffer.as_buffer(), obj_buffer: obj_buffer.as_buffer(),
llvm_ir: from_cstring(LLVMPrintModuleToString(self.module_ref)) llvm_ir,
.expect("Unable to print LLVM IR to string"),
} }
} }
} }
@ -626,7 +632,8 @@ impl BlockHolder {
module.values.insert(key, ret); module.values.insert(key, ret);
} }
self.data let term_instr = self
.data
.terminator .terminator
.clone() .clone()
.expect(&format!( .expect(&format!(
@ -634,6 +641,20 @@ impl BlockHolder {
self.data.name self.data.name
)) ))
.compile(module, function, block_ref); .compile(module, function, block_ref);
dbg!(&self.value, &self.data.terminator_location);
if let Some(location) = &self.data.terminator_location {
LLVMInstructionSetDebugLoc(
term_instr.value_ref,
*module
.debug
.as_ref()
.unwrap()
.locations
.get(&location)
.unwrap(),
);
}
} }
} }
} }
@ -790,7 +811,20 @@ impl InstructionHolder {
} }
} }
}; };
if let Some(location_value) = &self.data.location {} if let Some(location) = &self.data.location {
unsafe {
// LLVMInstructionSetDebugLoc(
// val,
// *module
// .debug
// .as_ref()
// .unwrap()
// .locations
// .get(&location)
// .unwrap(),
// );
}
}
LLVMValue { LLVMValue {
_ty, _ty,
value_ref: val, value_ref: val,

View File

@ -5,7 +5,10 @@ use std::{
marker::PhantomData, marker::PhantomData,
}; };
use crate::{CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*}; use crate::{
CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*,
debug_information::DebugLocationValue,
};
impl Debug for Builder { impl Debug for Builder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@ -29,6 +32,7 @@ impl Debug for ModuleHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value)) f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value))
.field(&self.functions) .field(&self.functions)
.field(&self.debug_information)
.finish() .finish()
} }
} }
@ -53,6 +57,7 @@ impl Debug for BlockHolder {
)) ))
.field(&self.instructions) .field(&self.instructions)
.field(&self.data.terminator) .field(&self.data.terminator)
.field(&self.data.terminator_location)
.finish() .finish()
} }
} }
@ -67,7 +72,20 @@ impl Debug for InstructionHolder {
impl Debug for InstructionData { impl Debug for InstructionData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.kind.fmt(f) self.kind.fmt(f)?;
if let Some(location) = self.location {
write!(f, " ({:?})", location)?;
}
Ok(())
}
}
impl Debug for DebugLocationValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("DebugLocationValue")
.field(&self.0)
.field(&self.1)
.finish()
} }
} }

View File

@ -6,7 +6,7 @@ use std::{
#[derive(Debug, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebugScopeValue(pub Vec<usize>); pub struct DebugScopeValue(pub Vec<usize>);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] #[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub struct DebugLocationValue(pub DebugProgramValue, pub usize); pub struct DebugLocationValue(pub DebugProgramValue, pub usize);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]

View File

@ -170,6 +170,7 @@ impl<'ctx> Function<'ctx> {
BlockData { BlockData {
name: name.to_owned(), name: name.to_owned(),
terminator: None, terminator: None,
terminator_location: None,
deleted: false, deleted: false,
}, },
), ),
@ -192,6 +193,7 @@ impl<'ctx> Function<'ctx> {
pub struct BlockData { pub struct BlockData {
name: String, name: String,
terminator: Option<TerminatorKind>, terminator: Option<TerminatorKind>,
terminator_location: Option<DebugLocationValue>,
deleted: bool, deleted: bool,
} }
@ -233,6 +235,10 @@ impl<'builder> Block<'builder> {
unsafe { self.builder.terminate(&self.value, instruction) } unsafe { self.builder.terminate(&self.value, instruction) }
} }
pub fn set_terminator_location(&mut self, location: DebugLocationValue) -> Result<(), ()> {
unsafe { self.builder.set_terminator_location(&self.value, location) }
}
/// Delete block if it is unused. Return true if deleted, false if not. /// Delete block if it is unused. Return true if deleted, false if not.
pub fn delete_if_unused(&mut self) -> Result<bool, ()> { pub fn delete_if_unused(&mut self) -> Result<bool, ()> {
unsafe { unsafe {

View File

@ -321,7 +321,12 @@ impl mir::Module {
types: &types, types: &types,
type_values: &type_values, type_values: &type_values,
stack_values, stack_values,
debug: None, debug: debug_scope.and_then(|scope| {
Some(Debug {
info: &debug,
scope,
})
}),
debug_const_tys: &debug_const_types, debug_const_tys: &debug_const_types,
}; };
@ -337,6 +342,12 @@ impl mir::Module {
scope.block.terminate(Term::RetVoid).ok(); scope.block.terminate(Term::RetVoid).ok();
} }
} }
if let Some(debug) = scope.debug {
let location = &block.return_meta().into_debug(tokens).unwrap();
let location = debug.info.location(&debug.scope, *location);
scope.block.set_terminator_location(location).unwrap();
}
} }
mir::FunctionDefinitionKind::Extern(_) => {} mir::FunctionDefinitionKind::Extern(_) => {}
} }
@ -668,10 +679,28 @@ impl mir::IfExpression {
let condition = self.0.codegen(scope, state).unwrap(); let condition = self.0.codegen(scope, state).unwrap();
// Create blocks // Create blocks
let then_b = scope.function.ir.block("then"); let mut then_b = scope.function.ir.block("then");
let mut else_b = scope.function.ir.block("else"); let mut else_b = scope.function.ir.block("else");
let after_b = scope.function.ir.block("after"); let after_b = scope.function.ir.block("after");
if let Some(debug) = &scope.debug {
let before_location = self.0 .1.into_debug(scope.tokens).unwrap();
let before_v = debug.info.location(&debug.scope, before_location);
scope.block.set_terminator_location(before_v).unwrap();
let then_location = self.1.return_meta().into_debug(scope.tokens).unwrap();
let then_v = debug.info.location(&debug.scope, then_location);
then_b.set_terminator_location(then_v).unwrap();
let else_location = if let Some(else_block) = &self.2 {
else_block.return_meta().into_debug(scope.tokens).unwrap()
} else {
then_location
};
let else_v = debug.info.location(&debug.scope, else_location);
else_b.set_terminator_location(else_v).unwrap();
}
// Store for convenience // Store for convenience
let then_bb = then_b.value(); let then_bb = then_b.value();
let else_bb = else_b.value(); let else_bb = else_b.value();
@ -684,6 +713,7 @@ impl mir::IfExpression {
let else_res = if let Some(else_block) = &self.2 { let else_res = if let Some(else_block) = &self.2 {
let mut else_scope = scope.with_block(else_b); let mut else_scope = scope.with_block(else_b);
scope scope
.block .block
.terminate(Term::CondBr(condition, then_bb, else_bb)) .terminate(Term::CondBr(condition, then_bb, else_bb))

View File

@ -1,3 +1,5 @@
use reid_lib::debug_information::DebugLocation;
use super::{typecheck::ErrorKind, typerefs::TypeRefs, VagueType as Vague, *}; use super::{typecheck::ErrorKind, typerefs::TypeRefs, VagueType as Vague, *};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -69,6 +71,14 @@ impl Block {
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta)) .ok_or(ReturnTypeOther::NoBlockReturn(self.meta))
} }
pub fn return_meta(&self) -> Metadata {
self.return_expression
.as_ref()
.map(|e| e.1 .1)
.or(self.statements.last().map(|s| s.1))
.unwrap_or(self.meta)
}
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let mut early_return = None; let mut early_return = None;

View File

@ -46,7 +46,7 @@ impl Metadata {
.skip(self.range.start) .skip(self.range.start)
.take(self.range.end - self.range.start); .take(self.range.end - self.range.start);
if let Some(first) = iter.next() { if let Some(first) = iter.next() {
let last = iter.last().unwrap(); let last = iter.last().unwrap_or(first);
Some((first.position, last.position.add(last.token.len() as u32))) Some((first.position, last.position.add(last.token.len() as u32)))
} else { } else {
None None