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<(), ()> {
|
||||
unsafe {
|
||||
let mut modules = self.modules.borrow_mut();
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use std::{
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
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);
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
|
@ -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<TerminatorKind>,
|
||||
terminator_location: Option<DebugLocationValue>,
|
||||
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<bool, ()> {
|
||||
unsafe {
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user