Add debug locations to returns
This commit is contained in:
parent
1967cadbc0
commit
b169e67ca4
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)]
|
||||||
|
@ -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 {
|
||||||
|
@ -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))
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user