reid-llvm/reid/src/codegen/util.rs
2025-08-05 22:00:11 +03:00

265 lines
10 KiB
Rust

use std::collections::HashMap;
use reid_lib::{
builder::{InstructionValue, TypeValue},
debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocation, DebugPointerType,
DebugPosition, DebugScopeValue, DebugStructType, DebugTypeData, DebugTypeValue, DwarfEncoding, DwarfFlags,
},
Block, CmpPredicate, ConstValueKind, Instr, Type,
};
use crate::{
lexer::{FullToken, Position},
mir::{self, CustomTypeKey, Metadata, SourceModuleId, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral},
};
use super::scope::{Debug, Scope};
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), Instr::Constant(self.as_const_kind()))
.unwrap()
}
pub(super) fn as_const_kind(&self) -> ConstValueKind {
match self.clone() {
mir::Literal::I8(val) => ConstValueKind::I8(val),
mir::Literal::I16(val) => ConstValueKind::I16(val),
mir::Literal::I32(val) => ConstValueKind::I32(val),
mir::Literal::I64(val) => ConstValueKind::I64(val),
mir::Literal::I128(val) => ConstValueKind::I128(val),
mir::Literal::U8(val) => ConstValueKind::U8(val),
mir::Literal::U16(val) => ConstValueKind::U16(val),
mir::Literal::U32(val) => ConstValueKind::U32(val),
mir::Literal::U64(val) => ConstValueKind::U64(val),
mir::Literal::U128(val) => ConstValueKind::U128(val),
mir::Literal::Bool(val) => ConstValueKind::Bool(val),
mir::Literal::String(val) => ConstValueKind::Str(val.clone()),
mir::Literal::Vague(VagueLiteral::Number(val)) => ConstValueKind::I32(val as i32),
mir::Literal::Vague(VagueLiteral::Decimal(val)) => ConstValueKind::F32(val as f32),
mir::Literal::F16(val) => ConstValueKind::F16(val),
mir::Literal::F32B(val) => ConstValueKind::F32B(val),
mir::Literal::F32(val) => ConstValueKind::F32(val),
mir::Literal::F64(val) => ConstValueKind::F64(val),
mir::Literal::F80(val) => ConstValueKind::F80(val),
mir::Literal::F128(val) => ConstValueKind::F128(val),
mir::Literal::F128PPC(val) => ConstValueKind::F128PPC(val),
mir::Literal::Char(c) => ConstValueKind::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_map,
scope.module_id,
scope.tokens,
scope.modules,
)
}
pub(super) fn get_debug_type_hard(
&self,
scope: &DebugScopeValue,
debug_info: &DebugInformation,
debug_types: &HashMap<TypeKind, DebugTypeValue>,
type_map: &HashMap<CustomTypeKey, TypeDefinition>,
local_mod: SourceModuleId,
tokens: &Vec<FullToken>,
modules: &HashMap<SourceModuleId, &mir::Module>,
) -> 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_map,
local_mod,
tokens,
modules,
),
size_bits: self.size_of(type_map),
})
}
TypeKind::Array(elem_ty, len) => {
let elem_ty = elem_ty.clone().get_debug_type_hard(
scope,
debug_info,
debug_types,
type_map,
local_mod,
tokens,
modules,
);
DebugTypeData::Array(DebugArrayType {
size_bits: self.size_of(type_map),
align_bits: self.alignment(),
element_type: elem_ty,
length: *len,
})
}
TypeKind::CustomType(key) => {
let typedef = type_map.get(key).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: scope.clone(),
pos: location.map(|l| l.pos),
size_bits: field.1.size_of(type_map),
offset: size_bits,
flags: DwarfFlags,
ty: field.1.get_debug_type_hard(
scope,
debug_info,
debug_types,
type_map,
local_mod,
tokens,
modules,
),
});
size_bits += field.1.size_of(type_map);
}
{
let location = if typedef.source_module != local_mod {
None
} else {
typedef.meta.into_debug(&tokens, scope)
};
DebugTypeData::Struct(DebugStructType {
name: key.0.clone(),
scope: scope.clone(),
pos: location.map(|l| l.pos),
size_bits,
flags: DwarfFlags,
fields,
})
}
}
}
}
_ => DebugTypeData::Basic(DebugBasicType {
name,
size_bits: self.size_of(type_map),
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: &DebugScopeValue) -> Option<DebugLocation> {
if let Some((start, _)) = self.into_positions(tokens) {
Some(start.debug(scope.clone()))
} else {
None
}
}
}
impl Position {
pub(super) fn debug(self, scope: DebugScopeValue) -> DebugLocation {
DebugLocation {
pos: DebugPosition {
line: self.1,
column: self.0,
},
scope,
}
}
}