diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index daf2389..26f7e19 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -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<(), ()> { unsafe { let mut modules = self.modules.borrow_mut(); diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 9266ec2..79547a8 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -95,14 +95,6 @@ impl CompiledModule { LLVMSetTarget(self.module_ref, triple); 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 err = ErrorMessageHolder::null(); LLVMTargetMachineEmitToMemoryBuffer( @@ -125,14 +117,28 @@ impl CompiledModule { ); 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 { triple: from_cstring(triple).expect("Unable to convert triple from cstring"), assembly: asm_buffer .as_string() .expect("Error while converting assembly-buffer to string"), obj_buffer: obj_buffer.as_buffer(), - llvm_ir: from_cstring(LLVMPrintModuleToString(self.module_ref)) - .expect("Unable to print LLVM IR to string"), + llvm_ir, } } } @@ -626,7 +632,8 @@ impl BlockHolder { module.values.insert(key, ret); } - self.data + let term_instr = self + .data .terminator .clone() .expect(&format!( @@ -634,6 +641,20 @@ impl BlockHolder { self.data.name )) .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 { _ty, value_ref: val, diff --git a/reid-llvm-lib/src/debug.rs b/reid-llvm-lib/src/debug.rs index 56b6778..5431645 100644 --- a/reid-llvm-lib/src/debug.rs +++ b/reid-llvm-lib/src/debug.rs @@ -5,7 +5,10 @@ use std::{ marker::PhantomData, }; -use crate::{CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*}; +use crate::{ + CmpPredicate, Instr, InstructionData, TerminatorKind, builder::*, + debug_information::DebugLocationValue, +}; impl Debug for Builder { 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 { f.debug_tuple(&format!("{}({:#?}) ", self.data.name, self.value)) .field(&self.functions) + .field(&self.debug_information) .finish() } } @@ -53,6 +57,7 @@ impl Debug for BlockHolder { )) .field(&self.instructions) .field(&self.data.terminator) + .field(&self.data.terminator_location) .finish() } } @@ -67,7 +72,20 @@ impl Debug for InstructionHolder { impl Debug for InstructionData { 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() } } diff --git a/reid-llvm-lib/src/debug_information.rs b/reid-llvm-lib/src/debug_information.rs index d1f05a4..65d81a4 100644 --- a/reid-llvm-lib/src/debug_information.rs +++ b/reid-llvm-lib/src/debug_information.rs @@ -6,7 +6,7 @@ use std::{ #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DebugScopeValue(pub Vec); -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct DebugLocationValue(pub DebugProgramValue, pub usize); #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index b5c8c2e..06563e4 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -170,6 +170,7 @@ impl<'ctx> Function<'ctx> { BlockData { name: name.to_owned(), terminator: None, + terminator_location: None, deleted: false, }, ), @@ -192,6 +193,7 @@ impl<'ctx> Function<'ctx> { pub struct BlockData { name: String, terminator: Option, + terminator_location: Option, deleted: bool, } @@ -233,6 +235,10 @@ impl<'builder> Block<'builder> { 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. pub fn delete_if_unused(&mut self) -> Result { unsafe { diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 111c727..7b0a634 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -321,7 +321,12 @@ impl mir::Module { types: &types, type_values: &type_values, stack_values, - debug: None, + debug: debug_scope.and_then(|scope| { + Some(Debug { + info: &debug, + scope, + }) + }), debug_const_tys: &debug_const_types, }; @@ -337,6 +342,12 @@ impl mir::Module { 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(_) => {} } @@ -668,10 +679,28 @@ impl mir::IfExpression { let condition = self.0.codegen(scope, state).unwrap(); // 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 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 let then_bb = then_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 mut else_scope = scope.with_block(else_b); + scope .block .terminate(Term::CondBr(condition, then_bb, else_bb)) diff --git a/reid/src/mir/impl.rs b/reid/src/mir/impl.rs index 585da65..b71aeca 100644 --- a/reid/src/mir/impl.rs +++ b/reid/src/mir/impl.rs @@ -1,3 +1,5 @@ +use reid_lib::debug_information::DebugLocation; + use super::{typecheck::ErrorKind, typerefs::TypeRefs, VagueType as Vague, *}; #[derive(Debug, Clone)] @@ -69,6 +71,14 @@ impl Block { .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> { let mut early_return = None; diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 4b913be..5787bf9 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -46,7 +46,7 @@ impl Metadata { .skip(self.range.start) .take(self.range.end - self.range.start); 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))) } else { None