Fix around in debug information generation, fix subprogram not being set

This commit is contained in:
Sofia 2025-07-18 16:59:05 +03:00
parent 0c6d9885ec
commit 990d8cb448
6 changed files with 171 additions and 168 deletions

View File

@ -8,7 +8,7 @@ use crate::{
TerminatorKind, Type, TypeData,
debug_information::{
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
DebugSubprogramValue,
DebugProgramValue,
},
util::match_types,
};
@ -199,7 +199,7 @@ impl Builder {
pub(crate) unsafe fn set_debug_subprogram(
&self,
value: &FunctionValue,
subprogram: DebugSubprogramValue,
subprogram: DebugProgramValue,
) {
unsafe {
let mut modules = self.modules.borrow_mut();

View File

@ -199,9 +199,9 @@ pub struct LLVMDebugInformation<'a> {
debug: &'a DebugInformation,
builder: LLVMDIBuilderRef,
file_ref: LLVMMetadataRef,
scopes: &'a HashMap<DebugScopeValue, LLVMMetadataRef>,
// scopes: &'a HashMap<DebugScopeValue, LLVMMetadataRef>,
types: &'a mut HashMap<DebugTypeValue, LLVMMetadataRef>,
subprograms: &'a mut HashMap<DebugSubprogramValue, LLVMMetadataRef>,
programs: &'a mut HashMap<DebugProgramValue, LLVMMetadataRef>,
metadata: &'a mut HashMap<DebugMetadataValue, LLVMMetadataRef>,
}
@ -227,10 +227,9 @@ impl ModuleHolder {
// Compile the contents
let mut scopes = HashMap::new();
let mut types = HashMap::new();
let mut metadata = HashMap::new();
let mut subprograms = HashMap::new();
let mut programs = HashMap::new();
let mut debug = if let Some(debug) = &self.debug_information {
let di_builder = LLVMCreateDIBuilder(module_ref);
@ -277,10 +276,15 @@ impl ModuleHolder {
0,
);
let scope = debug.get_scopes();
scope
.borrow()
.compile_scope(compile_unit, file_ref, &mut scopes, di_builder);
// let scope = debug.get_scopes();
// scopes.insert(scope.borrow().value.clone(), compile_unit);
// for scope in &scope.borrow().inner_scopes {
// dbg!("hello");
// scope.compile_scope(compile_unit, file_ref, &mut scopes, di_builder);
// }
// dbg!("after!");
programs.insert(DebugProgramValue(0), compile_unit);
let debug = LLVMDebugInformation {
builder: di_builder,
@ -288,8 +292,7 @@ impl ModuleHolder {
file_ref,
types: &mut types,
metadata: &mut metadata,
subprograms: &mut subprograms,
scopes: &scopes,
programs: &mut programs,
};
for ty in debug.debug.get_types().borrow().iter() {
@ -308,18 +311,22 @@ impl ModuleHolder {
let mut functions = HashMap::new();
for function in &self.functions {
functions.insert(
function.value,
function.compile_signature(context, module_ref, &types, &debug),
);
let func = function.compile_signature(context, module_ref, &types, &debug);
functions.insert(function.value, func);
if let Some(debug) = &mut debug {
if let Some(program_value) = function.data.debug {
debug.programs.insert(program_value, func.metadata.unwrap());
}
}
}
// if let Some(debug) = &mut debug {
// for subprogram in debug.debug.get_subprograms().borrow().iter() {
// let meta_ref = subprogram.compile_debug(&functions, &debug);
// debug.subprograms.insert(subprogram.value.clone(), meta_ref);
// }
// }
if let Some(debug) = &mut debug {
for meta in debug.debug.get_metadata().borrow().iter() {
let meta_ref = meta.compile(&debug);
debug.metadata.insert(meta.value.clone(), meta_ref);
}
}
let mut module = LLVMModule {
builder,
@ -377,15 +384,16 @@ impl DebugScopeHolder {
}
impl DebugMetadataHolder {
unsafe fn compile_meta(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
unsafe fn compile(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef {
dbg!(&self.program);
unsafe {
match &self.data {
DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable(
debug.builder,
*debug.scopes.get(&self.scope).unwrap(),
*debug.programs.get(&self.program).unwrap(),
into_cstring(param.name.clone()).as_ptr(),
param.name.len(),
param.arg_idx,
param.arg_idx + 1,
debug.file_ref,
param.location.line,
*debug.types.get(&param.ty).unwrap(),
@ -493,9 +501,9 @@ impl FunctionHolder {
let mangled_name = LLVMGetValueName2(function_ref, mangled_length_ptr);
let mangled_length = *mangled_length_ptr;
Some(LLVMDIBuilderCreateFunction(
let subprogram = LLVMDIBuilderCreateFunction(
debug.builder,
*debug.scopes.get(&subprogram.scope).unwrap(),
*debug.programs.get(&subprogram.outer_scope).unwrap(),
into_cstring(subprogram.name.clone()).as_ptr(),
subprogram.name.clone().len(),
mangled_name,
@ -508,7 +516,9 @@ impl FunctionHolder {
subprogram.opts.scope_line,
subprogram.opts.flags.as_llvm(),
subprogram.opts.is_optimized as i32,
))
);
LLVMSetSubprogram(function_ref, subprogram);
Some(subprogram)
} else {
None
}

View File

@ -7,7 +7,7 @@ use std::{
pub struct DebugScopeValue(pub Vec<usize>);
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebugLocationValue(pub DebugScopeValue, pub usize);
pub struct DebugLocationValue(pub DebugProgramValue, pub usize);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct DebugTypeValue(pub usize);
@ -15,8 +15,9 @@ pub struct DebugTypeValue(pub usize);
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct DebugMetadataValue(pub usize);
/// Represents either a subprogram, or the compilation context
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub struct DebugSubprogramValue(pub usize);
pub struct DebugProgramValue(pub usize);
#[derive(Debug, Clone)]
pub struct DebugFileData {
@ -34,7 +35,7 @@ pub(crate) struct DebugScopeHolder {
#[derive(Debug, Clone)]
pub struct DebugMetadataHolder {
pub(crate) scope: DebugScopeValue,
pub(crate) program: DebugProgramValue,
pub(crate) value: DebugMetadataValue,
pub(crate) data: DebugMetadata,
}
@ -47,7 +48,7 @@ pub struct DebugTypeHolder {
#[derive(Debug, Clone)]
pub struct DebugSubprogramHolder {
pub(crate) value: DebugSubprogramValue,
pub(crate) value: DebugProgramValue,
pub(crate) data: DebugSubprogramData,
}
@ -60,81 +61,74 @@ pub(crate) struct DebugLocationHolder {
#[derive(Debug, Clone)]
pub struct DebugInformation {
pub file: DebugFileData,
scope: Rc<RefCell<DebugScopeHolder>>,
subprograms: Rc<RefCell<Vec<DebugSubprogramHolder>>>,
// scope: Rc<RefCell<DebugScopeHolder>>,
locations: Rc<RefCell<Vec<DebugLocationHolder>>>,
programs: Rc<RefCell<Vec<DebugSubprogramHolder>>>,
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
types: Rc<RefCell<Vec<DebugTypeHolder>>>,
}
impl DebugInformation {
pub fn from_file(file: DebugFileData) -> (DebugInformation, DebugScopeValue) {
let scope_value = DebugScopeValue(Vec::new());
pub fn from_file(file: DebugFileData) -> (DebugInformation, DebugProgramValue) {
(
DebugInformation {
file,
scope: Rc::new(RefCell::new(DebugScopeHolder {
value: scope_value.clone(),
inner_scopes: Vec::new(),
locations: Vec::new(),
location: None,
})),
// scope: Rc::new(RefCell::new(DebugScopeHolder {
// value: scope_value.clone(),
// inner_scopes: Vec::new(),
// locations: Vec::new(),
// location: None,
// })),
locations: Rc::new(RefCell::new(Vec::new())),
metadata: Rc::new(RefCell::new(Vec::new())),
subprograms: Rc::new(RefCell::new(Vec::new())),
programs: Rc::new(RefCell::new(Vec::new())),
types: Rc::new(RefCell::new(Vec::new())),
},
scope_value,
DebugProgramValue(0),
)
}
pub fn inner_scope(
&self,
parent: &DebugScopeValue,
location: DebugLocation,
) -> DebugScopeValue {
unsafe {
let mut outer_scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
for i in &parent.0 {
v = v.inner_scopes.get_unchecked_mut(*i);
}
v
});
// pub fn inner_scope(
// &self,
// parent: &DebugScopeValue,
// location: DebugLocation,
// ) -> DebugScopeValue {
// unsafe {
// let mut outer_scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
// for i in &parent.0 {
// v = v.inner_scopes.get_unchecked_mut(*i);
// }
// v
// });
let mut arr = parent.0.clone();
arr.push(parent.0.len());
let value = DebugScopeValue(arr);
// let mut arr = parent.0.clone();
// arr.push(parent.0.len());
// let value = DebugScopeValue(arr);
outer_scope.inner_scopes.push(DebugScopeHolder {
value: value.clone(),
inner_scopes: Vec::new(),
locations: Vec::new(),
location: Some(location),
});
value
}
}
// outer_scope.inner_scopes.push(DebugScopeHolder {
// value: value.clone(),
// inner_scopes: Vec::new(),
// locations: Vec::new(),
// location: Some(location),
// });
// value
// }
// }
pub fn location(
&self,
scope_value: &DebugScopeValue,
program_value: &DebugProgramValue,
line: u32,
column: u32,
) -> DebugLocationValue {
unsafe {
let mut scope = RefMut::map(self.scope.borrow_mut(), |mut v| {
for i in &scope_value.0 {
v = v.inner_scopes.get_unchecked_mut(*i);
}
v
});
let value = DebugLocationValue(scope_value.clone(), scope.locations.len());
let value = DebugLocationValue(program_value.clone(), self.locations.borrow().len());
let location = DebugLocationHolder {
value: value.clone(),
location: DebugLocation { line, column },
};
scope.locations.push(location);
self.locations.borrow_mut().push(location);
value
}
}
pub fn debug_type(&self, kind: DebugTypeData) -> DebugTypeValue {
let mut types = self.types.borrow_mut();
@ -146,11 +140,11 @@ impl DebugInformation {
value
}
pub fn metadata(&self, scope: &DebugScopeValue, kind: DebugMetadata) -> DebugMetadataValue {
pub fn metadata(&self, program: &DebugProgramValue, kind: DebugMetadata) -> DebugMetadataValue {
let mut metadata = self.metadata.borrow_mut();
let value = DebugMetadataValue(metadata.len());
metadata.push(DebugMetadataHolder {
scope: scope.clone(),
program: *program,
value: value.clone(),
data: kind,
});
@ -164,9 +158,9 @@ impl DebugInformation {
}
}
pub fn subprogram(&self, kind: DebugSubprogramData) -> DebugSubprogramValue {
let mut subprogram = self.subprograms.borrow_mut();
let value = DebugSubprogramValue(subprogram.len());
pub fn subprogram(&self, kind: DebugSubprogramData) -> DebugProgramValue {
let mut subprogram = self.programs.borrow_mut();
let value = DebugProgramValue(subprogram.len() + 1);
subprogram.push(DebugSubprogramHolder {
value: value.clone(),
data: kind,
@ -178,23 +172,23 @@ impl DebugInformation {
self.metadata.clone()
}
pub fn get_scopes(&self) -> Rc<RefCell<DebugScopeHolder>> {
self.scope.clone()
}
// pub fn get_scopes(&self) -> Rc<RefCell<DebugScopeHolder>> {
// self.scope.clone()
// }
pub fn get_subprograms(&self) -> Rc<RefCell<Vec<DebugSubprogramHolder>>> {
self.subprograms.clone()
self.programs.clone()
}
pub fn get_types(&self) -> Rc<RefCell<Vec<DebugTypeHolder>>> {
self.types.clone()
}
pub fn get_subprogram_data(&self, value: &DebugSubprogramValue) -> DebugSubprogramData {
pub fn get_subprogram_data(&self, value: &DebugProgramValue) -> DebugSubprogramData {
unsafe {
self.subprograms
self.programs
.borrow()
.get_unchecked(value.0)
.get_unchecked(value.0 - 1)
.data
.clone()
}
@ -277,7 +271,7 @@ pub struct DebugSubprogramTypeData {
}
pub struct DebugSubprogramType {
pub params: Vec<DebugSubprogramValue>,
pub params: Vec<DebugProgramValue>,
pub flags: DwarfFlags,
}
@ -296,7 +290,7 @@ pub enum DwarfEncoding {
pub struct DebugSubprogramData {
/// Function name.
pub name: String,
pub scope: DebugScopeValue,
pub outer_scope: DebugProgramValue,
/// Used for line number.
pub location: DebugLocation,
/// Function type.

View File

@ -8,7 +8,7 @@ use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue,
use debug::PrintableModule;
use debug_information::{
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
DebugScopeValue, DebugSubprogramValue,
DebugProgramValue, DebugScopeValue,
};
use util::match_types;
@ -106,10 +106,10 @@ impl<'ctx> Module<'ctx> {
pub fn create_debug_info(
&mut self,
file: DebugFileData,
) -> (DebugInformation, DebugScopeValue) {
let (debug_info, scope) = DebugInformation::from_file(file);
) -> (DebugInformation, DebugProgramValue) {
let (debug_info, program_value) = DebugInformation::from_file(file);
self.debug_info = Some(debug_info.clone());
(debug_info, scope)
(debug_info, program_value)
}
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
@ -131,7 +131,7 @@ pub struct FunctionData {
ret: Type,
params: Vec<Type>,
flags: FunctionFlags,
debug: Option<DebugSubprogramValue>,
debug: Option<DebugProgramValue>,
}
#[derive(Debug, Clone, Copy, Hash)]
@ -177,7 +177,7 @@ impl<'ctx> Function<'ctx> {
}
}
pub fn set_debug(&self, subprogram: DebugSubprogramValue) {
pub fn set_debug(&self, subprogram: DebugProgramValue) {
unsafe {
self.builder.set_debug_subprogram(&self.value, subprogram);
}

View File

@ -5,8 +5,8 @@ use reid_lib::{
compile::CompiledModule,
debug_information::{
DebugBasicType, DebugFileData, DebugInformation, DebugLocation, DebugMetadata,
DebugMetadataValue, DebugParamVariable, DebugScopeValue, DebugSubprogramData,
DebugSubprogramOptionals, DebugSubprogramTypeData, DebugSubprogramValue, DebugTypeData,
DebugMetadataValue, DebugParamVariable, DebugProgramValue, DebugScopeValue,
DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramTypeData, DebugTypeData,
DebugTypeValue, DwarfEncoding, DwarfFlags,
},
Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
@ -82,14 +82,18 @@ pub struct Scope<'ctx, 'a> {
type_values: &'a HashMap<String, TypeValue>,
functions: &'a HashMap<String, StackFunction<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: &'ctx DebugInformation,
debug_scope: DebugScopeValue,
debug: Option<Debug<'ctx>>,
debug_const_tys: &'a HashMap<TypeKind, DebugTypeValue>,
}
#[derive(Debug, Clone)]
pub struct Debug<'ctx> {
info: &'ctx DebugInformation,
scope: Option<DebugProgramValue>,
}
pub struct StackFunction<'ctx> {
ir: Function<'ctx>,
debug: DebugSubprogramValue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -114,8 +118,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
types: self.types,
type_values: self.type_values,
stack_values: self.stack_values.clone(),
debug: self.debug,
debug_scope: self.debug_scope.clone(),
debug: self.debug.clone(),
debug_const_tys: self.debug_const_tys,
}
}
@ -161,7 +164,7 @@ impl mir::Module {
) -> ModuleCodegen<'ctx> {
let mut module = context.module(&self.name, self.is_main);
let (debug, debug_scope) = if let Some(path) = &self.path {
let (debug, compile_unit) = if let Some(path) = &self.path {
module.create_debug_info(DebugFileData {
name: path.file_name().unwrap().to_str().unwrap().to_owned(),
directory: path.parent().unwrap().to_str().unwrap().to_owned(),
@ -240,56 +243,60 @@ impl mir::Module {
),
};
let fn_return_ty = debug_const_types.get(&TypeKind::U32).unwrap();
let debug_ty = debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramTypeData {
parameters: vec![*fn_return_ty],
flags: DwarfFlags,
}));
let subprogram = debug.subprogram(DebugSubprogramData {
name: function.name.clone(),
scope: debug_scope.clone(),
location: DebugLocation { line: 0, column: 0 },
ty: debug_ty,
opts: DebugSubprogramOptionals {
is_local: !function.is_pub,
is_definition: true,
..DebugSubprogramOptionals::default()
},
});
func.set_debug(subprogram);
functions.insert(
function.name.clone(),
StackFunction {
ir: func,
debug: subprogram,
},
);
functions.insert(function.name.clone(), StackFunction { ir: func });
}
for mir_function in &self.functions {
let function = functions.get(&mir_function.name).unwrap();
let mut entry = function.ir.block("entry");
let location = match &mir_function.kind {
mir::FunctionDefinitionKind::Local(_, metadata) => {
metadata.into_debug(tokens).unwrap()
}
mir::FunctionDefinitionKind::Extern(_) => {
// TODO extern should probably still have a meta
DebugLocation {
..Default::default()
}
}
// Insert debug information
let debug_scope = if let Some(location) = mir_function.signature().into_debug(tokens) {
// let debug_scope = debug.inner_scope(&outer_scope, location);
let fn_param_ty = debug_const_types.get(&TypeKind::U32).unwrap();
let debug_ty =
debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramTypeData {
parameters: vec![*fn_param_ty],
flags: DwarfFlags,
}));
let subprogram = debug.subprogram(DebugSubprogramData {
name: mir_function.name.clone(),
outer_scope: compile_unit.clone(),
location,
ty: debug_ty,
opts: DebugSubprogramOptionals {
is_local: !mir_function.is_pub,
is_definition: true,
..DebugSubprogramOptionals::default()
},
});
function.ir.set_debug(subprogram);
Some(subprogram)
} else {
None
};
let debug_scope = debug.inner_scope(&debug_scope, location);
// Compile actual IR part
let mut stack_values = HashMap::new();
for (i, (p_name, p_ty)) in mir_function.parameters.iter().enumerate() {
// Codegen actual parameters
stack_values.insert(
p_name.clone(),
StackValue(
StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()),
p_ty.get_type(&type_values, &types),
),
);
// Generate debug info
if let (Some(debug_scope), Some(location)) =
(&debug_scope, mir_function.signature().into_debug(tokens))
{
debug.metadata(
&debug_scope,
DebugMetadata::ParamVar(DebugParamVariable {
@ -301,14 +308,7 @@ impl mir::Module {
flags: DwarfFlags,
}),
);
stack_values.insert(
p_name.clone(),
StackValue(
StackValueKind::Immutable(entry.build(Instr::Param(i)).unwrap()),
p_ty.get_type(&type_values, &types),
),
);
}
}
let mut scope = Scope {
@ -321,8 +321,7 @@ impl mir::Module {
types: &types,
type_values: &type_values,
stack_values,
debug: &debug,
debug_scope: debug_scope,
debug: None,
debug_const_tys: &debug_const_types,
};

View File

@ -282,14 +282,14 @@ pub enum FunctionDefinitionKind {
}
impl FunctionDefinition {
fn block_meta(&self) -> Metadata {
pub fn block_meta(&self) -> Metadata {
match &self.kind {
FunctionDefinitionKind::Local(block, _) => block.meta.clone(),
FunctionDefinitionKind::Extern(_) => Metadata::default(),
}
}
fn signature(&self) -> Metadata {
pub fn signature(&self) -> Metadata {
match &self.kind {
FunctionDefinitionKind::Local(_, metadata) => metadata.clone(),
FunctionDefinitionKind::Extern(_) => Metadata::default(),