diff --git a/reid-llvm-lib/Cargo.toml b/reid-llvm-lib/Cargo.toml index 2e22a76..dc31a3b 100644 --- a/reid-llvm-lib/Cargo.toml +++ b/reid-llvm-lib/Cargo.toml @@ -7,6 +7,6 @@ edition = "2024" [dependencies] ## LLVM Bindings -llvm-sys = {version ="201.0.1", features=["force-static"] } +llvm-sys = {version ="201.0.1", features=["prefer-dynamic"] } ## Make it easier to generate errors thiserror = "1.0.44" \ No newline at end of file diff --git a/reid/src/allocator.rs b/reid/src/codegen/allocator.rs similarity index 100% rename from reid/src/allocator.rs rename to reid/src/codegen/allocator.rs diff --git a/reid/src/intrinsics.rs b/reid/src/codegen/intrinsics.rs similarity index 96% rename from reid/src/intrinsics.rs rename to reid/src/codegen/intrinsics.rs index 4cc42c3..99c5cea 100644 --- a/reid/src/intrinsics.rs +++ b/reid/src/codegen/intrinsics.rs @@ -1,10 +1,12 @@ use reid_lib::{builder::InstructionValue, Instr}; use crate::{ - codegen::{ErrorKind, Scope, StackValue, StackValueKind}, + codegen::{ErrorKind, StackValueKind}, mir::{BinopDefinition, FunctionDefinition, TypeKind}, }; +use super::scope::{Scope, StackValue}; + pub fn form_intrinsics() -> Vec { let intrinsics = Vec::new(); diff --git a/reid/src/codegen.rs b/reid/src/codegen/mod.rs similarity index 78% rename from reid/src/codegen.rs rename to reid/src/codegen/mod.rs index 402de11..1326944 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen/mod.rs @@ -1,31 +1,33 @@ -use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use allocator::{Allocator, AllocatorScope}; +use intrinsics::*; use reid_lib::{ - builder::{InstructionValue, TypeValue}, compile::CompiledModule, debug_information::{ - DebugArrayType, DebugBasicType, DebugFieldType, DebugFileData, DebugInformation, - DebugLocalVariable, DebugLocation, DebugMetadata, DebugPointerType, DebugPosition, - DebugProgramValue, DebugRecordKind, DebugStructType, DebugSubprogramData, - DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DebugTypeValue, - DwarfEncoding, DwarfFlags, InstructionDebugRecordData, + DebugFileData, DebugLocalVariable, DebugLocation, DebugMetadata, DebugRecordKind, + DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, + DwarfFlags, InstructionDebugRecordData, }, - Block, CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, - Module, NamedStruct, TerminatorKind as Term, Type, + CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, + NamedStruct, TerminatorKind as Term, Type, }; +use scope::*; use crate::{ - allocator::{Allocator, AllocatorScope}, - intrinsics::IntrinsicFunction, - lexer::{FullToken, Position}, mir::{ self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, - Metadata, NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinition, - TypeDefinitionKind, TypeKind, VagueLiteral, WhileStatement, + NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinitionKind, TypeKind, + WhileStatement, }, util::try_all, }; +mod allocator; +pub mod intrinsics; +pub(super) mod scope; +pub(super) mod util; + #[derive(thiserror::Error, Debug, Clone, PartialEq, PartialOrd)] pub enum ErrorKind { #[error("NULL error, should never occur!")] @@ -73,160 +75,6 @@ impl<'ctx> std::fmt::Debug for ModuleCodegen<'ctx> { } } -pub struct Scope<'ctx, 'scope> { - context: &'ctx Context, - modules: &'scope HashMap>, - tokens: &'ctx Vec, - module: &'ctx Module<'ctx>, - module_id: SourceModuleId, - function: &'ctx Function<'ctx>, - pub(super) block: Block<'ctx>, - types: &'scope HashMap, - type_values: &'scope HashMap, - functions: &'scope HashMap>, - binops: &'scope HashMap>, - stack_values: HashMap, - debug: Option>, - allocator: Rc>, -} - -impl<'ctx, 'a> Scope<'ctx, 'a> { - fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> { - Scope { - block, - modules: self.modules, - tokens: self.tokens, - function: self.function, - context: self.context, - module: self.module, - module_id: self.module_id, - functions: self.functions, - types: self.types, - type_values: self.type_values, - stack_values: self.stack_values.clone(), - debug: self.debug.clone(), - allocator: self.allocator.clone(), - binops: self.binops, - } - } - - /// Takes the block out from this scope, swaps the given block in it's place - /// and returns the old block. - fn swap_block(&mut self, block: Block<'ctx>) -> Block<'ctx> { - let mut old_block = block; - mem::swap(&mut self.block, &mut old_block); - old_block - } - - fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> { - self.type_values.get(key).and_then(|v| self.types.get(v)) - } - - fn allocate(&self, name: &String, ty: &TypeKind) -> Option { - self.allocator.borrow_mut().allocate(name, ty) - } -} - -#[derive(Debug, Clone)] -pub struct Debug<'ctx> { - info: &'ctx DebugInformation, - scope: DebugProgramValue, - types: &'ctx HashMap, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct StackValue(pub(super) StackValueKind, pub(super) TypeKind); - -impl StackValue { - fn instr(&self) -> InstructionValue { - self.0.instr() - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum StackValueKind { - Immutable(InstructionValue), - Mutable(InstructionValue), - Literal(InstructionValue), -} - -impl StackValueKind { - fn mutable(mutable: bool, instr: InstructionValue) -> StackValueKind { - match mutable { - true => StackValueKind::Mutable(instr), - false => StackValueKind::Immutable(instr), - } - } - - fn instr(&self) -> InstructionValue { - match &self { - StackValueKind::Immutable(val) => *val, - StackValueKind::Mutable(val) => *val, - StackValueKind::Literal(val) => *val, - } - } - - fn derive(&self, instr: InstructionValue) -> StackValueKind { - match &self { - StackValueKind::Immutable(_) => StackValueKind::Immutable(instr), - StackValueKind::Mutable(_) => StackValueKind::Mutable(instr), - StackValueKind::Literal(_) => StackValueKind::Literal(instr), - } - } - - #[allow(dead_code)] - fn map(&self, lambda: F) -> StackValueKind - where - F: FnOnce(InstructionValue) -> InstructionValue, - { - self.derive(lambda(self.instr())) - } -} - -pub struct StackBinopDefinition<'ctx> { - parameters: ((String, TypeKind), (String, TypeKind)), - return_ty: TypeKind, - kind: StackBinopFunctionKind<'ctx>, -} - -pub enum StackBinopFunctionKind<'ctx> { - UserGenerated(Function<'ctx>), - Intrinsic(&'ctx Box), -} - -impl<'ctx> StackBinopDefinition<'ctx> { - fn codegen<'a>( - &self, - lhs: &StackValue, - rhs: &StackValue, - scope: &mut Scope<'ctx, 'a>, - ) -> Result { - let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { - (lhs, rhs) - } else { - (rhs, lhs) - }; - match &self.kind { - StackBinopFunctionKind::UserGenerated(ir) => { - let instr = scope - .block - .build(Instr::FunctionCall( - ir.value(), - vec![lhs.instr(), rhs.instr()], - )) - .unwrap(); - Ok(StackValue( - StackValueKind::Immutable(instr), - self.return_ty.clone(), - )) - } - StackBinopFunctionKind::Intrinsic(fun) => { - fun.codegen(scope, &[lhs.instr(), rhs.instr()]) - } - } - } -} - #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] struct State { should_load: bool, @@ -1567,262 +1415,3 @@ impl mir::IfExpression { } } } -impl mir::CmpOperator { - fn predicate(&self) -> CmpPredicate { - match self { - mir::CmpOperator::LT => CmpPredicate::LT, - mir::CmpOperator::GT => CmpPredicate::GT, - mir::CmpOperator::LE => CmpPredicate::LE, - mir::CmpOperator::GE => CmpPredicate::GE, - mir::CmpOperator::EQ => CmpPredicate::EQ, - mir::CmpOperator::NE => CmpPredicate::NE, - } - } -} - -impl mir::Literal { - fn as_const(&self, block: &mut Block) -> InstructionValue { - block - .build_named(format!("{}", self), self.as_const_kind()) - .unwrap() - } - - fn as_const_kind(&self) -> Instr { - Instr::Constant(match self.clone() { - mir::Literal::I8(val) => ConstValue::I8(val), - mir::Literal::I16(val) => ConstValue::I16(val), - mir::Literal::I32(val) => ConstValue::I32(val), - mir::Literal::I64(val) => ConstValue::I64(val), - mir::Literal::I128(val) => ConstValue::I128(val), - mir::Literal::U8(val) => ConstValue::U8(val), - mir::Literal::U16(val) => ConstValue::U16(val), - mir::Literal::U32(val) => ConstValue::U32(val), - mir::Literal::U64(val) => ConstValue::U64(val), - mir::Literal::U128(val) => ConstValue::U128(val), - mir::Literal::Bool(val) => ConstValue::Bool(val), - mir::Literal::String(val) => ConstValue::Str(val.clone()), - mir::Literal::Vague(VagueLiteral::Number(val)) => ConstValue::I32(val as i32), - mir::Literal::Vague(VagueLiteral::Decimal(val)) => ConstValue::F32(val as f32), - mir::Literal::F16(val) => ConstValue::F16(val), - mir::Literal::F32B(val) => ConstValue::F32B(val), - mir::Literal::F32(val) => ConstValue::F32(val), - mir::Literal::F64(val) => ConstValue::F64(val), - mir::Literal::F80(val) => ConstValue::F80(val), - mir::Literal::F128(val) => ConstValue::F128(val), - mir::Literal::F128PPC(val) => ConstValue::F128PPC(val), - mir::Literal::Char(c) => ConstValue::U8(c as u8), - }) - } -} - -impl TypeKind { - pub(super) fn get_type(&self, type_vals: &HashMap) -> Type { - match &self { - TypeKind::I8 => Type::I8, - TypeKind::I16 => Type::I16, - TypeKind::I32 => Type::I32, - TypeKind::I64 => Type::I64, - TypeKind::I128 => Type::I128, - TypeKind::U8 => Type::U8, - TypeKind::U16 => Type::U16, - TypeKind::U32 => Type::U32, - TypeKind::U64 => Type::U64, - TypeKind::U128 => Type::U128, - TypeKind::Bool => Type::Bool, - TypeKind::F16 => Type::F16, - TypeKind::F32B => Type::F32B, - TypeKind::F32 => Type::F32, - TypeKind::F64 => Type::F64, - TypeKind::F128 => Type::F128, - TypeKind::F80 => Type::F80, - TypeKind::F128PPC => Type::F128PPC, - TypeKind::Char => Type::U8, - TypeKind::Array(elem_t, len) => Type::Array(Box::new(elem_t.get_type(type_vals)), *len), - TypeKind::Void => Type::Void, - TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), - TypeKind::CustomType(n) => { - let type_val = type_vals.get(n).unwrap().clone(); - Type::CustomType(type_val) - } - TypeKind::UserPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), - TypeKind::CodegenPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), - TypeKind::Borrow(type_kind, _) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), - } - } -} - -impl TypeKind { - fn get_debug_type(&self, debug: &Debug, scope: &Scope) -> DebugTypeValue { - self.get_debug_type_hard( - debug.scope, - debug.info, - debug.types, - scope.type_values, - scope.types, - scope.module_id, - scope.tokens, - scope.modules, - ) - } - - fn get_debug_type_hard( - &self, - scope: DebugProgramValue, - debug_info: &DebugInformation, - 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; - } - - let name = format!("{}", self); - - let data = match self { - TypeKind::CodegenPtr(inner) | TypeKind::UserPtr(inner) | TypeKind::Borrow(inner, _) => { - DebugTypeData::Pointer(DebugPointerType { - name, - pointee: inner.get_debug_type_hard( - scope, - debug_info, - debug_types, - type_values, - types, - local_mod, - tokens, - modules, - ), - size_bits: self.size_of(), - }) - } - TypeKind::Array(elem_ty, len) => { - let elem_ty = elem_ty.clone().get_debug_type_hard( - scope, - debug_info, - debug_types, - type_values, - types, - local_mod, - tokens, - modules, - ); - DebugTypeData::Array(DebugArrayType { - size_bits: self.size_of(), - align_bits: self.alignment(), - element_type: elem_ty, - length: *len, - }) - } - 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(), - scope, - pos: location.map(|l| l.pos), - size_bits: field.1.size_of(), - offset: size_bits, - flags: DwarfFlags, - ty: field.1.get_debug_type_hard( - scope, - debug_info, - 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(), - scope, - pos: location.map(|l| l.pos), - size_bits, - flags: DwarfFlags, - fields, - }) - } - } - } - } - _ => DebugTypeData::Basic(DebugBasicType { - name, - size_bits: self.size_of(), - encoding: match self { - TypeKind::Bool => DwarfEncoding::Boolean, - TypeKind::I8 => DwarfEncoding::SignedChar, - TypeKind::U8 => DwarfEncoding::UnsignedChar, - TypeKind::I16 | TypeKind::I32 | TypeKind::I64 | TypeKind::I128 => { - DwarfEncoding::Signed - } - TypeKind::U16 | TypeKind::U32 | TypeKind::U64 | TypeKind::U128 => { - DwarfEncoding::Unsigned - } - TypeKind::F16 - | TypeKind::F32 - | TypeKind::F32B - | TypeKind::F64 - | TypeKind::F80 - | TypeKind::F128 - | TypeKind::F128PPC => DwarfEncoding::Float, - TypeKind::Void => DwarfEncoding::Address, - TypeKind::Char => DwarfEncoding::UnsignedChar, - TypeKind::Array(_, _) => DwarfEncoding::Address, - TypeKind::CustomType(_) => DwarfEncoding::Address, - _ => panic!("tried fetching debug-type for non-supported type!"), - }, - flags: DwarfFlags, - }), - }; - debug_info.debug_type(data) - } -} - -impl Metadata { - pub fn into_debug( - &self, - tokens: &Vec, - scope: DebugProgramValue, - ) -> Option { - if let Some((start, _)) = self.into_positions(tokens) { - Some(start.debug(scope)) - } else { - None - } - } -} - -impl Position { - fn debug(self, scope: DebugProgramValue) -> DebugLocation { - DebugLocation { - pos: DebugPosition { - line: self.1, - column: self.0, - }, - scope, - } - } -} diff --git a/reid/src/codegen/scope.rs b/reid/src/codegen/scope.rs new file mode 100644 index 0000000..5121a8f --- /dev/null +++ b/reid/src/codegen/scope.rs @@ -0,0 +1,168 @@ +use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; + +use reid_lib::{ + builder::{InstructionValue, TypeValue}, + debug_information::{DebugInformation, DebugProgramValue, DebugTypeValue}, + Block, Context, Function, Instr, Module, +}; + +use crate::{ + lexer::FullToken, + mir::{pass::ScopeBinopKey, CustomTypeKey, SourceModuleId, TypeDefinition, TypeKind}, +}; + +use super::{allocator::Allocator, ErrorKind, IntrinsicFunction, ModuleCodegen}; + +pub struct Scope<'ctx, 'scope> { + pub(super) context: &'ctx Context, + pub(super) modules: &'scope HashMap>, + pub(super) tokens: &'ctx Vec, + pub(super) module: &'ctx Module<'ctx>, + pub(super) module_id: SourceModuleId, + pub(super) function: &'ctx Function<'ctx>, + pub(super) block: Block<'ctx>, + pub(super) types: &'scope HashMap, + pub(super) type_values: &'scope HashMap, + pub(super) functions: &'scope HashMap>, + pub(super) binops: &'scope HashMap>, + pub(super) stack_values: HashMap, + pub(super) debug: Option>, + pub(super) allocator: Rc>, +} + +impl<'ctx, 'a> Scope<'ctx, 'a> { + pub fn with_block(&self, block: Block<'ctx>) -> Scope<'ctx, 'a> { + Scope { + block, + modules: self.modules, + tokens: self.tokens, + function: self.function, + context: self.context, + module: self.module, + module_id: self.module_id, + functions: self.functions, + types: self.types, + type_values: self.type_values, + stack_values: self.stack_values.clone(), + debug: self.debug.clone(), + allocator: self.allocator.clone(), + binops: self.binops, + } + } + + /// Takes the block out from this scope, swaps the given block in it's place + /// and returns the old block. + pub fn swap_block(&mut self, block: Block<'ctx>) -> Block<'ctx> { + let mut old_block = block; + mem::swap(&mut self.block, &mut old_block); + old_block + } + + pub fn get_typedef(&self, key: &CustomTypeKey) -> Option<&TypeDefinition> { + self.type_values.get(key).and_then(|v| self.types.get(v)) + } + + pub fn allocate(&self, name: &String, ty: &TypeKind) -> Option { + self.allocator.borrow_mut().allocate(name, ty) + } +} + +#[derive(Debug, Clone)] +pub struct Debug<'ctx> { + pub(super) info: &'ctx DebugInformation, + pub(super) scope: DebugProgramValue, + pub(super) types: &'ctx HashMap, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct StackValue(pub(super) StackValueKind, pub(super) TypeKind); + +impl StackValue { + pub fn instr(&self) -> InstructionValue { + self.0.instr() + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum StackValueKind { + Immutable(InstructionValue), + Mutable(InstructionValue), + Literal(InstructionValue), +} + +impl StackValueKind { + pub fn mutable(mutable: bool, instr: InstructionValue) -> StackValueKind { + match mutable { + true => StackValueKind::Mutable(instr), + false => StackValueKind::Immutable(instr), + } + } + + pub fn instr(&self) -> InstructionValue { + match &self { + StackValueKind::Immutable(val) => *val, + StackValueKind::Mutable(val) => *val, + StackValueKind::Literal(val) => *val, + } + } + + pub fn derive(&self, instr: InstructionValue) -> StackValueKind { + match &self { + StackValueKind::Immutable(_) => StackValueKind::Immutable(instr), + StackValueKind::Mutable(_) => StackValueKind::Mutable(instr), + StackValueKind::Literal(_) => StackValueKind::Literal(instr), + } + } + + #[allow(dead_code)] + fn map(&self, lambda: F) -> StackValueKind + where + F: FnOnce(InstructionValue) -> InstructionValue, + { + self.derive(lambda(self.instr())) + } +} + +pub struct StackBinopDefinition<'ctx> { + pub(super) parameters: ((String, TypeKind), (String, TypeKind)), + pub(super) return_ty: TypeKind, + pub(super) kind: StackBinopFunctionKind<'ctx>, +} + +pub enum StackBinopFunctionKind<'ctx> { + UserGenerated(Function<'ctx>), + Intrinsic(&'ctx Box), +} + +impl<'ctx> StackBinopDefinition<'ctx> { + pub fn codegen<'a>( + &self, + lhs: &StackValue, + rhs: &StackValue, + scope: &mut Scope<'ctx, 'a>, + ) -> Result { + let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { + (lhs, rhs) + } else { + (rhs, lhs) + }; + match &self.kind { + StackBinopFunctionKind::UserGenerated(ir) => { + let instr = scope + .block + .build(Instr::FunctionCall( + ir.value(), + vec![lhs.instr(), rhs.instr()], + )) + .unwrap(); + Ok(StackValue( + StackValueKind::Immutable(instr), + self.return_ty.clone(), + )) + } + StackBinopFunctionKind::Intrinsic(fun) => { + fun.codegen(scope, &[lhs.instr(), rhs.instr()]) + } + } + } +} diff --git a/reid/src/codegen/util.rs b/reid/src/codegen/util.rs new file mode 100644 index 0000000..e0b4d0c --- /dev/null +++ b/reid/src/codegen/util.rs @@ -0,0 +1,284 @@ +use std::collections::HashMap; + +use reid_lib::{ + builder::{InstructionValue, TypeValue}, + debug_information::{ + DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocation, + DebugPointerType, DebugPosition, DebugProgramValue, DebugStructType, DebugTypeData, + DebugTypeValue, DwarfEncoding, DwarfFlags, + }, + Block, CmpPredicate, ConstValue, Instr, Type, +}; + +use crate::{ + lexer::{FullToken, Position}, + mir::{ + self, CustomTypeKey, Metadata, SourceModuleId, TypeDefinition, TypeDefinitionKind, + TypeKind, VagueLiteral, + }, +}; + +use super::{ + scope::{Debug, Scope}, + ModuleCodegen, +}; + +impl mir::CmpOperator { + pub(super) fn predicate(&self) -> CmpPredicate { + match self { + mir::CmpOperator::LT => CmpPredicate::LT, + mir::CmpOperator::GT => CmpPredicate::GT, + mir::CmpOperator::LE => CmpPredicate::LE, + mir::CmpOperator::GE => CmpPredicate::GE, + mir::CmpOperator::EQ => CmpPredicate::EQ, + mir::CmpOperator::NE => CmpPredicate::NE, + } + } +} + +impl mir::Literal { + pub(super) fn as_const(&self, block: &mut Block) -> InstructionValue { + block + .build_named(format!("{}", self), self.as_const_kind()) + .unwrap() + } + + pub(super) fn as_const_kind(&self) -> Instr { + Instr::Constant(match self.clone() { + mir::Literal::I8(val) => ConstValue::I8(val), + mir::Literal::I16(val) => ConstValue::I16(val), + mir::Literal::I32(val) => ConstValue::I32(val), + mir::Literal::I64(val) => ConstValue::I64(val), + mir::Literal::I128(val) => ConstValue::I128(val), + mir::Literal::U8(val) => ConstValue::U8(val), + mir::Literal::U16(val) => ConstValue::U16(val), + mir::Literal::U32(val) => ConstValue::U32(val), + mir::Literal::U64(val) => ConstValue::U64(val), + mir::Literal::U128(val) => ConstValue::U128(val), + mir::Literal::Bool(val) => ConstValue::Bool(val), + mir::Literal::String(val) => ConstValue::Str(val.clone()), + mir::Literal::Vague(VagueLiteral::Number(val)) => ConstValue::I32(val as i32), + mir::Literal::Vague(VagueLiteral::Decimal(val)) => ConstValue::F32(val as f32), + mir::Literal::F16(val) => ConstValue::F16(val), + mir::Literal::F32B(val) => ConstValue::F32B(val), + mir::Literal::F32(val) => ConstValue::F32(val), + mir::Literal::F64(val) => ConstValue::F64(val), + mir::Literal::F80(val) => ConstValue::F80(val), + mir::Literal::F128(val) => ConstValue::F128(val), + mir::Literal::F128PPC(val) => ConstValue::F128PPC(val), + mir::Literal::Char(c) => ConstValue::U8(c as u8), + }) + } +} + +impl TypeKind { + pub(super) fn get_type(&self, type_vals: &HashMap) -> Type { + match &self { + TypeKind::I8 => Type::I8, + TypeKind::I16 => Type::I16, + TypeKind::I32 => Type::I32, + TypeKind::I64 => Type::I64, + TypeKind::I128 => Type::I128, + TypeKind::U8 => Type::U8, + TypeKind::U16 => Type::U16, + TypeKind::U32 => Type::U32, + TypeKind::U64 => Type::U64, + TypeKind::U128 => Type::U128, + TypeKind::Bool => Type::Bool, + TypeKind::F16 => Type::F16, + TypeKind::F32B => Type::F32B, + TypeKind::F32 => Type::F32, + TypeKind::F64 => Type::F64, + TypeKind::F128 => Type::F128, + TypeKind::F80 => Type::F80, + TypeKind::F128PPC => Type::F128PPC, + TypeKind::Char => Type::U8, + TypeKind::Array(elem_t, len) => Type::Array(Box::new(elem_t.get_type(type_vals)), *len), + TypeKind::Void => Type::Void, + TypeKind::Vague(_) => panic!("Tried to compile a vague type!"), + TypeKind::CustomType(n) => { + let type_val = type_vals.get(n).unwrap().clone(); + Type::CustomType(type_val) + } + TypeKind::UserPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), + TypeKind::CodegenPtr(type_kind) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), + TypeKind::Borrow(type_kind, _) => Type::Ptr(Box::new(type_kind.get_type(type_vals))), + } + } +} + +impl TypeKind { + pub(super) fn get_debug_type(&self, debug: &Debug, scope: &Scope) -> DebugTypeValue { + self.get_debug_type_hard( + debug.scope, + debug.info, + debug.types, + scope.type_values, + scope.types, + scope.module_id, + scope.tokens, + scope.modules, + ) + } + + pub(super) fn get_debug_type_hard( + &self, + scope: DebugProgramValue, + debug_info: &DebugInformation, + 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; + } + + let name = format!("{}", self); + + let data = match self { + TypeKind::CodegenPtr(inner) | TypeKind::UserPtr(inner) | TypeKind::Borrow(inner, _) => { + DebugTypeData::Pointer(DebugPointerType { + name, + pointee: inner.get_debug_type_hard( + scope, + debug_info, + debug_types, + type_values, + types, + local_mod, + tokens, + modules, + ), + size_bits: self.size_of(), + }) + } + TypeKind::Array(elem_ty, len) => { + let elem_ty = elem_ty.clone().get_debug_type_hard( + scope, + debug_info, + debug_types, + type_values, + types, + local_mod, + tokens, + modules, + ); + DebugTypeData::Array(DebugArrayType { + size_bits: self.size_of(), + align_bits: self.alignment(), + element_type: elem_ty, + length: *len, + }) + } + 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(), + scope, + pos: location.map(|l| l.pos), + size_bits: field.1.size_of(), + offset: size_bits, + flags: DwarfFlags, + ty: field.1.get_debug_type_hard( + scope, + debug_info, + 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(), + scope, + pos: location.map(|l| l.pos), + size_bits, + flags: DwarfFlags, + fields, + }) + } + } + } + } + _ => DebugTypeData::Basic(DebugBasicType { + name, + size_bits: self.size_of(), + encoding: match self { + TypeKind::Bool => DwarfEncoding::Boolean, + TypeKind::I8 => DwarfEncoding::SignedChar, + TypeKind::U8 => DwarfEncoding::UnsignedChar, + TypeKind::I16 | TypeKind::I32 | TypeKind::I64 | TypeKind::I128 => { + DwarfEncoding::Signed + } + TypeKind::U16 | TypeKind::U32 | TypeKind::U64 | TypeKind::U128 => { + DwarfEncoding::Unsigned + } + TypeKind::F16 + | TypeKind::F32 + | TypeKind::F32B + | TypeKind::F64 + | TypeKind::F80 + | TypeKind::F128 + | TypeKind::F128PPC => DwarfEncoding::Float, + TypeKind::Void => DwarfEncoding::Address, + TypeKind::Char => DwarfEncoding::UnsignedChar, + TypeKind::Array(_, _) => DwarfEncoding::Address, + TypeKind::CustomType(_) => DwarfEncoding::Address, + _ => panic!("tried fetching debug-type for non-supported type!"), + }, + flags: DwarfFlags, + }), + }; + debug_info.debug_type(data) + } +} + +impl Metadata { + pub(super) fn into_debug( + &self, + tokens: &Vec, + scope: DebugProgramValue, + ) -> Option { + if let Some((start, _)) = self.into_positions(tokens) { + Some(start.debug(scope)) + } else { + None + } + } +} + +impl Position { + pub(super) fn debug(self, scope: DebugProgramValue) -> DebugLocation { + DebugLocation { + pos: DebugPosition { + line: self.1, + column: self.0, + }, + scope, + } + } +} diff --git a/reid/src/lib.rs b/reid/src/lib.rs index 40230fd..56fed4c 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -43,8 +43,8 @@ use std::path::PathBuf; +use codegen::intrinsics::{form_intrinsic_binops, form_intrinsics}; use error_raporting::{ErrorKind as ErrorRapKind, ErrorModules, ReidError}; -use intrinsics::{form_intrinsic_binops, form_intrinsics}; use lexer::FullToken; use mir::{ linker::LinkerPass, typecheck::TypeCheck, typeinference::TypeInference, typerefs::TypeRefs, @@ -53,11 +53,9 @@ use reid_lib::{compile::CompileOutput, Context}; use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; -mod allocator; mod ast; mod codegen; pub mod error_raporting; -pub mod intrinsics; pub mod ld; mod lexer; pub mod mir; diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 9b2ace7..9039d8b 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, path::PathBuf}; use crate::{ - intrinsics::IntrinsicFunction, + codegen::intrinsics::IntrinsicFunction, lexer::{FullToken, Position}, token_stream::TokenRange, };