mir/triples use internpool now for types

This commit is contained in:
Janis 2024-12-22 22:25:01 +01:00
parent 0994f4b187
commit a3bee90ac3
6 changed files with 707 additions and 303 deletions

View file

@ -98,10 +98,10 @@ pub enum Key<'a> {
bigint: BigInt,
},
UIntType {
bits: u16,
bit_width: u16,
},
SIntType {
bits: u16,
bit_width: u16,
},
SimpleType {
ty: SimpleType,
@ -144,8 +144,8 @@ impl Hash for Key<'_> {
Key::F64 { bits } => ordered_float::OrderedFloat(*bits).hash(state),
Key::PositiveInt { bigint } => bigint.hash(state),
Key::NegativeInt { bigint } => bigint.hash(state),
Key::UIntType { bits } => bits.hash(state),
Key::SIntType { bits } => bits.hash(state),
Key::UIntType { bit_width: bits } => bits.hash(state),
Key::SIntType { bit_width: bits } => bits.hash(state),
Key::SimpleType { ty } => ty.hash(state),
Key::PointerType { pointee, flags } => (pointee, flags).hash(state),
Key::ArrayType {
@ -180,6 +180,14 @@ impl PointerFlags {
}
}
pub fn union(self, other: Self) -> Self {
Self::new(
self.is_const || other.is_const,
self.volatile || other.volatile,
self.noalias || other.noalias,
)
}
pub fn pack(self) -> u8 {
(self.volatile as u8) << 0
| (self.is_const as u8) << 1
@ -325,43 +333,44 @@ impl std::fmt::Debug for InternPool {
}
}
const STATIC_KEYS: [Key; 21] = [
Key::SimpleType {
ty: SimpleType::Bool,
},
Key::SimpleType {
ty: SimpleType::F32,
},
Key::SimpleType {
ty: SimpleType::F64,
},
Key::SimpleType {
ty: SimpleType::USize,
},
Key::SimpleType {
ty: SimpleType::ISize,
},
Key::SimpleType {
ty: SimpleType::Void,
},
Key::SimpleType {
ty: SimpleType::ComptimeInt,
},
Key::SIntType { bits: 1 },
Key::UIntType { bits: 1 },
Key::SIntType { bits: 0 },
Key::UIntType { bits: 0 },
Key::SIntType { bits: 8 },
Key::UIntType { bits: 8 },
Key::SIntType { bits: 16 },
Key::UIntType { bits: 16 },
Key::SIntType { bits: 32 },
Key::UIntType { bits: 32 },
Key::SIntType { bits: 64 },
Key::UIntType { bits: 64 },
Key::TrueValue,
Key::FalseValue,
];
macro_rules! static_keys {
($($name:ident => $def:expr),* $(,)?) => {
impl Index {
$(
pub const $name: Self = Self(${index()});
)*
}
const STATIC_KEYS: [Key; ${count($def)}] = [
$($def),*
];
};
}
static_keys!(
BOOL => Key::SimpleType {ty: SimpleType::Bool,},
F32 => Key::SimpleType {ty: SimpleType::F32,},
F64 => Key::SimpleType {ty: SimpleType::F64,},
USIZE => Key::SimpleType {ty: SimpleType::USize,},
ISIZE => Key::SimpleType {ty: SimpleType::ISize,},
VOID => Key::SimpleType {ty: SimpleType::Void,},
COMPTIME_INT => Key::SimpleType {ty: SimpleType::ComptimeInt,},
I1 => Key::SIntType { bit_width: 1 },
U1 => Key::UIntType { bit_width: 1 },
I0 => Key::SIntType { bit_width: 0 },
U0 => Key::UIntType { bit_width: 0 },
I8 => Key::SIntType { bit_width: 8 },
U8 => Key::UIntType { bit_width: 8 },
I16 => Key::SIntType { bit_width: 16 },
U16 => Key::UIntType { bit_width: 16 },
I32 => Key::SIntType { bit_width: 32 },
U32 => Key::UIntType { bit_width: 32 },
I64 => Key::SIntType { bit_width: 64 },
U64 => Key::UIntType { bit_width: 64 },
I128 => Key::SIntType { bit_width: 128 },
U128 => Key::UIntType { bit_width: 128 },
TRUE => Key::TrueValue,
FALSE => Key::FalseValue,
);
impl InternPool {
pub fn get_void_type(&self) -> Index {
@ -406,40 +415,40 @@ impl InternPool {
})
}
pub fn get_u0_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 0 })
self.get_assume_present(&Key::UIntType { bit_width: 0 })
}
pub fn get_i0_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 0 })
self.get_assume_present(&Key::SIntType { bit_width: 0 })
}
pub fn get_u1_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 1 })
self.get_assume_present(&Key::UIntType { bit_width: 1 })
}
pub fn get_i1_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 1 })
self.get_assume_present(&Key::SIntType { bit_width: 1 })
}
pub fn get_u8_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 8 })
self.get_assume_present(&Key::UIntType { bit_width: 8 })
}
pub fn get_i8_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 8 })
self.get_assume_present(&Key::SIntType { bit_width: 8 })
}
pub fn get_u16_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 16 })
self.get_assume_present(&Key::UIntType { bit_width: 16 })
}
pub fn get_i16_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 16 })
self.get_assume_present(&Key::SIntType { bit_width: 16 })
}
pub fn get_u32_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 32 })
self.get_assume_present(&Key::UIntType { bit_width: 32 })
}
pub fn get_i32_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 32 })
self.get_assume_present(&Key::SIntType { bit_width: 32 })
}
pub fn get_u64_type(&self) -> Index {
self.get_assume_present(&Key::UIntType { bits: 64 })
self.get_assume_present(&Key::UIntType { bit_width: 64 })
}
pub fn get_i64_type(&self) -> Index {
self.get_assume_present(&Key::SIntType { bits: 64 })
self.get_assume_present(&Key::SIntType { bit_width: 64 })
}
}
@ -447,41 +456,173 @@ impl InternPool {
pub struct TypeInfo {
pub bitsize: u32,
pub bitalign: u32,
pub signed: bool,
}
impl InternPool {
pub fn size_of_type(&self, index: Index, ptr_size: TypeInfo) -> TypeInfo {
match self.get_key(index) {
Key::UIntType { bits } => {
let bits = bits as u32;
TypeInfo {
bitsize: bits,
bitalign: bits.next_multiple_of(8).next_power_of_two(),
pub fn peer_type(&mut self, lhs: Index, rhs: Index) -> Option<Index> {
if lhs == rhs {
return Some(rhs);
}
let lt = self.get_key(lhs);
let rt = self.get_key(rhs);
match (lt, rt) {
(
Key::SimpleType {
ty: SimpleType::ComptimeInt,
},
Key::SimpleType {
ty: SimpleType::F32,
}
| Key::SimpleType {
ty: SimpleType::F64,
}
| Key::SimpleType {
ty: SimpleType::USize,
}
| Key::SimpleType {
ty: SimpleType::ISize,
}
| Key::SIntType { .. }
| Key::UIntType { .. },
) => Some(rhs),
(
Key::SimpleType {
ty: SimpleType::F32,
}
| Key::SimpleType {
ty: SimpleType::F64,
}
| Key::SimpleType {
ty: SimpleType::USize,
}
| Key::SimpleType {
ty: SimpleType::ISize,
}
| Key::SIntType { .. }
| Key::UIntType { .. },
Key::SimpleType {
ty: SimpleType::ComptimeInt,
},
) => Some(lhs),
(
Key::PointerType {
pointee: lp,
flags: lf,
},
Key::PointerType {
pointee: rp,
flags: rf,
},
) => {
if lp == rp {
Some(self.get_pointer_type(lp, Some(lf.union(rf))))
} else {
None
}
}
Key::SIntType { bits } => {
_ => None,
}
}
pub fn to_mir_type(
&self,
index: Index,
_ptr_size: TypeInfo,
) -> crate::mir::Type {
use crate::mir::Type;
match self.get_key(index) {
Key::UIntType { bit_width: bits } => {
let bits = bits as u32;
Type::from_bitsize_int(bits)
}
Key::SIntType { bit_width: bits } => {
let bits = bits as u32;
Type::from_bitsize_int(bits)
}
Key::SimpleType { ty } => match ty {
SimpleType::F32 => Type::SinglePrecision,
SimpleType::F64 => Type::DoublePrecision,
SimpleType::Bool => Type::Byte,
SimpleType::Void => {
todo!("void can't be turned into a mir type")
}
SimpleType::ISize | SimpleType::USize => Type::QWord,
SimpleType::ComptimeInt => {
panic!("comptime int can't be turned into a mir type")
}
},
Key::ArrayType { .. } => {
panic!("arrays can't be directly accessed in mir")
}
Key::FunctionType { .. } | Key::PointerType { .. } => Type::QWord,
Key::StructType { .. } => {
panic!("arrays can't be directly accessed in mir")
}
_ => {
panic!("index was not a type")
}
}
}
pub fn is_type_signed(&self, index: Index, _ptr_size: TypeInfo) -> bool {
match self.get_key(index) {
Key::UIntType { .. } => false,
Key::SIntType { .. } => true,
Key::SimpleType { ty } => match ty {
SimpleType::USize => false,
SimpleType::ISize => true,
_ => false,
},
Key::PointerType { .. } => false,
Key::ArrayType { .. } => false,
Key::FunctionType { .. } => false,
Key::StructType { .. } => false,
_ => false,
}
}
pub fn size_of_type(&self, index: Index, ptr_size: TypeInfo) -> TypeInfo {
match self.get_key(index) {
Key::UIntType { bit_width: bits } => {
let bits = bits as u32;
TypeInfo {
bitsize: bits,
bitalign: bits.next_multiple_of(8).next_power_of_two(),
signed: false,
}
}
Key::SIntType { bit_width: bits } => {
let bits = bits as u32;
TypeInfo {
bitsize: bits,
bitalign: bits.next_multiple_of(8).next_power_of_two(),
signed: true,
}
}
Key::SimpleType { ty } => match ty {
SimpleType::F32 => TypeInfo {
bitsize: 32,
bitalign: 32,
signed: true,
},
SimpleType::F64 => TypeInfo {
bitsize: 64,
bitalign: 64,
signed: true,
},
SimpleType::Bool => TypeInfo {
bitsize: 1,
bitalign: 1,
signed: false,
},
SimpleType::Void => TypeInfo {
bitsize: 0,
bitalign: 0,
signed: false,
},
SimpleType::USize => ptr_size,
SimpleType::ISize => ptr_size,
@ -495,6 +636,7 @@ impl InternPool {
let bitsize = element_size.bitalign * length;
TypeInfo {
bitsize,
signed: false,
..element_size
}
}
@ -518,6 +660,7 @@ impl InternPool {
TypeInfo {
bitsize: size,
bitalign: align,
signed: false,
}
}
_ => {
@ -527,7 +670,7 @@ impl InternPool {
}
pub fn from_ast1_type(
&self,
&mut self,
pointer_bits: u16,
ty: &crate::ast::Type,
) -> Index {
@ -536,9 +679,9 @@ impl InternPool {
crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(),
crate::ast::Type::Integer(i) => self.get_assume_present(&{
if i.signed {
Key::SIntType { bits: i.bits }
Key::SIntType { bit_width: i.bits }
} else {
Key::UIntType { bits: i.bits }
Key::UIntType { bit_width: i.bits }
}
}),
crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => {
@ -547,14 +690,26 @@ impl InternPool {
crate::ast::Type::Floating(crate::ast::FloatingType::Binary64) => {
self.get_f64_type()
}
crate::ast::Type::Pointer { constness, pointee } => self
.get_assume_present(&Key::PointerType {
pointee: self.from_ast1_type(pointer_bits, &pointee),
crate::ast::Type::Pointer { constness, pointee } => {
let pointee = self.from_ast1_type(pointer_bits, &pointee);
self.get_or_insert(Key::PointerType {
pointee,
flags: PointerFlags::new(*constness, false, false),
}),
crate::ast::Type::Fn { .. } => {
unimplemented!()
})
}
crate::ast::Type::Fn {
parameter_types,
return_type,
} => {
let parameters = parameter_types
.iter()
.map(|ty| self.from_ast1_type(pointer_bits, ty))
.collect::<Vec<_>>();
let return_type =
self.from_ast1_type(pointer_bits, &return_type);
self.get_function_type(return_type, parameters)
}
crate::ast::Type::Void => self.get_void_type(),
_ => {
todo!()
}
@ -568,10 +723,10 @@ impl InternPool {
) -> crate::ast::Type {
use crate::ast::Type;
match self.get_key(index) {
Key::UIntType { bits } => {
Key::UIntType { bit_width: bits } => {
Type::Integer(IntegralType::new(false, bits))
}
Key::SIntType { bits } => {
Key::SIntType { bit_width: bits } => {
Type::Integer(IntegralType::new(true, bits))
}
Key::SimpleType { ty } => match ty {
@ -613,9 +768,14 @@ impl InternPool {
}
pub const AMD64_POINTER_BITS: u16 = 64;
pub const AMD64_POINTER_TYPE_INFO: TypeInfo = TypeInfo {
bitsize: 64,
bitalign: 64,
signed: false,
};
impl InternPool {
pub fn create() -> Self {
pub fn new() -> Self {
let mut this = Self {
tags: Vec::new(),
indices: Vec::new(),
@ -701,10 +861,10 @@ impl InternPool {
self.create_item(Tag::NegativeInt, i)
}
Key::UIntType { bits } => {
Key::UIntType { bit_width: bits } => {
self.create_item(Tag::UIntType, bits as u32)
}
Key::SIntType { bits } => {
Key::SIntType { bit_width: bits } => {
self.create_item(Tag::SIntType, bits as u32)
}
Key::SimpleType { ty } => {
@ -855,10 +1015,10 @@ impl InternPool {
Key::PositiveInt { bigint }
}
Tag::SIntType => Key::SIntType {
bits: item.index as u16,
bit_width: item.index as u16,
},
Tag::UIntType => Key::UIntType {
bits: item.index as u16,
bit_width: item.index as u16,
},
Tag::SimpleType => {
let ty = item.idx() as u8;
@ -964,8 +1124,8 @@ impl InternPool {
pub fn get_int_type(&mut self, signed: bool, bits: u16) -> Index {
let key = match signed {
true => Key::SIntType { bits },
false => Key::UIntType { bits },
true => Key::SIntType { bit_width: bits },
false => Key::UIntType { bit_width: bits },
};
self.get_or_insert(key)

View file

@ -1909,7 +1909,8 @@ fn interned_type_and_value_to_comptime_number(
let ty_key = ip.get_key(ty);
match ty_key {
intern::Key::SIntType { bits } | intern::Key::UIntType { bits } => {
intern::Key::SIntType { bit_width: bits }
| intern::Key::UIntType { bit_width: bits } => {
let ty = IntegralType::new(false, bits);
match ip.get_key(val) {
intern::Key::SIntSmall { bits } => {
@ -2191,7 +2192,7 @@ pub mod ast_gen {
pub fn new() -> Parser {
Self {
ast: Ast::new(),
intern: intern::InternPool::create(),
intern: intern::InternPool::new(),
syms: crate::symbol_table::syms2::Symbols::new(),
scopes: Vec::new(),
errors: Vec::new(),
@ -4252,12 +4253,12 @@ pub mod ir_gen {
use super::*;
use crate::{symbol_table::syms2::Symbols, triples::*};
struct IRGen {
struct IRGen<'a> {
ast: Ast,
syms: Symbols,
intern: InternPool,
ir: IR,
ir: IR<'a>,
}
impl IRGen {}
impl IRGen<'_> {}
}

View file

@ -1,7 +1,8 @@
use std::{io::Read, path::PathBuf};
use std::{io::Read, path::PathBuf, sync::Arc};
use clap::Command;
use compiler::{
ast2::intern::InternPool,
lexer::Tokenizer,
parser::Tree,
triples::{MirBuilder, IR},
@ -62,7 +63,8 @@ fn main() {
}
"ir" => {
let mut tree = ast_tree(&tokens);
let mut ir = IR::new();
let mut intern = InternPool::new();
let mut ir = IR::new(&mut intern);
let builder = ir.build(&mut tree);
let mut buf = String::new();
builder.render(&mut buf).unwrap();
@ -70,7 +72,8 @@ fn main() {
}
"mir" => {
let mut tree = ast_tree(&tokens);
let mut ir = IR::new();
let mut intern = InternPool::new();
let mut ir = IR::new(&mut intern);
ir.build(&mut tree);
let mut mir = MirBuilder::new(&ir, tree.strings);
@ -90,8 +93,9 @@ fn main() {
}
"asm" => {
let mut tree = ast_tree(&tokens);
let mut ir = IR::new();
ir.build(&mut tree);
let mut intern = InternPool::new();
let mut ir = IR::new(&mut intern);
_ = ir.build(&mut tree);
let mut mir = MirBuilder::new(&ir, tree.strings);
mir.build();

View file

@ -9,7 +9,8 @@
iter_array_chunks,
int_roundings,
if_let_guard,
debug_closure_helpers
debug_closure_helpers,
macro_metavar_expr
)]
#![allow(unused_macros)]

View file

@ -12,6 +12,7 @@ use itertools::Itertools;
use crate::asm::amd64::Register;
use crate::ast::IntegralType;
use crate::ast2::intern;
use crate::string_table::{Index as StringsIndex, StringTable};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
@ -1107,18 +1108,22 @@ impl Mir {
pub fn gen_extend_integer(
&mut self,
src: u32,
from: IntegralType,
to: IntegralType,
from: intern::TypeInfo,
to: intern::TypeInfo,
) -> u32 {
// example: u4 -> (byte, false, 4)
// 1111_1111 << 4 = 1111_0000
// mask = 0000_1111;
// shift = 8 - 4;
let src_ty = Type::from_bitsize_int(from.bits as u32);
let truncated =
self.gen_truncate_integer(src, src_ty, from.signed, from.bits);
let src_ty = Type::from_bitsize_int(from.bitsize);
let truncated = self.gen_truncate_integer(
src,
src_ty,
from.signed,
from.bitsize as u16,
);
let dst_ty = Type::from_bitsize_int(to.bits as u32);
let dst_ty = Type::from_bitsize_int(to.bitsize);
if to.signed {
self.gen_sign_extend(dst_ty, truncated)
} else {

File diff suppressed because it is too large Load diff