diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index c70665e..1024947 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -8,6 +8,7 @@ use crate::{ TerminatorKind, Type, TypeData, debug_information::{ DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, + InstructionDebugRecordData, }, util::match_types, }; @@ -60,6 +61,7 @@ pub struct BlockHolder { pub struct InstructionHolder { pub(crate) value: InstructionValue, pub(crate) data: InstructionData, + pub(crate) record: Option, } #[derive(Clone)] @@ -154,7 +156,11 @@ impl Builder { let function = module.functions.get_unchecked_mut(block_val.0.1); let block = function.blocks.get_unchecked_mut(block_val.1); let value = InstructionValue(block.value, block.instructions.len()); - block.instructions.push(InstructionHolder { value, data }); + block.instructions.push(InstructionHolder { + value, + data, + record: None, + }); // Drop modules so that it is no longer mutable borrowed // (check_instruction requires an immutable borrow). @@ -195,6 +201,21 @@ impl Builder { } } + pub(crate) unsafe fn add_instruction_record( + &self, + value: &InstructionValue, + record: InstructionDebugRecordData, + ) { + 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.record = Some(record) + } + } + pub(crate) unsafe fn set_debug_subprogram( &self, value: &FunctionValue, diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index db0d6cd..c6f7d1e 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -417,7 +417,6 @@ impl DebugScopeHolder { impl DebugMetadataHolder { unsafe fn compile(&self, debug: &LLVMDebugInformation) -> LLVMMetadataRef { - dbg!(&self.program); unsafe { match &self.data { DebugMetadata::ParamVar(param) => LLVMDIBuilderCreateParameterVariable( @@ -444,6 +443,7 @@ impl DebugMetadataHolder { var.flags.as_llvm(), var.alignment, ), + DebugMetadata::VarAssignment => todo!(), } } } @@ -822,6 +822,48 @@ impl InstructionHolder { } } }; + if let Some(record) = &self.record { + let debug = module.debug.as_ref().unwrap(); + + unsafe { + let mut addr = Vec::::new(); + let expr = + LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); + + let location = LLVMDIBuilderCreateDebugLocation( + module.context_ref, + record.location.line, + record.location.column, + *debug.programs.get(&record.scope).unwrap(), + null_mut(), + ); + + match record.kind { + DebugRecordKind::Declare(instruction_value) => { + dbg!(&self.value, &instruction_value); + + LLVMDIBuilderInsertDeclareRecordBefore( + debug.builder, + module.values.get(&instruction_value).unwrap().value_ref, + *debug.metadata.get(&record.variable).unwrap(), + expr, + location, + val, + ) + } + DebugRecordKind::Value(instruction_value) => { + LLVMDIBuilderInsertDbgValueRecordBefore( + debug.builder, + module.values.get(&instruction_value).unwrap().value_ref, + *debug.metadata.get(&record.variable).unwrap(), + expr, + location, + val, + ) + } + }; + } + } if let Some(location) = &self.data.location { unsafe { // dbg!(&self.data.kind, LLVMGetValueKind(val)); @@ -850,6 +892,26 @@ impl InstructionHolder { value_ref: val, } } + + fn get_inner_value(&self) -> Option { + match &self.data.kind { + crate::Instr::Param(_) => None, + crate::Instr::Constant(_) => None, + crate::Instr::Add(_, _) => None, + crate::Instr::Sub(_, _) => None, + crate::Instr::Mult(_, _) => None, + crate::Instr::And(_, _) => None, + crate::Instr::Phi(_) => None, + crate::Instr::Alloca(_, _) => todo!(), + crate::Instr::Load(_, _) => None, + crate::Instr::Store(_, val) => Some(*val), + crate::Instr::ArrayAlloca(_, _) => None, + crate::Instr::GetElemPtr(_, _) => None, + crate::Instr::GetStructElemPtr(_, _) => None, + crate::Instr::ICmp(_, _, _) => None, + crate::Instr::FunctionCall(_, _) => None, + } + } } impl TerminatorKind { diff --git a/reid-llvm-lib/src/debug_information.rs b/reid-llvm-lib/src/debug_information.rs index e469323..4b0931d 100644 --- a/reid-llvm-lib/src/debug_information.rs +++ b/reid-llvm-lib/src/debug_information.rs @@ -1,5 +1,7 @@ use std::{cell::RefCell, rc::Rc}; +use crate::builder::InstructionValue; + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct DebugScopeValue(pub Vec); @@ -153,6 +155,7 @@ impl DebugInformation { match &metadata { DebugMetadata::ParamVar(debug_param_variable) => todo!(), DebugMetadata::LocalVar(debug_local_variable) => todo!(), + DebugMetadata::VarAssignment => todo!(), } } @@ -207,6 +210,7 @@ pub struct DebugLocation { pub enum DebugMetadata { ParamVar(DebugParamVariable), LocalVar(DebugLocalVariable), + VarAssignment, } #[derive(Debug, Clone)] @@ -312,3 +316,17 @@ pub struct DebugSubprogramOptionals { /// prototyped or not. pub flags: DwarfFlags, } + +#[derive(Clone)] +pub struct InstructionDebugRecordData { + pub scope: DebugProgramValue, + pub variable: DebugMetadataValue, + pub location: DebugLocation, + pub kind: DebugRecordKind, +} + +#[derive(Clone, Copy)] +pub enum DebugRecordKind { + Declare(InstructionValue), + Value(InstructionValue), +} diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 6d6618c..ab88fb4 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -8,6 +8,7 @@ use builder::{BlockValue, Builder, FunctionValue, InstructionValue, ModuleValue, use debug::PrintableModule; use debug_information::{ DebugFileData, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, + InstructionDebugRecordData, }; use util::match_types; @@ -275,6 +276,12 @@ impl InstructionValue { } self } + + pub fn add_record(&self, block: &mut Block, record: InstructionDebugRecordData) { + unsafe { + block.builder.add_instruction_record(self, record); + } + } } #[derive(Clone)] diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 4d0169a..d5929a3 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -5,9 +5,9 @@ use reid_lib::{ compile::CompiledModule, debug_information::{ DebugBasicType, DebugFileData, DebugInformation, DebugLocalVariable, DebugLocation, - DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugProgramValue, DebugScopeValue, - DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramTypeData, DebugTypeData, - DebugTypeValue, DwarfEncoding, DwarfFlags, + DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugProgramValue, DebugRecordKind, + DebugScopeValue, DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramTypeData, + DebugTypeData, DebugTypeValue, DwarfEncoding, DwarfFlags, InstructionDebugRecordData, }, Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, NamedStruct, TerminatorKind as Term, Type, @@ -106,6 +106,16 @@ pub enum StackValueKind { Any(InstructionValue), } +impl StackValueKind { + unsafe fn get_inner(&self) -> InstructionValue { + match &self { + StackValueKind::Immutable(val) => *val, + StackValueKind::Mutable(val) => *val, + StackValueKind::Any(val) => *val, + } + } +} + impl<'ctx, 'a> Scope<'ctx, 'a> { fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> { Scope { @@ -403,56 +413,70 @@ impl mir::Statement { match &self.0 { mir::StmtKind::Let(NamedVariableRef(ty, name, _), mutable, expression) => { let value = expression.codegen(scope, &state).unwrap(); + let (stack_value, store) = match mutable { + false => (StackValueKind::Immutable(value), value), + true => match ty { + // Struct is already allocated at initialization + TypeKind::Array(_, _) => (StackValueKind::Mutable(value), value), + TypeKind::CustomType(n) => { + match scope.types.get(scope.type_values.get(n).unwrap()).unwrap() { + // Struct also is allocated at initialization + TypeDefinitionKind::Struct(_) => { + (StackValueKind::Mutable(value), value) + } + } + } + _ => { + let alloca = scope + .block + .build(Instr::Alloca( + name.clone(), + ty.get_type(scope.type_values, scope.types), + )) + .unwrap() + .maybe_location(&mut scope.block, location); + let store = scope + .block + .build(Instr::Store(alloca, value)) + .unwrap() + .maybe_location(&mut scope.block, location); + (StackValueKind::Mutable(alloca), store) + } + }, + }; scope.stack_values.insert( name.clone(), - StackValue( - match mutable { - false => StackValueKind::Immutable(value), - true => match ty { - // Struct is already allocated at initialization - TypeKind::Array(_, _) => StackValueKind::Mutable(value), - TypeKind::CustomType(n) => match scope - .types - .get(scope.type_values.get(n).unwrap()) - .unwrap() - { - // Struct also is allocated at initialization - TypeDefinitionKind::Struct(_) => StackValueKind::Mutable(value), - }, - _ => StackValueKind::Mutable({ - let alloca = scope - .block - .build(Instr::Alloca( - name.clone(), - ty.get_type(scope.type_values, scope.types), - )) - .unwrap() - .maybe_location(&mut scope.block, location); - scope - .block - .build(Instr::Store(alloca, value)) - .unwrap() - .maybe_location(&mut scope.block, location); - alloca - }), - }, - }, - ty.get_type(scope.type_values, scope.types), - ), + StackValue(stack_value, ty.get_type(scope.type_values, scope.types)), ); if let Some(debug) = &scope.debug { - let location = self.1.into_debug(scope.tokens).unwrap(); - debug.info.metadata( - &debug.scope, - DebugMetadata::LocalVar(DebugLocalVariable { - name: name.clone(), - location, - ty: scope.debug_const_tys.get(&TypeKind::U32).unwrap().clone(), - always_preserve: true, - alignment: 32, - flags: DwarfFlags, - }), - ); + match stack_value { + StackValueKind::Immutable(_) => {} + StackValueKind::Mutable(_) => { + let location = self.1.into_debug(scope.tokens).unwrap(); + let var = debug.info.metadata( + &debug.scope, + DebugMetadata::LocalVar(DebugLocalVariable { + name: name.clone(), + location, + ty: scope.debug_const_tys.get(&TypeKind::U32).unwrap().clone(), + always_preserve: true, + alignment: 32, + flags: DwarfFlags, + }), + ); + dbg!(&store); + store.add_record( + &mut scope.block, + InstructionDebugRecordData { + variable: var, + location, + kind: DebugRecordKind::Declare(value), + scope: debug.scope, + }, + ); + } + StackValueKind::Any(_) => {} + } } None }