Start adding debug information

This commit is contained in:
Sofia 2025-07-18 00:07:11 +03:00
parent 292688a840
commit 9bb4f97e6b
5 changed files with 373 additions and 9 deletions

View File

@ -5,7 +5,11 @@ use std::{cell::RefCell, rc::Rc};
use crate::{
BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct,
TerminatorKind, Type, TypeData, util::match_types,
TerminatorKind, Type, TypeData,
debug_information::{
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
},
util::match_types,
};
#[derive(Clone, Hash, Copy, PartialEq, Eq)]
@ -29,6 +33,7 @@ pub struct ModuleHolder {
pub(crate) data: ModuleData,
pub(crate) functions: Vec<FunctionHolder>,
pub(crate) types: Vec<TypeHolder>,
pub(crate) debug_information: Option<DebugInformation>,
}
#[derive(Clone)]
@ -76,10 +81,23 @@ impl Builder {
data,
functions: Vec::new(),
types: Vec::new(),
debug_information: None,
});
value
}
pub(crate) fn set_debug_information(
&self,
mod_val: &ModuleValue,
debug_info: DebugInformation,
) {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(mod_val.0);
module.debug_information = Some(debug_info);
}
}
pub(crate) unsafe fn add_type(&self, mod_val: &ModuleValue, data: TypeData) -> TypeValue {
unsafe {
let mut modules = self.modules.borrow_mut();
@ -145,6 +163,49 @@ impl Builder {
}
}
pub(crate) unsafe fn add_instruction_location(
&self,
value: &InstructionValue,
location: DebugLocationValue,
) {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0.0.0);
let function = module.functions.get_unchecked_mut(value.0.0.1);
let block = function.blocks.get_unchecked_mut(value.0.1);
let instr = block.instructions.get_unchecked_mut(value.1);
instr.data.location = Some(location)
}
}
pub(crate) unsafe fn add_instruction_metadata(
&self,
value: &InstructionValue,
metadata: DebugMetadataValue,
) {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0.0.0);
let function = module.functions.get_unchecked_mut(value.0.0.1);
let block = function.blocks.get_unchecked_mut(value.0.1);
let instr = block.instructions.get_unchecked_mut(value.1);
instr.data.meta = Some(metadata)
}
}
pub(crate) unsafe fn add_function_metadata(
&self,
value: &FunctionValue,
metadata: DebugMetadataValue,
) {
unsafe {
let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(value.0.0);
let function = module.functions.get_unchecked_mut(value.1);
function.data.meta = Some(metadata)
}
}
pub(crate) unsafe fn terminate(
&self,
block: &BlockValue,

View File

@ -0,0 +1,192 @@
use std::{
cell::{RefCell, RefMut},
rc::Rc,
};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebugScopeValue(pub Vec<usize>);
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebugLocationValue(pub DebugScopeValue, pub usize);
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebugMetadataValue(pub usize);
#[derive(Debug, Clone)]
pub struct DebugFileData {
pub name: String,
pub directory: String,
}
#[derive(Debug, Clone)]
pub(crate) struct DebugScopeHolder {
value: DebugScopeValue,
location: Option<DebugLocation>,
inner_scopes: Vec<DebugScopeHolder>,
locations: Vec<DebugLocationHolder>,
}
#[derive(Debug, Clone)]
pub struct DebugMetadataHolder {
scope: DebugScopeValue,
value: DebugMetadataValue,
data: DebugMetadata,
}
#[derive(Debug, Clone)]
pub(crate) struct DebugLocationHolder {
value: DebugLocationValue,
location: DebugLocation,
}
#[derive(Debug, Clone)]
pub struct DebugLocation {
pub line: u32,
pub column: u32,
}
#[derive(Debug, Clone)]
pub struct DebugInformation {
file: DebugFileData,
scope: Rc<RefCell<DebugScopeHolder>>,
metadata: Rc<RefCell<Vec<DebugMetadataHolder>>>,
}
impl DebugInformation {
pub fn from_file(file: DebugFileData) -> (DebugInformation, DebugScopeValue) {
let scope_value = DebugScopeValue(Vec::new());
(
DebugInformation {
file,
scope: Rc::new(RefCell::new(DebugScopeHolder {
value: scope_value.clone(),
inner_scopes: Vec::new(),
locations: Vec::new(),
location: None,
})),
metadata: Rc::new(RefCell::new(Vec::new())),
},
scope_value,
)
}
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);
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,
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 location = DebugLocationHolder {
value: value.clone(),
location: DebugLocation { line, column },
};
scope.locations.push(location);
value
}
}
pub fn metadata(&self, scope: &DebugScopeValue, kind: DebugMetadata) -> DebugMetadataValue {
let mut metadata = self.metadata.borrow_mut();
let value = DebugMetadataValue(metadata.len());
metadata.push(DebugMetadataHolder {
scope: scope.clone(),
value: value.clone(),
data: kind,
});
value
}
}
#[derive(Debug, Clone)]
pub enum DebugMetadata {
Function(DebugFunction),
BasicType(DebugBasicType),
ParamVar(DebugParamVariable),
LocalVar(DebugLocalVariable),
}
#[derive(Debug, Clone)]
pub struct DebugBasicType {
pub name: String,
pub size_bits: u32,
pub encoding: AteEncoding,
}
#[derive(Debug, Clone)]
pub enum AteEncoding {
Address = 1,
Boolean = 2,
Float = 4,
Signed = 5,
SignedChar = 6,
Unsigned = 7,
UnsignedChar = 8,
}
#[derive(Debug, Clone)]
pub struct DebugFunction {
pub scope: DebugScopeValue,
pub name: String,
pub linkage_name: String,
pub location: DebugLocation,
pub return_ty: DebugMetadataValue,
pub is_local: bool,
pub is_definition: bool,
pub is_optimized: bool,
pub scope_line: u32,
}
#[derive(Debug, Clone)]
pub struct DebugParamVariable {
pub scope: DebugScopeValue,
pub name: String,
pub arg_idx: u32,
pub location: DebugLocation,
pub ty: DebugMetadataValue,
pub always_preserve: bool,
}
#[derive(Debug, Clone)]
pub struct DebugLocalVariable {
pub scope: DebugScopeValue,
pub name: String,
pub location: DebugLocation,
pub ty: DebugMetadataValue,
pub always_preserve: bool,
pub alignment: u32,
}

