diff --git a/src/ast2/intern.rs b/src/ast2/intern.rs index c6528d6..9386d29 100644 --- a/src/ast2/intern.rs +++ b/src/ast2/intern.rs @@ -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 { + 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::>(); + 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) diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 0533ca1..9a73f2f 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -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<'_> {} } diff --git a/src/bin/main.rs b/src/bin/main.rs index ab8c32b..15602bf 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -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(); diff --git a/src/lib.rs b/src/lib.rs index 39c1a7a..ec19563 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,8 @@ iter_array_chunks, int_roundings, if_let_guard, - debug_closure_helpers + debug_closure_helpers, + macro_metavar_expr )] #![allow(unused_macros)] diff --git a/src/mir.rs b/src/mir.rs index 3835113..35df816 100644 --- a/src/mir.rs +++ b/src/mir.rs @@ -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 { diff --git a/src/triples.rs b/src/triples.rs index eb6577b..f2a44e5 100644 --- a/src/triples.rs +++ b/src/triples.rs @@ -7,6 +7,9 @@ use std::{ use crate::{ ast::{IntegralType, Node as AstNode, Tag, Type}, + ast2::intern::{ + self, InternPool, AMD64_POINTER_BITS, AMD64_POINTER_TYPE_INFO, + }, parser::Tree, string_table::{ImmOrIndex, Index as StringsIndex, StringTable}, variant, write_indented, writeln_indented, @@ -35,6 +38,13 @@ impl Into for Type2 { } } +fn mir_unalignment(signed: bool, bits: u32) -> Option<(bool, u16)> { + match bits { + 8 | 16 | 32 | 64 => None, + bits => Some((signed, bits as u16)), + } +} + impl Type2 { fn mir_type(self) -> mir::Type { match self { @@ -138,20 +148,20 @@ pub enum Inst { /// index Label, /// ast-node -> index - ExternRef(Type2), + ExternRef(intern::Index), /// index FunctionStart, /// None FunctionEnd, // marker /// lhs - Argument(Type2), - InlineType(Type2), + Argument(intern::Index), + InlineType(intern::Index), /// list of arguments /// start, (inlinetype)end Call(Node), /// Value /// lhs - GlobalConstant(StringsIndex, Type2), + GlobalConstant(StringsIndex, intern::Index), /// u32 ConstantU32, /// lo, hi @@ -161,53 +171,53 @@ pub enum Inst { /// size, align Alloca, /// src - Load(Type2), + Load(intern::Index), /// src, dst - Store(Type2), + Store(intern::Index), /// ptr, index, - GetElementPtr(Type2), + GetElementPtr(intern::Index), /// size, align - Parameter(Type2), + Parameter(intern::Index), /// lhs, rhs - Add(Type2), + Add(intern::Index), /// lhs, rhs - Sub(Type2), + Sub(intern::Index), /// lhs, rhs - Mul(Type2), + Mul(intern::Index), /// lhs, rhs - Div(Type2), + Div(intern::Index), /// lhs, rhs - Rem(Type2), + Rem(intern::Index), /// lhs, rhs - BitAnd(Type2), + BitAnd(intern::Index), /// lhs, rhs - BitOr(Type2), + BitOr(intern::Index), /// lhs, rhs - BitXOr(Type2), + BitXOr(intern::Index), /// lhs, rhs - ShiftLeft(Type2), + ShiftLeft(intern::Index), /// lhs, rhs - ShiftRight(Type2), + ShiftRight(intern::Index), /// lhs - Negate(Type2), + Negate(intern::Index), /// lhs - Not(Type2), + Not(intern::Index), /// lhs, rhs - Eq(Type2), + Eq(intern::Index), /// lhs, rhs - Neq(Type2), + Neq(intern::Index), /// lhs, rhs - Gt(Type2), + Gt(intern::Index), /// lhs, rhs - Lt(Type2), + Lt(intern::Index), /// lhs, rhs - Ge(Type2), + Ge(intern::Index), /// lhs, rhs - Le(Type2), + Le(intern::Index), /// lhs - ExplicitCast(Type2, Type2), + ExplicitCast(intern::Index, intern::Index), /// lhs - ReturnValue(Type2), + ReturnValue(intern::Index), /// no parameters Return, /// Node is a bool @@ -217,7 +227,7 @@ pub enum Inst { /// lhs: Label Jump, /// lhs, rhs - Phi2(Type2), + Phi2(intern::Index), } impl Inst { @@ -296,15 +306,15 @@ impl From for Data { } } -pub struct IRBuilder<'tree, 'ir> { - ir: &'ir mut IR, +pub struct IRBuilder<'tree, 'ir, 'intern> { + ir: &'ir mut IR<'intern>, tree: &'tree mut Tree, type_map: HashMap, lookup: HashMap, fixup: Vec, } -impl core::ops::Index for IR { +impl core::ops::Index for IR<'_> { type Output = Inst; fn index(&self, index: Node) -> &Self::Output { @@ -312,8 +322,8 @@ impl core::ops::Index for IR { } } -impl<'tree, 'ir> IRBuilder<'tree, 'ir> { - fn new(ir: &'ir mut IR, tree: &'tree mut Tree) -> Self { +impl<'tree, 'ir, 'intern> IRBuilder<'tree, 'ir, 'intern> { + fn new(ir: &'ir mut IR<'intern>, tree: &'tree mut Tree) -> Self { Self { ir, tree, @@ -385,8 +395,12 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(*ty); let size = ty.size_of(); let align = ty.align_of(); + let ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &ty); let ir = self.ir.push( - Inst::Parameter(ty.into()), + Inst::Parameter(ty), Some(Data::new(size, align)), ); @@ -399,6 +413,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { self.tree.st.into_parent(); if value != !0 { let ty = self.tree.type_of_node(*body); + let ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push( Inst::ReturnValue(ty.into()), Some(Data::lhs(value)), @@ -422,6 +440,10 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let start = self.ir.nodes.len(); for (arg, ty) in args { + let ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &ty); _ = self.ir.push( Inst::Argument(ty.into()), Some(Data::lhs(arg)), @@ -437,6 +459,9 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { self.ir.nodes.len() as u32, self.ir.nodes.len() as u32, )); + + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push(Inst::InlineType(ty.into()), None); let func = self.visit(*lhs); @@ -464,6 +489,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { Inst::Alloca, Some(Data::new(ty.size_of(), ty.align_of())), ); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); if let Some(assignment) = assignment { let value = self.visit(*assignment); @@ -485,6 +512,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { variant!(self.tree.nodes.get_node(*name) => Tag::Ident { name }); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); let global = self.ir.push( Inst::GlobalConstant(*name, ty.into()), Some(Data::lhs(value)), @@ -496,6 +525,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } Tag::GlobalRef(decl) => { let ty = self.tree.type_of_node(*decl); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); let node = self.ir.push( Inst::ExternRef(ty.into()), Some(Data::lhs(decl.get())), @@ -516,12 +547,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let dest = self.visit(*lhs); let source = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::Store(ty.into()), Some(Data::new(source, dest))) } Tag::ReturnStmt { expr } => { if let Some(expr) = expr { let ty = self.tree.type_of_node(*expr); + let ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &ty); let expr = self.visit(*expr); self.ir.push( Inst::ReturnValue(ty.into()), @@ -536,12 +573,16 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(*lhs).pointee().unwrap().clone(); let lhs = self.visit(*lhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs))) } Tag::Add { lhs, rhs } => { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::Add(ty.into()), Some(Data::new(lhs, rhs))) } @@ -549,6 +590,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::Sub(ty.into()), Some(Data::new(lhs, rhs))) } @@ -556,6 +599,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::BitAnd(ty.into()), Some(Data::new(lhs, rhs))) } @@ -563,6 +608,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::BitOr(ty.into()), Some(Data::new(lhs, rhs))) } @@ -570,6 +617,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::BitXOr(ty.into()), Some(Data::new(lhs, rhs))) } @@ -589,6 +638,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { }) .into(); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); let inst = match tag { Tag::Eq { .. } => Inst::Eq(ty), Tag::NEq { .. } => Inst::Neq(ty), @@ -607,23 +658,31 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::Mul(ty.into()), Some(Data::new(lhs, rhs))) } Tag::Negate { lhs } => { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push(Inst::Negate(ty.into()), Some(Data::lhs(lhs))) } Tag::Not { lhs } => { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push(Inst::Not(ty.into()), Some(Data::lhs(lhs))) } Tag::Shl { lhs, rhs } => { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir .push(Inst::ShiftLeft(ty.into()), Some(Data::new(lhs, rhs))) } @@ -631,6 +690,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let ty = self.tree.type_of_node(node); let lhs = self.visit(*lhs); let rhs = self.visit(*rhs); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push( Inst::ShiftRight(ty.into()), Some(Data::new(lhs, rhs)), @@ -641,6 +702,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let lhs = self.visit(*lhs); // self.ir.push(Inst::Load(ty.into()), Some(Data::lhs(lhs))) // nothing happens here because lhs is of type pointer + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); self.ir.push( Inst::GetElementPtr(ty.into()), Some(Data::new(lhs, 0)), @@ -667,6 +730,14 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { //noop? lhs } else { + let l_ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &l_ty); + let r_ty = self + .ir + .intern_pool + .from_ast1_type(AMD64_POINTER_BITS, &r_ty); self.ir.push( Inst::ExplicitCast(l_ty.into(), r_ty.into()), Some(Data::lhs(lhs)), @@ -699,6 +770,8 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } => { assert_eq!(self.tree.type_of_node(*condition), Type::Bool); let ty = self.tree.peer_type_of_nodes_unwrap(*body, *else_expr); + let ty = + self.ir.intern_pool.from_ast1_type(AMD64_POINTER_BITS, &ty); let condition = self.visit(*condition); let br = self.ir.push(Inst::Branch(condition), None); @@ -717,7 +790,7 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { let nojump = self .ir .push(Inst::Label, Some(StringsIndex::none().into())); - let phi = if let Some(ty) = Type2::try_from_ast_type(&ty) { + let phi = if ty != self.ir.intern_pool.get_void_type() { self.ir.push(Inst::Phi2(ty), Some(Data::new(lhs, rhs))) } else { br @@ -737,19 +810,20 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } } -pub struct IR { +pub struct IR<'a> { nodes: Vec, data: Vec>, + intern_pool: &'a mut InternPool, } -impl IR { - pub fn new() -> Self { +impl<'a> IR<'a> { + pub fn new(intern_pool: &'a mut InternPool) -> Self { Self { + intern_pool, nodes: Vec::new(), data: Vec::new(), } } - fn push(&mut self, inst: Inst, data: Option) -> u32 { let node = self.nodes.len() as u32; self.nodes.push(inst); @@ -757,10 +831,13 @@ impl IR { node } - pub fn build<'a, 'tree>( - &'a mut self, + pub fn build<'b, 'tree>( + &'b mut self, tree: &'tree mut Tree, - ) -> IRBuilder<'tree, 'a> { + ) -> IRBuilder<'tree, 'b, 'a> + where + 'a: 'b, + { let global_decls = tree.global_decls.clone(); let mut builder = IRBuilder::new(self, tree); @@ -796,7 +873,7 @@ impl IR { } } -impl<'tree, 'ir> IRBuilder<'tree, 'ir> { +impl IRBuilder<'_, '_, '_> { fn render_node( &self, w: &mut W, @@ -1130,18 +1207,18 @@ impl<'tree, 'ir> IRBuilder<'tree, 'ir> { } } -struct IRIter<'a> { - ir: &'a IR, +struct IRIter<'a, 'b> { + ir: &'a IR<'b>, offset: usize, item: Option<(Inst, Option)>, } -impl<'a> IRIter<'a> { +impl IRIter<'_, '_> { fn node(&self) -> u32 { self.offset as Node } } -impl<'a> Iterator for IRIter<'a> { +impl Iterator for IRIter<'_, '_> { type Item = (Inst, Option); fn next(&mut self) -> Option { @@ -1155,15 +1232,15 @@ impl<'a> Iterator for IRIter<'a> { use crate::mir; -pub struct MirBuilder<'a> { - ir: IRIter<'a>, +pub struct MirBuilder<'a, 'b> { + ir: IRIter<'a, 'b>, pub strings: StringTable, pub functions: HashMap, pub globals: HashMap, } struct IrToMirMapping<'a> { - ir: &'a IR, + ir: &'a IR<'a>, mapping: BTreeMap, } @@ -1188,8 +1265,11 @@ impl<'a> IrToMirMapping<'a> { eprintln!( "does this even get hit anymore???????????????????//" ); - let ext = - mir::NodeRef(mir.gen_extern(Some(ty.mir_type()), name)); + let ty = self + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let ext = mir::NodeRef(mir.gen_extern(Some(ty), name)); self.insert(ir, ext); Some(ext) } @@ -1198,8 +1278,8 @@ impl<'a> IrToMirMapping<'a> { } } -impl<'a> MirBuilder<'a> { - pub fn new(ir: &'a IR, strings: StringTable) -> MirBuilder<'a> { +impl<'a, 'b> MirBuilder<'a, 'b> { + pub fn new(ir: &'a IR<'b>, strings: StringTable) -> MirBuilder<'a, 'b> { Self { ir: IRIter { ir, @@ -1332,7 +1412,11 @@ impl<'a> MirBuilder<'a> { mir.gen_alloca(l, r) } Inst::Load(ty) => { - let ty = mir::Type::from_bytesize_int(ty.size()); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); let src = mapping .get(&mut mir, data.unwrap().as_u32()) .unwrap() @@ -1340,20 +1424,33 @@ impl<'a> MirBuilder<'a> { mir.gen_load(ty, src) } Inst::Store(ty) => { - let ty = mir::Type::from_bytesize_int(ty.size()); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); let (src, dst) = data.unwrap().as_lhs_rhs(); let src = mapping.get(&mut mir, src).unwrap().0; let dst = mapping.get(&mut mir, dst).unwrap().0; mir.gen_store(ty, src, dst) } Inst::GetElementPtr(ty) => { - let ty = mir::Type::from_bytesize_int(ty.size()); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); let (ptr, idx) = data.unwrap().as_lhs_rhs(); let src = mapping.get(&mut mir, ptr).unwrap().0; mir.gen_get_element_ptr(ty, src, idx) } Inst::Parameter(ty) => { // let (size, _) = data.unwrap().as_lhs_rhs(); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); mir.gen_param(ty.into()) } Inst::Eq(ty) @@ -1377,47 +1474,48 @@ impl<'a> MirBuilder<'a> { _ => unreachable!(), }; - mir.gen_cmp_byte( - ty.mir_type(), - ty.is_signed(), - ord, - invert, - lhs, - rhs, - ) + let signed = self + .ir + .ir + .intern_pool + .is_type_signed(ty, AMD64_POINTER_TYPE_INFO); + let mir_ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + mir.gen_cmp_byte(mir_ty, signed, ord, invert, lhs, rhs) } Inst::Add(ty) => { let (src, dst) = data.unwrap().as_lhs_rhs(); let lhs = mapping.get(&mut mir, src).unwrap().0; let rhs = mapping.get(&mut mir, dst).unwrap().0; - match ty { - Type2::Integral(signed, bits) => match bits { - 8 => mir.gen_add(mir::Type::Byte, lhs, rhs), - 16 => mir.gen_add(mir::Type::Word, lhs, rhs), - 32 => mir.gen_add(mir::Type::DWord, lhs, rhs), - 64 => mir.gen_add(mir::Type::QWord, lhs, rhs), - 64.. => { - unimplemented!() - } - bits => { - let ty = - mir::Type::from_bitsize_int(bits as u32); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); - let sum = mir.gen_add(ty, lhs, rhs); - mir.gen_truncate_integer(sum, ty, signed, bits) - } - }, - Type2::Binary32 => { - mir.gen_add(mir::Type::SinglePrecision, lhs, rhs) + match info.bitsize { + 8 | 16 | 32 | 64 => mir.gen_add(ty, lhs, rhs), + 64.. => { + unimplemented!() } - Type2::Binary64 => { - mir.gen_add(mir::Type::DoublePrecision, lhs, rhs) + bits => { + let sum = mir.gen_add(ty, lhs, rhs); + mir.gen_truncate_integer( + sum, + ty, + info.signed, + info.bitsize as u16, + ) } - Type2::Pointer => { - mir.gen_add(mir::Type::QWord, lhs, rhs) - } - _ => unreachable!(), } } Inst::Sub(ty) => { @@ -1425,8 +1523,18 @@ impl<'a> MirBuilder<'a> { let lhs = mapping.get(&mut mir, src).unwrap().0; let rhs = mapping.get(&mut mir, dst).unwrap().0; - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let sum = mir.gen_sub(ty, lhs, rhs); if let Some((signed, bits)) = unalignment { @@ -1438,14 +1546,23 @@ impl<'a> MirBuilder<'a> { Inst::Mul(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let signed = ty.is_signed(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; - let sum = mir.gen_mul(ty, signed, lhs, rhs); + let sum = mir.gen_mul(ty, info.signed, lhs, rhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) } else { @@ -1455,14 +1572,23 @@ impl<'a> MirBuilder<'a> { Inst::Div(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let signed = ty.is_signed(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; - let sum = mir.gen_div(ty, signed, lhs, rhs); + let sum = mir.gen_div(ty, info.signed, lhs, rhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) } else { @@ -1472,14 +1598,23 @@ impl<'a> MirBuilder<'a> { Inst::Rem(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let signed = ty.is_signed(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; - let sum = mir.gen_rem(ty, signed, lhs, rhs); + let sum = mir.gen_rem(ty, info.signed, lhs, rhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) } else { @@ -1489,8 +1624,18 @@ impl<'a> MirBuilder<'a> { Inst::BitAnd(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { @@ -1512,8 +1657,18 @@ impl<'a> MirBuilder<'a> { Inst::BitOr(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { @@ -1535,9 +1690,6 @@ impl<'a> MirBuilder<'a> { Inst::BitXOr(ty) => { let (lhs, rhs) = data.unwrap().as_lhs_rhs(); - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); - let (lhs, rhs) = if self.ir.ir.nodes[lhs as usize].is_constant() { (rhs, lhs) @@ -1548,6 +1700,19 @@ impl<'a> MirBuilder<'a> { let lhs = mapping.get(&mut mir, lhs).unwrap().0; let rhs = mapping.get(&mut mir, rhs).unwrap().0; + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); + let sum = mir.gen_bitxor(ty, lhs, rhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) @@ -1560,27 +1725,28 @@ impl<'a> MirBuilder<'a> { let lhs = mapping.get(&mut mir, src).unwrap().0; let rhs = mapping.get(&mut mir, dst).unwrap().0; + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); + // TODO: check rhs type and pass it to gen_sh{l,r}? let rhs = mir.gen_truncate_integer(rhs, ty.into(), false, 8); - match ty { - Type2::Integral(signed, bits) => match bits { - 8 => mir.gen_shl(mir::Type::Byte, lhs, rhs), - 16 => mir.gen_shl(mir::Type::Word, lhs, rhs), - 32 => mir.gen_shl(mir::Type::DWord, lhs, rhs), - 64 => mir.gen_shl(mir::Type::QWord, lhs, rhs), - 64.. => { - unimplemented!() - } - bits => { - let ty = - mir::Type::from_bitsize_int(bits as u32); - let sum = mir.gen_shl(ty, lhs, rhs); - mir.gen_truncate_integer(sum, ty, signed, bits) - } - }, - _ => unreachable!(), + let sum = mir.gen_shl(ty, lhs, rhs); + if let Some((signed, bits)) = unalignment { + mir.gen_truncate_integer(sum, ty, signed, bits) + } else { + sum } } Inst::ShiftRight(ty) => { @@ -1588,44 +1754,47 @@ impl<'a> MirBuilder<'a> { let lhs = mapping.get(&mut mir, src).unwrap().0; let rhs = mapping.get(&mut mir, dst).unwrap().0; - match ty { - Type2::Integral(signed, bits) => match bits { - 8 | 16 | 32 | 64 => { - let ty = - mir::Type::from_bitsize_int(bits as u32); - if signed { - mir.gen_sar(ty, lhs, rhs) - } else { - mir.gen_shr(ty, lhs, rhs) - } - } - 64.. => { - unimplemented!() - } - bits => { - let ty = - mir::Type::from_bitsize_int(bits as u32); + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); - let sum = if signed { - mir.gen_sar(ty, lhs, rhs) - } else { - mir.gen_shr(ty, lhs, rhs) - }; + // TODO: check rhs type and pass it to gen_sh{l,r}? + let rhs = + mir.gen_truncate_integer(rhs, ty.into(), false, 8); - mir.gen_truncate_integer(sum, ty, signed, bits) - } - }, - _ => unreachable!(), + let sum = mir.gen_shr(ty, lhs, rhs); + if let Some((signed, bits)) = unalignment { + mir.gen_truncate_integer(sum, ty, signed, bits) + } else { + sum } } Inst::Not(ty) => { let lhs = data.unwrap().as_u32(); - - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); - let lhs = mapping.get(&mut mir, lhs).unwrap().0; + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); + let sum = mir.gen_not(ty, lhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) @@ -1635,12 +1804,21 @@ impl<'a> MirBuilder<'a> { } Inst::Negate(ty) => { let lhs = data.unwrap().as_u32(); - - let unalignment = ty.mir_unalignment(); - let ty = ty.mir_type(); - let lhs = mapping.get(&mut mir, lhs).unwrap().0; + let info = self + .ir + .ir + .intern_pool + .size_of_type(ty, AMD64_POINTER_TYPE_INFO); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let unalignment = + mir_unalignment(info.signed, info.bitsize); + let sum = mir.gen_negate(ty, lhs); if let Some((signed, bits)) = unalignment { mir.gen_truncate_integer(sum, ty, signed, bits) @@ -1650,48 +1828,74 @@ impl<'a> MirBuilder<'a> { } Inst::ExplicitCast(from, to) => { let lhs = data.unwrap().as_u32(); - let from_mir = from.mir_type(); - let to_mir = to.mir_type(); - let lhs = mapping.get(&mut mir, lhs).unwrap().0; - match (from, to) { - ( - Type2::Integral(a_signed, a), - Type2::Integral(b_signed, b), - ) => { - if a > b { - mir.gen_truncate_integer( - lhs, to_mir, b_signed, b, - ) - } else if a < b { - mir.gen_extend_integer( - lhs, - IntegralType::new(a_signed, a), - IntegralType::new(b_signed, b), - ) - } else { - unreachable!() - } - } - (Type2::Integral(_, _), Type2::Bool) => { - let is_zero = mir.gen_is_zero(from_mir, lhs); - mir.gen_negate(mir::Type::Byte, is_zero) - } - (Type2::Bool, Type2::Integral(b_signed, b)) => mir - .gen_extend_integer( - lhs, - IntegralType::u1(), - IntegralType::new(b_signed, b), - ), - _ => unimplemented!(), + let to_info = self + .ir + .ir + .intern_pool + .size_of_type(to, AMD64_POINTER_TYPE_INFO); + let to_ty = self + .ir + .ir + .intern_pool + .to_mir_type(to, AMD64_POINTER_TYPE_INFO); + let to_unalignment = + mir_unalignment(to_info.signed, to_info.bitsize); + + let from_info = self + .ir + .ir + .intern_pool + .size_of_type(from, AMD64_POINTER_TYPE_INFO); + let from_ty = self + .ir + .ir + .intern_pool + .to_mir_type(from, AMD64_POINTER_TYPE_INFO); + let from_unalignment = + mir_unalignment(from_info.signed, from_info.bitsize); + + if from == to { + lhs + } else if from == intern::Index::BOOL { + mir.gen_extend_integer( + lhs, + intern::TypeInfo { + bitsize: 1, + bitalign: 8, + signed: false, + }, + to_info, + ) + } else if to == intern::Index::BOOL { + let one = mir.gen_u8(0b1); + mir.gen_bitand(mir::Type::Byte, lhs, one) + } else if from_info.bitsize > to_info.bitsize { + mir.gen_truncate_integer( + lhs, + to_ty, + to_info.signed, + to_info.bitsize as u16, + ) + } else if from_info.bitsize < to_info.bitsize { + mir.gen_extend_integer(lhs, from_info, to_info) + } else { + // no resizing required + lhs } } Inst::ReturnValue(ty) => { let src = data.unwrap().as_u32(); let src = mapping.get(&mut mir, src).unwrap().0; - mir.gen_ret_val(ty.mir_type(), src) + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + + mir.gen_ret_val(ty, src) } Inst::Return => mir.gen_ret(), Inst::Jump => { @@ -1758,35 +1962,61 @@ impl<'a> MirBuilder<'a> { let (start, end) = data.unwrap().as_lhs_rhs(); variant!(&ir.nodes[end as usize -1] => Inst::InlineType(ty)); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(*ty, AMD64_POINTER_TYPE_INFO); let args = (start..(end - 1)) .map(|arg| { variant!(&ir.nodes[arg as usize] => Inst::Argument(ty)); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(*ty, AMD64_POINTER_TYPE_INFO); let arg = ir.data[arg as usize].unwrap().lhs; let arg = mapping.get(&mut mir, arg).unwrap().0; - (ty.mir_type(), arg) + (ty, arg) }) .collect::>(); - mir.gen_call(ty.mir_type(), f, args) + mir.gen_call(ty, f, args) } Inst::Phi2(ty) => { let (src, dst) = data.unwrap().as_lhs_rhs(); let lhs = mapping.get(&mut mir, src).unwrap().0; let rhs = mapping.get(&mut mir, dst).unwrap().0; + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); - mir.gen_phi2(ty.mir_type(), lhs, rhs) + mir.gen_phi2(ty, lhs, rhs) } Inst::GlobalConstant(name, ty) => { - let ext = mir.gen_extern(Some(ty.mir_type()), name); + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + let ext = mir.gen_extern(Some(ty), name); ext } Inst::Argument(_) | Inst::InlineType(_) => { continue; } - Inst::ExternRef(ty) => mir - .gen_extern(Some(ty.mir_type()), data.unwrap().as_index()), + Inst::ExternRef(ty) => { + let ty = self + .ir + .ir + .intern_pool + .to_mir_type(ty, AMD64_POINTER_TYPE_INFO); + mir.gen_extern(Some(ty), data.unwrap().as_index()) + } #[allow(unreachable_patterns)] _ => { eprintln!( @@ -1890,11 +2120,14 @@ fn u10(x: i10) -> i10 { tree.render(&mut buf).unwrap(); println!("AST:\n{buf}"); - let mut ir = IR::new(); - let builder = ir.build(&mut tree); - let mut buf = String::new(); - builder.render(&mut buf).unwrap(); - println!("IR:\n{buf}"); + 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(); + println!("IR:\n{buf}"); + } let mut mir = MirBuilder::new(&ir, tree.strings); mir.build();