Get debug info working very preliminarily

This commit is contained in:
Sofia 2025-07-18 17:26:11 +03:00
parent 287ab69d32
commit 1967cadbc0
5 changed files with 83 additions and 13 deletions

View File

@ -2,7 +2,10 @@
//! LLIR ([`Context`]) into LLVM IR. This module is the only one that interfaces //! LLIR ([`Context`]) into LLVM IR. This module is the only one that interfaces
//! with the LLVM API. //! with the LLVM API.
use std::{collections::HashMap, ptr::null_mut}; use std::{
collections::HashMap,
ptr::{null, null_mut},
};
use llvm_sys::{ use llvm_sys::{
LLVMIntPredicate, LLVMLinkage, LLVMIntPredicate, LLVMLinkage,
@ -203,6 +206,7 @@ pub struct LLVMDebugInformation<'a> {
types: &'a mut HashMap<DebugTypeValue, LLVMMetadataRef>, types: &'a mut HashMap<DebugTypeValue, LLVMMetadataRef>,
programs: &'a mut HashMap<DebugProgramValue, LLVMMetadataRef>, programs: &'a mut HashMap<DebugProgramValue, LLVMMetadataRef>,
metadata: &'a mut HashMap<DebugMetadataValue, LLVMMetadataRef>, metadata: &'a mut HashMap<DebugMetadataValue, LLVMMetadataRef>,
locations: &'a mut HashMap<DebugLocationValue, LLVMMetadataRef>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -230,6 +234,7 @@ impl ModuleHolder {
let mut types = HashMap::new(); let mut types = HashMap::new();
let mut metadata = HashMap::new(); let mut metadata = HashMap::new();
let mut programs = HashMap::new(); let mut programs = HashMap::new();
let mut locations = HashMap::new();
let mut debug = if let Some(debug) = &self.debug_information { let mut debug = if let Some(debug) = &self.debug_information {
let di_builder = LLVMCreateDIBuilder(module_ref); let di_builder = LLVMCreateDIBuilder(module_ref);
@ -293,6 +298,7 @@ impl ModuleHolder {
types: &mut types, types: &mut types,
metadata: &mut metadata, metadata: &mut metadata,
programs: &mut programs, programs: &mut programs,
locations: &mut locations,
}; };
for ty in debug.debug.get_types().borrow().iter() { for ty in debug.debug.get_types().borrow().iter() {
@ -322,6 +328,11 @@ impl ModuleHolder {
} }
if let Some(debug) = &mut debug { if let Some(debug) = &mut debug {
for location in debug.debug.get_locations().borrow().iter() {
let location_ref = location.compile(context, &debug);
debug.locations.insert(location.value, location_ref);
}
for meta in debug.debug.get_metadata().borrow().iter() { for meta in debug.debug.get_metadata().borrow().iter() {
let meta_ref = meta.compile(&debug); let meta_ref = meta.compile(&debug);
debug.metadata.insert(meta.value.clone(), meta_ref); debug.metadata.insert(meta.value.clone(), meta_ref);
@ -353,6 +364,24 @@ impl ModuleHolder {
} }
} }
impl DebugLocationHolder {
unsafe fn compile(
&self,
context: &LLVMContext,
debug: &LLVMDebugInformation,
) -> LLVMMetadataRef {
unsafe {
LLVMDIBuilderCreateDebugLocation(
context.context_ref,
self.location.line,
self.location.column,
*debug.programs.get(&self.program).unwrap(),
null_mut(),
)
}
}
}
impl DebugScopeHolder { impl DebugScopeHolder {
unsafe fn compile_scope( unsafe fn compile_scope(
&self, &self,
@ -761,6 +790,7 @@ impl InstructionHolder {
} }
} }
}; };
if let Some(location_value) = &self.data.location {}
LLVMValue { LLVMValue {
_ty, _ty,
value_ref: val, value_ref: val,

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, Hash, PartialEq, Eq)] #[derive(Debug, 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)]
@ -54,8 +54,9 @@ pub struct DebugSubprogramHolder {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct DebugLocationHolder { pub(crate) struct DebugLocationHolder {
value: DebugLocationValue, pub(crate) program: DebugProgramValue,
location: DebugLocation, pub(crate) value: DebugLocationValue,
pub(crate) location: DebugLocation,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -118,13 +119,13 @@ impl DebugInformation {
pub fn location( pub fn location(
&self, &self,
program_value: &DebugProgramValue, program_value: &DebugProgramValue,
line: u32, location: DebugLocation,
column: u32,
) -> DebugLocationValue { ) -> DebugLocationValue {
let value = DebugLocationValue(program_value.clone(), self.locations.borrow().len()); let value = DebugLocationValue(program_value.clone(), self.locations.borrow().len());
let location = DebugLocationHolder { let location = DebugLocationHolder {
program: *program_value,
value: value.clone(), value: value.clone(),
location: DebugLocation { line, column }, location,
}; };
self.locations.borrow_mut().push(location); self.locations.borrow_mut().push(location);
value value
@ -184,6 +185,10 @@ impl DebugInformation {
self.types.clone() self.types.clone()
} }
pub fn get_locations(&self) -> Rc<RefCell<Vec<DebugLocationHolder>>> {
self.locations.clone()
}
pub fn get_subprogram_data(&self, value: &DebugProgramValue) -> DebugSubprogramData { pub fn get_subprogram_data(&self, value: &DebugProgramValue) -> DebugSubprogramData {
unsafe { unsafe {
self.programs self.programs

View File

@ -250,6 +250,28 @@ impl<'builder> Block<'builder> {
} }
} }
impl InstructionValue {
pub fn with_location(self, block: &Block, location: DebugLocationValue) -> InstructionValue {
unsafe {
block.builder.add_instruction_location(&self, location);
}
self
}
pub fn maybe_location(
self,
block: &mut Block,
location: Option<DebugLocationValue>,
) -> InstructionValue {
unsafe {
if let Some(location) = location {
block.builder.add_instruction_location(&self, location);
}
}
self
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct InstructionData { pub struct InstructionData {
kind: Instr, kind: Instr,

View File

@ -89,7 +89,7 @@ pub struct Scope<'ctx, 'a> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Debug<'ctx> { pub struct Debug<'ctx> {
info: &'ctx DebugInformation, info: &'ctx DebugInformation,
scope: Option<DebugProgramValue>, scope: DebugProgramValue,
} }
pub struct StackFunction<'ctx> { pub struct StackFunction<'ctx> {
@ -440,6 +440,16 @@ impl mir::Expression {
scope: &mut Scope<'ctx, 'a>, scope: &mut Scope<'ctx, 'a>,
state: &State, state: &State,
) -> Option<InstructionValue> { ) -> Option<InstructionValue> {
let location = if let Some(debug) = &scope.debug {
Some(
debug
.info
.location(&debug.scope, self.1.into_debug(scope.tokens).unwrap()),
)
} else {
None
};
match &self.0 { match &self.0 {
mir::ExprKind::Variable(varref) => { mir::ExprKind::Variable(varref) => {
varref.0.known().expect("variable type unknown"); varref.0.known().expect("variable type unknown");
@ -463,7 +473,10 @@ impl mir::Expression {
_ => panic!("Found an unknown-mutable variable!"), _ => panic!("Found an unknown-mutable variable!"),
}) })
} }
mir::ExprKind::Literal(lit) => Some(lit.as_const(&mut scope.block)), mir::ExprKind::Literal(lit) => Some(
lit.as_const(&mut scope.block)
.maybe_location(&mut scope.block, location),
),
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
lhs_exp lhs_exp
.return_type() .return_type()

View File

@ -95,10 +95,10 @@ impl<'map> Pass for LinkerPass<'map> {
modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens))));
} }
modules.insert( // modules.insert(
"std".to_owned(), // "std".to_owned(),
Rc::new(RefCell::new(compile_std(&mut self.module_map))), // Rc::new(RefCell::new(compile_std(&mut self.module_map))),
); // );
let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> = let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> =
modules.values().cloned().collect(); modules.values().cloned().collect();