From 76e50085a0947473a7dd978ae6f4d95b10c90b04 Mon Sep 17 00:00:00 2001 From: Janis Date: Wed, 6 Aug 2025 22:27:00 +0200 Subject: [PATCH] idk man, intern stuff innit --- src/ast2/intern.rs | 242 ++++++++++++++++++++++++--------------------- src/ast2/mod.rs | 64 ++++++------ src/common.rs | 20 +++- 3 files changed, 178 insertions(+), 148 deletions(-) diff --git a/src/ast2/intern.rs b/src/ast2/intern.rs index 09df5f6..d541c69 100644 --- a/src/ast2/intern.rs +++ b/src/ast2/intern.rs @@ -15,7 +15,7 @@ use crate::{ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[repr(u8)] pub enum SimpleType { - F32 = 0, + F32, F64, Bool, Void, @@ -28,11 +28,14 @@ pub enum SimpleType { /// Bottom type: this is the subtype of all types, and it can coerce into a value of any type. /// Akin to Rust's `!`. Bottom, + UInt(u16), + SInt(u16), } -impl From for SimpleType { - fn from(value: u8) -> Self { - match value { +impl From for SimpleType { + fn from(value: u32) -> Self { + let [discriminant, bits] = *crate::common::u32_as_u16_slice(&value); + match discriminant { 0 => Self::F32, 1 => Self::F64, 2 => Self::Bool, @@ -40,28 +43,49 @@ impl From for SimpleType { 4 => Self::USize, 5 => Self::ISize, 6 => Self::ComptimeInt, + 7 => Self::Top, + 8 => Self::Bottom, + 9 => Self::UInt(bits), + 10 => Self::SInt(bits), _ => panic!("{value} is not a simple type"), } } } +impl From for u32 { + fn from(value: SimpleType) -> Self { + match value { + SimpleType::F32 => crate::common::u32_from_u16_slice(&[0, 0]), + SimpleType::F64 => crate::common::u32_from_u16_slice(&[1, 0]), + SimpleType::Bool => crate::common::u32_from_u16_slice(&[2, 0]), + SimpleType::Void => crate::common::u32_from_u16_slice(&[3, 0]), + SimpleType::USize => crate::common::u32_from_u16_slice(&[4, 0]), + SimpleType::ISize => crate::common::u32_from_u16_slice(&[5, 0]), + SimpleType::ComptimeInt => crate::common::u32_from_u16_slice(&[6, 0]), + SimpleType::Top => crate::common::u32_from_u16_slice(&[7, 0]), + SimpleType::Bottom => crate::common::u32_from_u16_slice(&[8, 0]), + SimpleType::UInt(bits) => crate::common::u32_from_u16_slice(&[9, bits]), + SimpleType::SInt(bits) => crate::common::u32_from_u16_slice(&[10, bits]), + } + } +} + impl Display for SimpleType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - SimpleType::F32 => "f32", - SimpleType::F64 => "f64", - SimpleType::Bool => "bool", - SimpleType::Void => "void", - SimpleType::USize => "usize", - SimpleType::ISize => "isize", - SimpleType::ComptimeInt => "comptime_int", - SimpleType::Top => "⊤", - SimpleType::Bottom => "⊥", - } - ) + let fmt: std::borrow::Cow = match self { + SimpleType::F32 => "f32".into(), + SimpleType::F64 => "f64".into(), + SimpleType::Bool => "bool".into(), + SimpleType::Void => "void".into(), + SimpleType::USize => "usize".into(), + SimpleType::ISize => "isize".into(), + SimpleType::ComptimeInt => "comptime_int".into(), + SimpleType::Top => "⊤".into(), + SimpleType::Bottom => "⊥".into(), + SimpleType::UInt(bits) => format!("u{bits}").into(), + SimpleType::SInt(bits) => format!("i{bits}").into(), + }; + write!(f, "{fmt}",) } } @@ -78,8 +102,6 @@ pub enum Tag { F64, PositiveInt, NegativeInt, - UIntType, - SIntType, SimpleType, PointerType, ArrayType, @@ -88,9 +110,9 @@ pub enum Tag { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -struct Item { - tag: Tag, - index: u32, +pub(super) struct Item { + pub(super) tag: Tag, + pub(super) index: u32, } #[derive(Debug, Clone, PartialEq)] @@ -126,12 +148,6 @@ pub enum Key<'a> { NegativeInt { bigint: BigInt, }, - UIntType { - bit_width: u16, - }, - SIntType { - bit_width: u16, - }, SimpleType { ty: SimpleType, }, @@ -178,8 +194,6 @@ impl Display for KeyDisplay<'_> { Key::F64 { bits } => write!(f, "{bits}")?, Key::PositiveInt { ref bigint } => write!(f, "{bigint}")?, Key::NegativeInt { ref bigint } => write!(f, "{bigint}")?, - Key::UIntType { bit_width } => write!(f, "u{bit_width}")?, - Key::SIntType { bit_width } => write!(f, "i{bit_width}")?, Key::SimpleType { ty } => write!(f, "{ty}")?, Key::PointerType { pointee, flags } => { write!(f, "*{flags}{}", self.ip.display_key(pointee))? @@ -238,8 +252,6 @@ 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 { 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 { @@ -544,20 +556,20 @@ static_keys!( 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 }, + I0 => Key::SimpleType { ty: SimpleType::SInt(0) }, + U0 => Key::SimpleType { ty: SimpleType::UInt(0) }, + I1 => Key::SimpleType { ty: SimpleType::SInt(1) }, + U1 => Key::SimpleType { ty: SimpleType::UInt(1) }, + I8 => Key::SimpleType { ty: SimpleType::SInt(8) }, + U8 => Key::SimpleType { ty: SimpleType::UInt(8) }, + I16 => Key::SimpleType { ty: SimpleType::SInt(16) }, + U16 => Key::SimpleType { ty: SimpleType::UInt(16) }, + I32 => Key::SimpleType { ty: SimpleType::SInt(32) }, + U32 => Key::SimpleType { ty: SimpleType::UInt(32) }, + I64 => Key::SimpleType { ty: SimpleType::SInt(64) }, + U64 => Key::SimpleType { ty: SimpleType::UInt(64) }, + I128 => Key::SimpleType { ty: SimpleType::SInt(128) }, + U128 => Key::SimpleType { ty: SimpleType::UInt(128) }, TRUE => Key::TrueValue, FALSE => Key::FalseValue, EMPTY_STRING => Key::String { str: "" }, @@ -606,41 +618,51 @@ impl InternPool { ty: SimpleType::ISize, }) } + // Assumes the type is present in the pool. + fn get_simple_type_unchecked(&self, ty: SimpleType) -> Index { + self.get_assume_present(&Key::SimpleType { ty }) + } pub fn get_u0_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 0 }) + self.get_simple_type_unchecked(SimpleType::UInt(0)) } pub fn get_i0_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 0 }) + self.get_simple_type_unchecked(SimpleType::SInt(0)) } pub fn get_u1_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 1 }) + self.get_simple_type_unchecked(SimpleType::UInt(1)) } pub fn get_i1_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 1 }) + self.get_simple_type_unchecked(SimpleType::SInt(1)) } pub fn get_u8_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 8 }) + self.get_simple_type_unchecked(SimpleType::UInt(8)) } pub fn get_i8_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 8 }) + self.get_simple_type_unchecked(SimpleType::SInt(8)) } pub fn get_u16_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 16 }) + self.get_simple_type_unchecked(SimpleType::UInt(16)) } pub fn get_i16_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 16 }) + self.get_simple_type_unchecked(SimpleType::SInt(16)) } pub fn get_u32_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 32 }) + self.get_simple_type_unchecked(SimpleType::UInt(32)) } pub fn get_i32_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 32 }) + self.get_simple_type_unchecked(SimpleType::SInt(32)) } pub fn get_u64_type(&self) -> Index { - self.get_assume_present(&Key::UIntType { bit_width: 64 }) + self.get_simple_type_unchecked(SimpleType::UInt(64)) } pub fn get_i64_type(&self) -> Index { - self.get_assume_present(&Key::SIntType { bit_width: 64 }) + self.get_simple_type_unchecked(SimpleType::SInt(64)) + } + pub fn get_u128_type(&self) -> Index { + self.get_simple_type_unchecked(SimpleType::UInt(128)) + } + pub fn get_i128_type(&self) -> Index { + self.get_simple_type_unchecked(SimpleType::SInt(128)) } pub fn get_top_type(&self) -> Index { @@ -700,8 +722,9 @@ impl InternPool { | Key::SimpleType { ty: SimpleType::ISize, } - | Key::SIntType { .. } - | Key::UIntType { .. }, + | Key::SimpleType { + ty: SimpleType::SInt(_) | SimpleType::UInt(_), + }, ) => Some(rhs), ( Key::SimpleType { @@ -716,8 +739,9 @@ impl InternPool { | Key::SimpleType { ty: SimpleType::ISize, } - | Key::SIntType { .. } - | Key::UIntType { .. }, + | Key::SimpleType { + ty: SimpleType::SInt(_) | SimpleType::UInt(_), + }, Key::SimpleType { ty: SimpleType::ComptimeInt, }, @@ -745,15 +769,6 @@ impl InternPool { 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, @@ -762,6 +777,9 @@ impl InternPool { todo!("void can't be turned into a mir type") } SimpleType::ISize | SimpleType::USize => Type::QWord, + SimpleType::UInt(bits) | SimpleType::SInt(bits) => { + Type::from_bitsize_int(bits as u32) + } SimpleType::Top | SimpleType::Bottom | SimpleType::ComptimeInt => { panic!("{ty} can't be turned into a mir type") } @@ -782,11 +800,9 @@ impl InternPool { 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, + SimpleType::USize | SimpleType::UInt(_) => false, + SimpleType::ISize | SimpleType::SInt(_) => true, _ => false, }, Key::PointerType { .. } => false, @@ -799,23 +815,17 @@ impl InternPool { 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::SInt(bits) => TypeInfo { + bitsize: bits as u32, + bitalign: (bits as u32).next_multiple_of(8).next_power_of_two(), + signed: true, + }, + SimpleType::UInt(bits) => TypeInfo { + bitsize: bits as u32, + bitalign: (bits as u32).next_multiple_of(8).next_power_of_two(), + signed: false, + }, SimpleType::F32 => TypeInfo { bitsize: 32, bitalign: 32, @@ -889,9 +899,13 @@ impl InternPool { crate::ast::Type::ComptimeNumber => self.get_comptime_int_type(), crate::ast::Type::Integer(i) => self.get_or_insert({ if i.signed { - Key::SIntType { bit_width: i.bits } + Key::SimpleType { + ty: SimpleType::SInt(i.bits), + } } else { - Key::UIntType { bit_width: i.bits } + Key::SimpleType { + ty: SimpleType::UInt(i.bits), + } } }), crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(), @@ -930,9 +944,13 @@ 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 { bit_width: i.bits } + Key::SimpleType { + ty: SimpleType::SInt(i.bits), + } } else { - Key::UIntType { bit_width: i.bits } + Key::SimpleType { + ty: SimpleType::UInt(i.bits), + } } }), crate::ast::Type::Floating(crate::ast::FloatingType::Binary32) => self.get_f32_type(), @@ -968,11 +986,11 @@ impl InternPool { pub fn as_ast1_type(&self, pointer_bits: u16, index: Index) -> crate::ast::Type { use crate::ast::Type; match self.get_key(index) { - Key::UIntType { bit_width: bits } => Type::Integer(IntegralType::new(false, bits)), - Key::SIntType { bit_width: bits } => Type::Integer(IntegralType::new(true, bits)), Key::SimpleType { ty } => match ty { SimpleType::F32 => Type::Floating(crate::ast::FloatingType::Binary32), SimpleType::F64 => Type::Floating(crate::ast::FloatingType::Binary64), + SimpleType::SInt(bits) => Type::Integer(IntegralType::new(true, bits)), + SimpleType::UInt(bits) => Type::Integer(IntegralType::new(false, bits)), SimpleType::Bool => Type::Bool, SimpleType::Void => Type::Void, SimpleType::USize => Type::Integer(IntegralType::new(false, pointer_bits)), @@ -1098,9 +1116,7 @@ impl InternPool { self.create_item(Tag::NegativeInt, i) } - Key::UIntType { bit_width: bits } => self.create_item(Tag::UIntType, bits as u32), - Key::SIntType { bit_width: bits } => self.create_item(Tag::SIntType, bits as u32), - Key::SimpleType { ty } => self.create_item(Tag::SimpleType, ty as u8 as u32), + Key::SimpleType { ty } => self.create_item(Tag::SimpleType, ty.into()), Key::PointerType { pointee, flags } => { let flags = flags.pack(); let i = self.extend_words([pointee.index() as u32, flags as u32]); @@ -1230,17 +1246,11 @@ impl InternPool { let bigint = BigInt::from_biguint(Sign::Plus, data); Key::PositiveInt { bigint } } - Tag::SIntType => Key::SIntType { - bit_width: item.index as u16, - }, - Tag::UIntType => Key::UIntType { - bit_width: item.index as u16, - }, Tag::SimpleType => { - let ty = item.idx() as u8; + let ty = item.idx() as u32; Key::SimpleType { - ty: unsafe { core::mem::transmute::(ty) }, + ty: SimpleType::from(ty), } } Tag::PointerType => { @@ -1337,8 +1347,12 @@ impl InternPool { pub fn get_int_type(&mut self, signed: bool, bits: u16) -> Index { let key = match signed { - true => Key::SIntType { bit_width: bits }, - false => Key::UIntType { bit_width: bits }, + true => Key::SimpleType { + ty: SimpleType::SInt(bits), + }, + false => Key::SimpleType { + ty: SimpleType::UInt(bits), + }, }; self.get_or_insert(key) @@ -1535,7 +1549,7 @@ impl InternPool { ((index.index() as u32) < self.len()).then_some(index) } - fn get_item(&self, index: Index) -> Option { + pub(super) fn get_item(&self, index: Index) -> Option { self.check_bounds(index).map(|i| Item { tag: self.tags[i.index()], index: self.indices[i.index()], @@ -1554,8 +1568,6 @@ impl InternPool { | Key::ArrayType { .. } | Key::PointerType { .. } | Key::SimpleType { .. } - | Key::SIntType { .. } - | Key::UIntType { .. } | Key::StructType { .. } ) } diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index cf27e46..1cfdc91 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -2134,36 +2134,6 @@ where let ty_key = ip.get_key(ty); let signed = ip.is_type_signed(ty, AMD64_POINTER_TYPE_INFO); match ty_key { - intern::Key::SIntType { bit_width: bits } | intern::Key::UIntType { bit_width: bits } => { - let ty = IntegralType::new(signed, bits); - match ip.get_key(val) { - intern::Key::SIntSmall { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::UIntSmall { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::SInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::UInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { - bits: bits as _, - ty, - }), - intern::Key::PositiveInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) - } - intern::Key::NegativeInt { bigint } => { - ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) - } - _ => { - unreachable!() - } - } - } intern::Key::SimpleType { ty } => match ty { intern::SimpleType::F32 => match ip.get_key(val) { intern::Key::F32 { bits } => { @@ -2256,6 +2226,40 @@ where intern::SimpleType::Top | intern::SimpleType::Bottom => { unreachable!() } + intern::SimpleType::UInt(bits) | intern::SimpleType::SInt(bits) => { + let ty = IntegralType::new(signed, bits); + match ip.get_key(val) { + intern::Key::SIntSmall { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::UIntSmall { bits } => { + ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }) + } + intern::Key::SInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }), + intern::Key::UInt64 { bits } => ComptimeNumber::Integral(ComptimeInt::Native { + bits: bits as _, + ty, + }), + intern::Key::PositiveInt { bigint } => { + ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + } + intern::Key::NegativeInt { bigint } => { + ComptimeNumber::Integral(ComptimeInt::BigInt { bits: bigint, ty }) + } + _ => { + unreachable!() + } + } + } }, _ => { unreachable!() diff --git a/src/common.rs b/src/common.rs index b95e9cd..e2bba03 100644 --- a/src/common.rs +++ b/src/common.rs @@ -72,9 +72,7 @@ pub fn is_oct_digit(ch: char) -> bool { } pub fn is_hex_digit(ch: char) -> bool { - ('0'..='9').contains(&ch) - || ('a'..='f').contains(&ch) - || ('A'..='F').contains(&ch) + ('0'..='9').contains(&ch) || ('a'..='f').contains(&ch) || ('A'..='F').contains(&ch) } /// Trait for only yielding the next item in the Iterator if it tests true for some predicate @@ -176,3 +174,19 @@ pub fn from_lo_hi_dwords(lo: u32, hi: u32) -> u64 { pub fn into_lo_hi_dwords(qword: u64) -> (u32, u32) { (qword as u32, (qword >> 32) as u32) } + +pub fn u32_as_u16_slice(value: &u32) -> &[u16; 2] { + // SAFETY: This is safe because u32 is guaranteed to be 4 bytes and + // we are creating a slice of 2 u16s which is also 4 bytes. + unsafe { &*(value as *const u32 as *const [u16; 2]) } +} + +// we can't transform any &[u16; 2] into a &u32 because of alignment guarantees +pub fn u32_from_u16_slice(slice: &[u16; 2]) -> u32 { + let mut out = 0u32; + unsafe { + core::ptr::copy_nonoverlapping(slice.as_ptr(), &raw mut out as *mut u16, 2); + } + + out +}