From 81ce1dfc2e80b232eb2c63c6af7a2827688a5adf Mon Sep 17 00:00:00 2001 From: sofia Date: Tue, 22 Jul 2025 19:16:45 +0300 Subject: [PATCH] Fix a bunch of bugs with debug information and stuff --- reid-llvm-lib/src/builder.rs | 5 +- reid-llvm-lib/src/compile.rs | 26 +- reid-llvm-lib/src/debug_information.rs | 11 +- reid-llvm-lib/src/fmt.rs | 22 +- reid-llvm-lib/src/lib.rs | 2 +- reid/src/codegen.rs | 343 ++++++++++++++----------- 6 files changed, 236 insertions(+), 173 deletions(-) diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 47c3c3b..a614d08 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -389,6 +389,7 @@ impl Builder { return Err(()); // TODO error: invalid amount of params } for (a, b) in param_types.iter().zip(params) { + dbg!(&a, &b.get_type(&self)); if *a != b.get_type(&self)? { return Err(()); // TODO error: params do not match } @@ -478,7 +479,7 @@ impl Builder { Instr::SIToFP(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), - Instr::BitCast(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), + Instr::BitCast(instr, ty) => Ok(()), } } } @@ -628,7 +629,7 @@ impl InstructionValue { SIToFP(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), PtrToInt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), - BitCast(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), + BitCast(_, ty) => Ok(ty.clone()), } } } diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 0ae77c3..8c3a3ee 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -376,8 +376,8 @@ impl DebugLocationHolder { unsafe { LLVMDIBuilderCreateDebugLocation( context.context_ref, - self.location.line, - self.location.column, + self.location.pos.line, + self.location.pos.column, *debug.programs.get(&self.program).unwrap(), null_mut(), ) @@ -399,8 +399,8 @@ impl DebugScopeHolder { di_builder, parent, file, - location.line, - location.column, + location.pos.line, + location.pos.column, ) } else { LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) @@ -426,7 +426,7 @@ impl DebugMetadataHolder { param.name.len(), param.arg_idx + 1, debug.file_ref, - self.location.line, + self.location.pos.line, *debug.types.get(¶m.ty).unwrap(), param.always_preserve as i32, param.flags.as_llvm(), @@ -437,7 +437,7 @@ impl DebugMetadataHolder { into_cstring(var.name.clone()).as_ptr(), var.name.len(), debug.file_ref, - self.location.line, + self.location.pos.line, *debug.types.get(&var.ty).unwrap(), var.always_preserve as i32, var.flags.as_llvm(), @@ -504,11 +504,11 @@ impl DebugTypeHolder { .map(|field| { LLVMDIBuilderCreateMemberType( debug.builder, - *debug.programs.get(&st.location.scope).unwrap(), + *debug.programs.get(&st.scope).unwrap(), into_cstring(field.name.clone()).as_ptr(), field.name.len(), debug.file_ref, - field.location.line, + field.pos.map(|p| p.line).unwrap_or(1), field.size_bits, 0, 1, @@ -519,11 +519,11 @@ impl DebugTypeHolder { .collect::>(); LLVMDIBuilderCreateStructType( debug.builder, - *debug.programs.get(&st.location.scope).unwrap(), + *debug.programs.get(&st.scope).unwrap(), into_cstring(st.name.clone()).as_ptr(), st.name.len(), debug.file_ref, - st.location.line, + st.pos.map(|p| p.line).unwrap_or(1), st.size_bits, 0, st.flags.as_llvm(), @@ -617,7 +617,7 @@ impl FunctionHolder { mangled_name, mangled_length, debug.file_ref, - subprogram.location.line, + subprogram.location.pos.line, *debug.types.get(&subprogram.ty).unwrap(), subprogram.opts.is_local as i32, subprogram.opts.is_definition as i32, @@ -1027,8 +1027,8 @@ impl InstructionHolder { let location = LLVMDIBuilderCreateDebugLocation( module.context_ref, - record.location.line, - record.location.column, + record.location.pos.line, + record.location.pos.column, *debug.programs.get(&record.scope).unwrap(), null_mut(), ); diff --git a/reid-llvm-lib/src/debug_information.rs b/reid-llvm-lib/src/debug_information.rs index a9046cf..0efb7d8 100644 --- a/reid-llvm-lib/src/debug_information.rs +++ b/reid-llvm-lib/src/debug_information.rs @@ -225,6 +225,11 @@ impl DebugInformation { #[derive(Clone, Copy)] pub struct DebugLocation { pub scope: DebugProgramValue, + pub pos: DebugPosition, +} + +#[derive(Clone, Copy)] +pub struct DebugPosition { pub line: u32, pub column: u32, } @@ -310,7 +315,8 @@ pub struct DebugPointerType { #[derive(Clone)] pub struct DebugStructType { pub name: String, - pub location: DebugLocation, + pub scope: DebugProgramValue, + pub pos: Option, pub size_bits: u64, pub flags: DwarfFlags, pub fields: Vec, @@ -319,7 +325,8 @@ pub struct DebugStructType { #[derive(Clone)] pub struct DebugFieldType { pub name: String, - pub location: DebugLocation, + pub scope: DebugProgramValue, + pub pos: Option, pub size_bits: u64, pub offset: u64, pub flags: DwarfFlags, diff --git a/reid-llvm-lib/src/fmt.rs b/reid-llvm-lib/src/fmt.rs index ca9d4aa..aefea50 100644 --- a/reid-llvm-lib/src/fmt.rs +++ b/reid-llvm-lib/src/fmt.rs @@ -11,8 +11,8 @@ use crate::{ debug_information::{ DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, - DebugPointerType, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugStructType, - DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, + DebugPointerType, DebugPosition, DebugProgramValue, DebugRecordKind, DebugScopeValue, + DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, }, pad_adapter::PadAdapter, }; @@ -171,6 +171,12 @@ impl DebugMetadataValue { } impl Display for DebugLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?} on scope {:?}", self.pos, self.scope) + } +} + +impl Display for DebugPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "line {}, col {}", self.line, self.column) } @@ -484,7 +490,8 @@ impl Debug for DebugStructType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Struct") .field("name", &self.name) - .field("location", &self.location) + .field("scope", &self.scope) + .field("pos", &self.pos) .field("size_bit", &self.size_bits) .field("flags", &self.flags) .field("elements", &self.fields) @@ -495,7 +502,8 @@ impl Debug for DebugStructType { impl Debug for DebugFieldType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct(&format!("Field({})", self.name)) - .field("location", &self.location) + .field("scope", &self.scope) + .field("pos", &self.pos) .field("size_bits", &self.size_bits) .field("offset", &self.offset) .field("flags", &self.flags) @@ -569,6 +577,12 @@ impl Debug for DebugLocationValue { } impl Debug for DebugLocation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?} on scope {:?}", self.pos, self.scope) + } +} + +impl Debug for DebugPosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ln {}, col {}", self.line, self.column) } diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 2b966bc..c616225 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -521,7 +521,7 @@ impl ConstValue { ConstValue::U32(_) => U32, ConstValue::U64(_) => U64, ConstValue::U128(_) => U128, - ConstValue::Str(_) => Type::Ptr(Box::new(I8)), + ConstValue::Str(_) => Type::Ptr(Box::new(U8)), ConstValue::Bool(_) => Bool, ConstValue::F16(_) => F16, ConstValue::F32B(_) => F32B, diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 1b74b4f..b9fa801 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -6,7 +6,7 @@ use reid_lib::{ debug_information::{ DebugArrayType, DebugBasicType, DebugFieldType, DebugFileData, DebugInformation, DebugLocalVariable, DebugLocation, DebugMetadata, DebugParamVariable, DebugPointerType, - DebugProgramValue, DebugRecordKind, DebugStructType, DebugSubprogramData, + DebugPosition, DebugProgramValue, DebugRecordKind, DebugStructType, DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DebugTypeValue, DwarfEncoding, DwarfFlags, InstructionDebugRecordData, }, @@ -57,6 +57,8 @@ impl mir::Context { #[derive(Clone)] struct ModuleCodegen<'ctx> { module: Module<'ctx>, + tokens: &'ctx Vec, + debug_types: Option>, type_values: HashMap, } @@ -194,7 +196,7 @@ impl Default for State { impl mir::Module { fn codegen<'ctx>( - &self, + &'ctx self, context: &'ctx Context, modules: HashMap>, ) -> ModuleCodegen<'ctx> { @@ -227,7 +229,9 @@ impl mir::Module { &debug_types, &type_values, &types, - tokens, + self.module_id, + &self.tokens, + &modules, ), ) }; @@ -247,29 +251,23 @@ impl mir::Module { insert_debug!(&TypeKind::Void); insert_debug!(&TypeKind::Char); - for typedef in &self.typedefs { + let mut typedefs = self.typedefs.clone(); + typedefs.sort_by(|a, b| b.source_module.cmp(&a.source_module)); + + for typedef in typedefs { let type_key = TypeKey(typedef.name.clone(), typedef.source_module); - let type_value = if typedef.source_module != self.module_id { - *modules - .get(&typedef.source_module) - .unwrap() - .type_values - .get(&type_key) - .unwrap() - } else { - match &typedef.kind { - TypeDefinitionKind::Struct(StructType(fields)) => { - module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( - typedef.name.clone(), - fields - .iter() - // TODO: Reorder custom-type definitions such that - // inner types get evaluated first. Otherwise this - // will cause a panic! - .map(|StructField(_, t, _)| t.get_type(&type_values, &types)) - .collect(), - ))) - } + let type_value = match &typedef.kind { + TypeDefinitionKind::Struct(StructType(fields)) => { + module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( + typedef.name.clone(), + fields + .iter() + // TODO: Reorder custom-type definitions such that + // inner types get evaluated first. Otherwise this + // will cause a panic! + .map(|StructField(_, t, _)| t.get_type(&type_values, &types)) + .collect(), + ))) } }; types.insert(type_value, typedef.clone()); @@ -316,120 +314,128 @@ impl mir::Module { for mir_function in &self.functions { let function = functions.get(&mir_function.name).unwrap(); - let mut entry = function.ir.block("entry"); - - // Insert debug information - let debug_scope = if let Some(location) = - mir_function.signature().into_debug(tokens, compile_unit) - { - // let debug_scope = debug.inner_scope(&outer_scope, location); - - let fn_param_ty = &mir_function.return_type.get_debug_type_hard( - compile_unit, - &debug, - &debug_types, - &type_values, - &types, - tokens, - ); - - let debug_ty = debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramType { - 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 - }; - - // 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 - let arg_name = format!("arg.{}", p_name); - let param = entry - .build_named(format!("{}.get", arg_name), Instr::Param(i)) - .unwrap(); - let alloca = entry - .build_named( - &arg_name, - Instr::Alloca(p_ty.get_type(&type_values, &types)), - ) - .unwrap(); - entry - .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) - .unwrap(); - stack_values.insert( - p_name.clone(), - StackValue( - StackValueKind::mutable(p_ty.is_mutable(), alloca), - TypeKind::CodegenPtr(Box::new(p_ty.clone())), - ), - ); - - // Generate debug info - if let (Some(debug_scope), Some(location)) = ( - &debug_scope, - mir_function.signature().into_debug(tokens, compile_unit), - ) { - debug.metadata( - &location, - DebugMetadata::ParamVar(DebugParamVariable { - name: p_name.clone(), - arg_idx: i as u32, - ty: p_ty.get_debug_type_hard( - *debug_scope, - &debug, - &debug_types, - &type_values, - &types, - tokens, - ), - always_preserve: true, - flags: DwarfFlags, - }), - ); - } - } - - let mut scope = Scope { - context, - modules: &modules, - tokens, - module: &module, - module_id: self.module_id, - function, - block: entry, - functions: &functions, - types: &types, - type_values: &type_values, - stack_values, - debug: debug_scope.and_then(|scope| { - Some(Debug { - info: &debug, - scope, - types: &debug_types, - }) - }), - }; match &mir_function.kind { mir::FunctionDefinitionKind::Local(block, _) => { + let mut entry = function.ir.block("entry"); + + // Insert debug information + let debug_scope = if let Some(location) = + mir_function.signature().into_debug(tokens, compile_unit) + { + // let debug_scope = debug.inner_scope(&outer_scope, location); + + let fn_param_ty = &mir_function.return_type.get_debug_type_hard( + compile_unit, + &debug, + &debug_types, + &type_values, + &types, + self.module_id, + &self.tokens, + &modules, + ); + + let debug_ty = + debug.debug_type(DebugTypeData::Subprogram(DebugSubprogramType { + 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 + }; + + // 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 + let arg_name = format!("arg.{}", p_name); + let param = entry + .build_named(format!("{}.get", arg_name), Instr::Param(i)) + .unwrap(); + let alloca = entry + .build_named( + &arg_name, + Instr::Alloca(p_ty.get_type(&type_values, &types)), + ) + .unwrap(); + entry + .build_named(format!("{}.store", arg_name), Instr::Store(alloca, param)) + .unwrap(); + stack_values.insert( + p_name.clone(), + StackValue( + StackValueKind::mutable(p_ty.is_mutable(), alloca), + TypeKind::CodegenPtr(Box::new(p_ty.clone())), + ), + ); + + // Generate debug info + if let (Some(debug_scope), Some(location)) = ( + &debug_scope, + mir_function.signature().into_debug(tokens, compile_unit), + ) { + dbg!(mir_function.name.clone()); + dbg!(p_name.clone()); + // debug.metadata( + // &location, + // DebugMetadata::ParamVar(DebugParamVariable { + // name: p_name.clone(), + // arg_idx: i as u32, + // ty: p_ty.get_debug_type_hard( + // *debug_scope, + // &debug, + // &debug_types, + // &type_values, + // &types, + // self.module_id, + // &self.tokens, + // &modules, + // ), + // always_preserve: true, + // flags: DwarfFlags, + // }), + // ); + } + } + + let mut scope = Scope { + context, + modules: &modules, + tokens, + module: &module, + module_id: self.module_id, + function, + block: entry, + functions: &functions, + types: &types, + type_values: &type_values, + stack_values, + debug: debug_scope.and_then(|scope| { + Some(Debug { + info: &debug, + scope, + types: &debug_types, + }) + }), + }; + let state = State::default(); if let Some(ret) = block.codegen(&mut scope, &state) { scope.block.terminate(Term::Ret(ret.instr())).unwrap(); @@ -454,7 +460,9 @@ impl mir::Module { ModuleCodegen { module, + debug_types: Some(debug_types), type_values, + tokens: &self.tokens, } } } @@ -680,8 +688,9 @@ impl mir::Expression { let params = call .parameters .iter() - .map(|e| e.codegen(scope, &mut state.load(true)).unwrap().instr()) - .collect(); + .map(|e| e.codegen(scope, state).unwrap()) + .collect::>(); + let param_instrs = params.iter().map(|e| e.instr()).collect(); let callee = scope .functions .get(&call.name) @@ -691,7 +700,7 @@ impl mir::Expression { .block .build_named( call.name.clone(), - Instr::FunctionCall(callee.ir.value(), params), + Instr::FunctionCall(callee.ir.value(), param_instrs), ) .unwrap(); @@ -769,7 +778,6 @@ impl mir::Expression { }; let (ptr, contained_ty) = if let TypeKind::UserPtr(further_inner) = *inner.clone() { - dbg!(&further_inner, &val_t); let loaded = scope .block .build_named( @@ -806,7 +814,6 @@ impl mir::Expression { }; if state.should_load { - dbg!(&contained_ty); Some(StackValue( kind.derive( scope @@ -900,7 +907,6 @@ impl mir::Expression { mir::ExprKind::Accessed(expression, type_kind, field) => { let struct_val = expression.codegen(scope, &state.load(false)).unwrap(); - dbg!(&expression, &struct_val); let TypeKind::CodegenPtr(inner) = &struct_val.1 else { panic!("tried accessing non-pointer"); }; @@ -1049,7 +1055,7 @@ impl mir::Expression { }; StackValue( StackValueKind::mutable(mutable, var_ptr_instr), - *borrow_inner.clone(), + TypeKind::CodegenPtr(borrow_inner.clone()), ) } }) @@ -1059,7 +1065,18 @@ impl mir::Expression { if val.1 == *type_kind { Some(val) } else if let (TypeKind::UserPtr(_), TypeKind::UserPtr(_)) = (&val.1, type_kind) { - Some(val) + Some(StackValue( + val.0.derive( + scope + .block + .build(Instr::BitCast( + val.instr(), + type_kind.get_type(scope.type_values, scope.types), + )) + .unwrap(), + ), + type_kind.clone(), + )) } else { let cast_instr = val .1 @@ -1262,7 +1279,7 @@ impl TypeKind { TypeKind::F128 => Type::F128, TypeKind::F80 => Type::F80, TypeKind::F128PPC => Type::F128PPC, - TypeKind::Char => Type::I8, + TypeKind::Char => Type::U8, TypeKind::Array(elem_t, len) => { Type::Array(Box::new(elem_t.get_type(type_vals, typedefs)), *len) } @@ -1293,7 +1310,9 @@ impl TypeKind { debug.types, scope.type_values, scope.types, + scope.module_id, scope.tokens, + scope.modules, ) } @@ -1304,7 +1323,9 @@ impl TypeKind { debug_types: &HashMap, type_values: &HashMap, types: &HashMap, + local_mod: SourceModuleId, tokens: &Vec, + modules: &HashMap, ) -> DebugTypeValue { if let Some(ty) = debug_types.get(self) { return *ty; @@ -1322,7 +1343,9 @@ impl TypeKind { debug_types, type_values, types, + local_mod, tokens, + modules, ), size_bits: self.size_of(), }) @@ -1334,7 +1357,9 @@ impl TypeKind { debug_types, type_values, types, + local_mod, tokens, + modules, ); DebugTypeData::Array(DebugArrayType { size_bits: self.size_of(), @@ -1345,15 +1370,21 @@ impl TypeKind { } TypeKind::CustomType(key) => { let typedef = types.get(type_values.get(key).unwrap()).unwrap(); - match &typedef.kind { TypeDefinitionKind::Struct(struct_type) => { let mut fields = Vec::new(); let mut size_bits = 0; + for field in &struct_type.0 { + let location = if typedef.source_module != local_mod { + None + } else { + field.2.into_debug(&tokens, scope) + }; fields.push(DebugFieldType { name: field.0.clone(), - location: field.2.into_debug(tokens, scope).unwrap(), + scope, + pos: location.map(|l| l.pos), size_bits: field.1.size_of(), offset: size_bits, flags: DwarfFlags, @@ -1363,15 +1394,23 @@ impl TypeKind { debug_types, type_values, types, + local_mod, tokens, + modules, ), }); size_bits += field.1.size_of(); } { + let location = if typedef.source_module != local_mod { + None + } else { + typedef.meta.into_debug(&tokens, scope) + }; DebugTypeData::Struct(DebugStructType { name: key.0.clone(), - location: typedef.meta.into_debug(tokens, scope).unwrap(), + scope, + pos: location.map(|l| l.pos), size_bits, flags: DwarfFlags, fields, @@ -1422,7 +1461,7 @@ impl Metadata { if let Some((start, _)) = self.into_positions(tokens) { Some(start.debug(scope)) } else { - Some(Position(0, 0).debug(scope)) + None } } } @@ -1430,8 +1469,10 @@ impl Metadata { impl Position { fn debug(self, scope: DebugProgramValue) -> DebugLocation { DebugLocation { - line: self.1, - column: self.0, + pos: DebugPosition { + line: self.1, + column: self.0, + }, scope, } }