View File

@ -6,15 +6,18 @@ use std::{fmt::Debug, marker::PhantomData};
use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, TypeValue};
use debug::PrintableModule;
use debug_information::{
DebugFileData, DebugInformation, DebugLocation, DebugLocationValue, DebugMetadataValue,
DebugScopeValue,
};
use util::match_types;
pub mod builder;
pub mod compile;
mod debug;
pub mod debug_information;
mod util;
// pub struct InstructionValue(BlockValue, usize);
#[derive(Debug)]
pub struct Context {
builder: Builder,
@ -36,6 +39,7 @@ impl Context {
phantom: PhantomData,
builder: self.builder.clone(),
value,
debug_info: None,
}
}
}
@ -50,11 +54,12 @@ pub struct Module<'ctx> {
phantom: PhantomData<&'ctx ()>,
builder: Builder,
value: ModuleValue,
debug_info: Option<DebugInformation>,
}
impl<'ctx> Module<'ctx> {
pub fn function(
&mut self,
&self,
name: &str,
ret: Type,
params: Vec<Type>,
@ -71,13 +76,14 @@ impl<'ctx> Module<'ctx> {
ret,
params,
flags,
meta: None,
},
),
}
}
}
pub fn custom_type(&mut self, ty: CustomTypeKind) -> TypeValue {
pub fn custom_type(&self, ty: CustomTypeKind) -> TypeValue {
unsafe {
let (name, kind) = match &ty {
CustomTypeKind::NamedStruct(NamedStruct(name, _)) => (name.clone(), ty),
@ -96,6 +102,27 @@ impl<'ctx> Module<'ctx> {
module: self.builder.find_module(self.value),
}
}
pub fn create_debug_info(
&mut self,
file: DebugFileData,
) -> (DebugInformation, DebugScopeValue) {
let (debug_info, scope) = DebugInformation::from_file(file);
self.debug_info = Some(debug_info.clone());
(debug_info, scope)
}
pub fn get_debug_info(&self) -> &Option<DebugInformation> {
&self.debug_info
}
}
impl<'ctx> Drop for Module<'ctx> {
fn drop(&mut self) {
if let Some(debug_info) = self.debug_info.take() {
self.builder.set_debug_information(&self.value, debug_info);
}
}
}
#[derive(Debug, Clone, Hash)]
@ -104,6 +131,7 @@ pub struct FunctionData {
ret: Type,
params: Vec<Type>,
flags: FunctionFlags,
meta: Option<DebugMetadataValue>,
}
#[derive(Debug, Clone, Copy, Hash)]
@ -149,6 +177,12 @@ impl<'ctx> Function<'ctx> {
}
}
pub fn set_metadata(&self, metadata: DebugMetadataValue) {
unsafe {
self.builder.add_function_metadata(&self.value, metadata);
}
}
pub fn value(&self) -> FunctionValue {
self.value
}
@ -169,9 +203,29 @@ pub struct Block<'builder> {
impl<'builder> Block<'builder> {
pub fn build(&mut self, instruction: Instr) -> Result<InstructionValue, ()> {
unsafe {
self.builder.add_instruction(
&self.value,
InstructionData {
kind: instruction,
location: None,
meta: None,
},
)
}
}
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
unsafe {
self.builder
.add_instruction(&self.value, InstructionData { kind: instruction })
.add_instruction_location(&instruction, location);
}
}
pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) {
unsafe {
self.builder
.add_instruction_metadata(&instruction, location);
}
}
@ -196,9 +250,11 @@ impl<'builder> Block<'builder> {
}
}
#[derive(Clone, Hash)]
#[derive(Clone)]
pub struct InstructionData {
kind: Instr,
location: Option<DebugLocationValue>,
meta: Option<DebugMetadataValue>,
}
#[derive(Clone, Copy, Hash)]

