idk man, intern stuff innit

This commit is contained in:
Janis 2025-08-06 22:27:00 +02:00
parent d124ae2b59
commit 76e50085a0
3 changed files with 178 additions and 148 deletions

View file

@ -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<u8> for SimpleType {
fn from(value: u8) -> Self {
match value {
impl From<u32> 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<u8> 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<SimpleType> 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<str> = 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::<u8, SimpleType>(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<Item> {
pub(super) fn get_item(&self, index: Index) -> Option<Item> {
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 { .. }
)
}

View file

@ -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!()

View file

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