Start adding debug information
This commit is contained in:
parent
292688a840
commit
9bb4f97e6b
@ -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,
|
||||
|
192
reid-llvm-lib/src/debug_information.rs
Normal file
192
reid-llvm-lib/src/debug_information.rs
Normal 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,
|
||||
}
|
@ -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)]
|
||||
|
@ -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(_) => {}
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user