Refactor stuff into codegen-module

This commit is contained in:
Sofia 2025-07-25 15:52:37 +03:00
parent d79d396814
commit 6ee43d4012
8 changed files with 474 additions and 433 deletions

View File

@ -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"

View File

@ -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<FunctionDefinition> {
let intrinsics = Vec::new();

View File

@ -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<SourceModuleId, ModuleCodegen<'ctx>>,
tokens: &'ctx Vec<FullToken>,
module: &'ctx Module<'ctx>,
module_id: SourceModuleId,
function: &'ctx Function<'ctx>,
pub(super) block: Block<'ctx>,
types: &'scope HashMap<TypeValue, TypeDefinition>,
type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
functions: &'scope HashMap<String, Function<'ctx>>,
binops: &'scope HashMap<ScopeBinopKey, StackBinopDefinition<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>,
allocator: Rc<RefCell<Allocator>>,
}
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<InstructionValue> {
self.allocator.borrow_mut().allocate(name, ty)
}
}
#[derive(Debug, Clone)]
pub struct Debug<'ctx> {
info: &'ctx DebugInformation,
scope: DebugProgramValue,
types: &'ctx HashMap<TypeKind, DebugTypeValue>,
}
#[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<F>(&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<dyn IntrinsicFunction>),
}
impl<'ctx> StackBinopDefinition<'ctx> {
fn codegen<'a>(
&self,
lhs: &StackValue,
rhs: &StackValue,
scope: &mut Scope<'ctx, 'a>,
) -> Result<StackValue, ErrorKind> {
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<CustomTypeKey, TypeValue>) -> 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<TypeKind, DebugTypeValue>,
type_values: &HashMap<CustomTypeKey, TypeValue>,
types: &HashMap<TypeValue, TypeDefinition>,
local_mod: SourceModuleId,
tokens: &Vec<FullToken>,
modules: &HashMap<SourceModuleId, ModuleCodegen>,
) -> 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<FullToken>,
scope: DebugProgramValue,
) -> Option<DebugLocation> {
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,
}
}
}

168
reid/src/codegen/scope.rs Normal file
View File

@ -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<SourceModuleId, ModuleCodegen<'ctx>>,
pub(super) tokens: &'ctx Vec<FullToken>,
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<TypeValue, TypeDefinition>,
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
pub(super) functions: &'scope HashMap<String, Function<'ctx>>,
pub(super) binops: &'scope HashMap<ScopeBinopKey, StackBinopDefinition<'ctx>>,
pub(super) stack_values: HashMap<String, StackValue>,
pub(super) debug: Option<Debug<'ctx>>,
pub(super) allocator: Rc<RefCell<Allocator>>,
}
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<InstructionValue> {
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<TypeKind, DebugTypeValue>,
}
#[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<F>(&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<dyn IntrinsicFunction>),
}
impl<'ctx> StackBinopDefinition<'ctx> {
pub fn codegen<'a>(
&self,
lhs: &StackValue,
rhs: &StackValue,
scope: &mut Scope<'ctx, 'a>,
) -> Result<StackValue, ErrorKind> {
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()])
}
}
}
}

284
reid/src/codegen/util.rs Normal file
View File

@ -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<CustomTypeKey, TypeValue>) -> 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<TypeKind, DebugTypeValue>,
type_values: &HashMap<CustomTypeKey, TypeValue>,
types: &HashMap<TypeValue, TypeDefinition>,
local_mod: SourceModuleId,
tokens: &Vec<FullToken>,
modules: &HashMap<SourceModuleId, ModuleCodegen>,
) -> 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<FullToken>,
scope: DebugProgramValue,
) -> Option<DebugLocation> {
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,
}
}
}

View File

@ -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;

View File

@ -5,7 +5,7 @@
use std::{collections::HashMap, path::PathBuf};
use crate::{
intrinsics::IntrinsicFunction,
codegen::intrinsics::IntrinsicFunction,
lexer::{FullToken, Position},
token_stream::TokenRange,
};