View File

@ -3,6 +3,10 @@ use std::{collections::HashMap, mem};
use reid_lib::{
builder::{InstructionValue, TypeValue},
compile::CompiledModule,
debug_information::{
AteEncoding, DebugBasicType, DebugFileData, DebugFunction, DebugInformation, DebugLocation,
DebugMetadata, DebugMetadataValue, DebugScopeValue,
},
Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr,
Module, NamedStruct, TerminatorKind as Term, Type,
};
@ -56,6 +60,9 @@ pub struct Scope<'ctx, 'a> {
type_values: &'a HashMap<String, TypeValue>,
functions: &'a HashMap<String, Function<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: &'ctx DebugInformation,
debug_scope: DebugScopeValue,
debug_const_tys: &'a HashMap<TypeKind, DebugMetadataValue>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -79,6 +86,9 @@ 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_const_tys: self.debug_const_tys,
}
}
@ -119,8 +129,33 @@ impl mir::Module {
fn codegen<'ctx>(&self, context: &'ctx Context) -> ModuleCodegen<'ctx> {
let mut module = context.module(&self.name, self.is_main);
let (debug, debug_scope) = 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(),
})
} else {
module.create_debug_info(DebugFileData {
name: self.name.clone(),
directory: String::new(),
})
};
let mut types = HashMap::new();
let mut type_values = HashMap::new();
let mut debug_const_types = HashMap::new();
debug_const_types.insert(
TypeKind::U32,
debug.metadata(
&debug_scope,
DebugMetadata::BasicType(DebugBasicType {
name: String::from("u32"),
size_bits: 32,
encoding: AteEncoding::Unsigned,
}),
),
);
for typedef in &self.typedefs {
let type_value = match &typedef.kind {
@ -201,6 +236,9 @@ impl mir::Module {
types: &types,
type_values: &type_values,
stack_values,
debug: &debug,
debug_scope: debug_scope.clone(),
debug_const_tys: &debug_const_types,
};
match &mir_function.kind {
mir::FunctionDefinitionKind::Local(block, _) => {
@ -214,6 +252,23 @@ impl mir::Module {
scope.block.terminate(Term::RetVoid).ok();
}
}
let fn_return_ty = debug_const_types.get(&TypeKind::U32).unwrap();
scope.function.set_metadata(scope.debug.metadata(
&scope.debug_scope,
DebugMetadata::Function(DebugFunction {
scope: scope.debug_scope.clone(),
name: mir_function.name.clone(),
linkage_name: String::new(),
location: DebugLocation { line: 0, column: 0 },
return_ty: fn_return_ty.clone(),
is_local: true,
is_definition: true,
is_optimized: false,
scope_line: 0,
}),
));
}
mir::FunctionDefinitionKind::Extern(_) => {}
}

View File

@ -61,7 +61,7 @@ impl TokenRange {
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, PartialOrd, Ord)]
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, PartialOrd, Ord, Hash)]
pub enum TypeKind {
#[error("bool")]
Bool,
@ -99,7 +99,7 @@ pub enum TypeKind {
Vague(#[from] VagueType),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error, PartialOrd, Ord, Hash)]
pub enum VagueType {
#[error("Unknown")]
Unknown,