Big restructure pt.2

This commit is contained in:
Mia
2026-02-27 02:20:45 +01:00
parent f4334e79f6
commit 4b07d93ae3
14 changed files with 305 additions and 548 deletions
+11 -142
View File
@@ -1,16 +1,11 @@
use crate::{
assembly::intrinsic_types::make_intrinsic_types,
functions::Function,
types::{
Type,
derivations::{FuncT, TypeDerivations},
intrinsics::*,
},
values::{Const, ConstData, Int},
types::derivations::{FuncT, TypeDerivations},
values::AnyConst,
};
use derive_more::Debug;
use leaf_allocators::SyncAllocator;
use scc::HashMap;
use scc::{HashMap, HashSet};
use std::{borrow::Cow, hash::Hash, sync::OnceLock};
#[derive(derive_more::Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -33,8 +28,6 @@ pub type Ctx<'l> = &'l Context<'l>;
pub struct Context<'l> {
pub(crate) alloc: &'l dyn SyncAllocator,
pub(crate) derivations: TypeDerivations<'l>,
constants: HashMap<&'l ConstData<'l>, &'l Const<'l>>,
intrinsics: OnceLock<Box<intrinsic_types::IntrinsicTypesArray<'l>>>,
assemblies: HashMap<AssemblyIdentifier, &'l Assembly<'l>>,
}
@@ -54,17 +47,11 @@ impl Hash for Context<'_> {
impl<'l> Context<'l> {
pub fn new(alloc: &'l dyn SyncAllocator) -> &'l Self {
let ctx = alloc.alloc(Self {
alloc.alloc(Self {
alloc,
constants: HashMap::new(),
derivations: TypeDerivations::new(alloc),
intrinsics: OnceLock::new(),
assemblies: Default::default(),
});
ctx.intrinsics
.set(Box::new(make_intrinsic_types(ctx)))
.unwrap();
ctx
})
}
pub fn get_assembly(&'l self, ident: &AssemblyIdentifier) -> Option<&'l Assembly<'l>> {
@@ -86,10 +73,10 @@ pub struct Assembly<'l> {
ident: AssemblyIdentifier,
#[debug("{:#?}", {
let mut c = vec![];
constants.iter_sync(|k, _| {c.push(*k); true});
constants.iter_sync(|k| {c.push(*k); true});
c
})]
constants: HashMap<&'l Const<'l>, &'l Const<'l>>,
constants: HashSet<AnyConst<'l>>,
}
impl Eq for Assembly<'_> {}
@@ -111,7 +98,7 @@ impl<'l> Assembly<'l> {
let assembly = ctx.alloc.alloc(Self {
ctx,
ident,
constants: HashMap::new(),
constants: HashSet::new(),
});
assembly
}
@@ -127,127 +114,9 @@ impl<'l> Assembly<'l> {
body: OnceLock::new(),
declaring_assembly: self,
});
let constant = self.ctx.alloc.alloc(Const {
ctx: self.ctx,
data: ConstData::Function(func),
});
self.constants.insert_sync(constant, constant).unwrap();
self.constants
.insert_sync(AnyConst::Function(func))
.unwrap();
func
}
}
pub trait CreateConst<'l, T> {
fn create_const(&'l self, value: T) -> &'l Const<'l>;
}
macro_rules! create_const {
($(impl $ty:ty : $expr:expr,)*) => {
$(
impl<'l> CreateConst<'l, $ty> for Context<'l> {
fn create_const(&'l self, value: $ty) -> &'l Const<'l> {
let constant = ($expr)(self, value);
if let Some(existing) = self.constants.get_sync(&constant.data) {
return *existing;
}
let constant = self.alloc.alloc(constant);
*self.constants.entry_sync(&constant.data).or_insert(constant)
}
}
)*
};
}
create_const! {
impl i8: |ctx, val| Const { ctx, data: ConstData::Int(Int::I8(val)) },
impl i16: |ctx, val| Const { ctx, data: ConstData::Int(Int::I16(val)) },
impl i32: |ctx, val| Const { ctx, data: ConstData::Int(Int::I32(val)) },
impl i64: |ctx, val| Const { ctx, data: ConstData::Int(Int::I64(val)) },
impl i128: |ctx, val| Const { ctx, data: ConstData::Int(Int::I128(val)) },
impl u8: |ctx, val| Const { ctx, data: ConstData::Int(Int::U8(val)) },
impl u16: |ctx, val| Const { ctx, data: ConstData::Int(Int::U16(val)) },
impl u32: |ctx, val| Const { ctx, data: ConstData::Int(Int::U32(val)) },
impl u64: |ctx, val| Const { ctx, data: ConstData::Int(Int::U64(val)) },
impl u128: |ctx, val| Const { ctx, data: ConstData::Int(Int::U128(val)) },
impl (): |ctx, _| Const { ctx, data: ConstData::Void },
impl char: |ctx, val| Const { ctx, data: ConstData::Char(val) },
impl bool: |ctx, val| Const { ctx, data: ConstData::Bool(val) },
impl &'l str: |ctx, val| Const { ctx, data: ConstData::Str(val) },
}
mod intrinsic_types {
use super::*;
use std::mem::MaybeUninit;
macro_rules! create_intrinsics {
($(($id:ident, $fn_id:ident, $init:expr),)*) => {
pub enum IntrinsicTypeKind {
$($id,)*
COUNT,
}
pub type IntrinsicTypesArray<'l> = [Type<'l>; IntrinsicTypeKind::COUNT as usize];
pub fn make_intrinsic_types<'l>(ctx: &'l Context<'l>) -> IntrinsicTypesArray<'l> {
unsafe {
const C: usize = IntrinsicTypeKind::COUNT as usize;
let mut intrinsics = [MaybeUninit::<Type>::uninit(); C];
$(
intrinsics[IntrinsicTypeKind::$id as usize]
.write((&*ctx.alloc.alloc($init(ctx))).into());
)*
std::mem::transmute(intrinsics)
}
}
impl<'l> Context<'l> {
$(
#[inline]
pub fn $fn_id(&'l self) -> Type<'l> {
self.get_intrinsic(IntrinsicTypeKind::$id)
}
)*
#[inline]
fn get_intrinsic(&'l self, intrinsic: IntrinsicTypeKind) -> Type<'l> {
unsafe {
self.intrinsics
.get()
.unwrap_unchecked()
.get_unchecked(intrinsic as usize)
.clone()
}
}
}
};
}
create_intrinsics! {
(Void, void_t, |ctx| VoidT { ctx }),
(Char, char_t, |ctx| CharT { ctx }),
(Bool, bool_t, |ctx| BoolT { ctx }),
(Type, type_t, |ctx| TypeT { ctx, }),
(ConstStr, const_str_t, |ctx| ConstStrT { ctx, }),
(I8, i8_t, |ctx| IntT { ctx, signed: true, precision: 8 }),
(I16, i16_t, |ctx| IntT { ctx, signed: true, precision: 16 }),
(I32, i32_t, |ctx| IntT { ctx, signed: true, precision: 32 }),
(I64, i64_t, |ctx| IntT { ctx, signed: true, precision: 64 }),
(I128, i128_t, |ctx| IntT { ctx, signed: true, precision: 128 }),
(ISize, isize_t, |ctx| IntT { ctx, signed: true, precision: u32::MAX }),
(U8, u8_t, |ctx| IntT { ctx, signed: false, precision: 8 }),
(U16, u16_t, |ctx| IntT { ctx, signed: false, precision: 16 }),
(U32, u32_t, |ctx| IntT { ctx, signed: false, precision: 32 }),
(U64, u64_t, |ctx| IntT { ctx, signed: false, precision: 64 }),
(U128, u128_t, |ctx| IntT { ctx, signed: false, precision: 128 }),
(USize, usize_t, |ctx| IntT { ctx, signed: false, precision: u32::MAX }),
(F16, f16_t, |ctx| FloatT { ctx, precision: 16 }),
(F32, f32_t, |ctx| FloatT { ctx, precision: 32 }),
(F64, f64_t, |ctx| FloatT { ctx, precision: 64 }),
}
}
+9 -15
View File
@@ -4,7 +4,7 @@ use crate::{
types::{Type, derivations::*},
values::{Value, ValueFlags},
};
use derive_more::Debug;
use derive_more::{Debug, Display};
use std::{borrow::Cow, cell::UnsafeCell, hash::Hash, ops::Deref, sync::OnceLock};
// Maybe unsafe but honestly it's extremely unlikely that this will go wrong and it won't cause any issues.
@@ -12,8 +12,9 @@ struct Id(UnsafeCell<u32>);
unsafe impl Send for Id {}
unsafe impl Sync for Id {}
#[derive(Debug)]
#[derive(Debug, Display)]
#[debug("{variant:?}")]
#[display("%{}", unsafe { *id.0.get() })]
pub struct Instruction<'l> {
id: Id,
pub parent_block: &'l Block<'l>,
@@ -45,13 +46,6 @@ impl<'l> Deref for Instruction<'l> {
}
}
impl<'l> Into<Value<'l>> for &'l Instruction<'l> {
#[inline]
fn into(self) -> Value<'l> {
Value::Instruction(self)
}
}
impl<'l> Instruction<'l> {
#[inline]
pub fn ctx(&self) -> Ctx<'l> {
@@ -69,10 +63,10 @@ impl<'l> Instruction<'l> {
}
}
pub fn value_ty(&self) -> Type<'l> {
pub fn value_ty(&'l self) -> Type<'l> {
match self.variant {
InstructionVariant::Return(_) => self.ctx().void_t(),
InstructionVariant::Store(_, _) => self.ctx().void_t(),
InstructionVariant::Return(_) => Type::Void,
InstructionVariant::Store(_, _) => Type::Void,
InstructionVariant::StackAlloc(ty) => ty.make_ptr(true).into(),
InstructionVariant::Load(value) => match value.ty() {
Type::Ptr(PtrT { base, .. }) => *base,
@@ -80,7 +74,7 @@ impl<'l> Instruction<'l> {
},
InstructionVariant::IAdd(a, _) => a.ty(),
InstructionVariant::FAdd(a, _) => a.ty(),
InstructionVariant::ICmp(_, _, _) => self.ctx().bool_t(),
InstructionVariant::ICmp(_, _, _) => Type::Bool,
_ => todo!("{self:?}"),
}
}
@@ -299,7 +293,7 @@ impl<'l> BlockBuilder<'l> {
if !std::ptr::eq(false_case.func, self.block.func) {
return Err("Block does not belong to this function.".into());
}
if !matches!(cond.ty(), Type::Bool(_)) {
if !matches!(cond.ty(), Type::Bool) {
return Err(format!("Expected value of type `bool`, found `{}`.", cond.ty()).into());
}
let inst = self.push_instruction(InstructionVariant::Branch {
@@ -342,7 +336,7 @@ impl<'l> BlockBuilder<'l> {
let ret_t = self.block.func.ty.ret_t;
let value_ty = match value {
Some(v) => v.ty(),
None => self.block.func.ctx().void_t(),
None => Type::Void,
};
if value_ty != ret_t {
return Err(format!(
+10 -37
View File
@@ -78,7 +78,7 @@ impl Hash for TypeDerivations<'_> {
}
#[non_exhaustive]
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display("*{}{}", if *mutable { "mut " } else { "" }, *base)]
pub struct PtrT<'l> {
#[debug("{base}")]
@@ -86,14 +86,8 @@ pub struct PtrT<'l> {
pub mutable: bool,
}
impl<'l> Into<Type<'l>> for &'l PtrT<'l> {
fn into(self) -> Type<'l> {
Type::Ptr(self)
}
}
#[non_exhaustive]
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display("&{}{}", if *mutable { "mut " } else { "" }, *base)]
pub struct RefT<'l> {
#[debug("{base}")]
@@ -101,12 +95,6 @@ pub struct RefT<'l> {
pub mutable: bool,
}
impl<'l> Into<Type<'l>> for &'l RefT<'l> {
fn into(self) -> Type<'l> {
Type::Ref(self)
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FuncT<'l> {
@@ -127,33 +115,18 @@ impl Display for FuncT<'_> {
}
}
impl<'l> Into<Type<'l>> for &'l FuncT<'l> {
fn into(self) -> Type<'l> {
Type::Func(self)
}
}
pub trait MakeTypeDerivations<'l> {
fn make_ptr(self, mutable: bool) -> &'l PtrT<'l>;
fn make_ref(self, mutable: bool) -> &'l RefT<'l>;
fn make_fn(self, par_t: impl IntoIterator<Item = Type<'l>>) -> &'l FuncT<'l>;
}
impl<'l, T: 'l + Into<Type<'l>>> MakeTypeDerivations<'l> for T {
fn make_ptr(self, mutable: bool) -> &'l PtrT<'l> {
let ty = self.into();
ty.ctx().derivations.make_ptr(ty, mutable)
impl<'l> Type<'l> {
pub fn make_ptr(&self, mutable: bool) -> &'l PtrT<'l> {
self.ctx().derivations.make_ptr(*self, mutable)
}
fn make_ref(self, mutable: bool) -> &'l RefT<'l> {
let ty = self.into();
ty.ctx().derivations.make_ref(ty, mutable)
pub fn make_ref(&self, mutable: bool) -> &'l RefT<'l> {
self.ctx().derivations.make_ref(*self, mutable)
}
fn make_fn(self, par_t: impl IntoIterator<Item = Type<'l>>) -> &'l FuncT<'l> {
let ty = self.into();
ty.ctx()
pub fn make_fn(&self, par_t: impl IntoIterator<Item = Type<'l>>) -> &'l FuncT<'l> {
self.ctx()
.derivations
.make_fn(ty, par_t.into_iter().collect())
.make_fn(*self, par_t.into_iter().collect())
}
}
-103
View File
@@ -1,103 +0,0 @@
use crate::{assembly::Ctx, types::Type};
use derive_more::{Debug, Display};
use std::fmt::Display;
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("type")]
#[debug("type")]
pub struct TypeT<'l> {
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l TypeT<'l> {
fn into(self) -> Type<'l> {
Type::Type(self)
}
}
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("void")]
#[debug("void")]
pub struct VoidT<'l> {
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l VoidT<'l> {
fn into(self) -> Type<'l> {
Type::Void(self)
}
}
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("char")]
#[debug("char")]
pub struct CharT<'l> {
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l CharT<'l> {
fn into(self) -> Type<'l> {
Type::Char(self)
}
}
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("bool")]
#[debug("bool")]
pub struct BoolT<'l> {
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l BoolT<'l> {
fn into(self) -> Type<'l> {
Type::Bool(self)
}
}
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("const_str")]
#[debug("const_str")]
pub struct ConstStrT<'l> {
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l ConstStrT<'l> {
fn into(self) -> Type<'l> {
Type::ConstStr(self)
}
}
#[non_exhaustive]
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display(
"{}{}",
if *signed { "i" } else { "u" },
if *precision == u32::MAX { &"size" as &dyn Display } else { precision })
]
#[debug("{self}")]
pub struct IntT<'l> {
pub signed: bool,
pub precision: u32,
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l IntT<'l> {
fn into(self) -> Type<'l> {
Type::Int(self)
}
}
#[non_exhaustive]
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("f{}", precision)]
#[debug("{self}")]
pub struct FloatT<'l> {
pub precision: u32,
pub(crate) ctx: Ctx<'l>,
}
impl<'l> Into<Type<'l>> for &'l FloatT<'l> {
fn into(self) -> Type<'l> {
Type::Float(self)
}
}
+84 -31
View File
@@ -1,26 +1,47 @@
pub mod derivations;
pub mod intrinsics;
use crate::{assembly::Context, types::derivations::*};
use derive_more::{Debug, Display, From, TryInto};
use leaf_allocators::SyncArenaAllocator;
use std::{fmt::Display, sync::OnceLock};
use crate::{
assembly::Ctx,
types::{derivations::*, intrinsics::*},
};
use derive_more::{Debug, Display};
pub mod derivations;
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display(
"{}{}",
if *signed { "i" } else { "u" },
if *precision == u32::MAX { &"size" as &dyn Display } else { precision })
]
#[debug("{self}")]
pub struct IntT {
pub signed: bool,
pub precision: u32,
}
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display("f{}", precision)]
#[debug("{self}")]
pub struct FloatT {
pub precision: u32,
}
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
pub enum Type<'l> {
Void(&'l VoidT<'l>),
Char(&'l CharT<'l>),
Bool(&'l BoolT<'l>),
Void,
Char,
Bool,
Type,
ConstStr,
#[debug("{_0:?}")]
#[display("{_0}")]
Int(&'l IntT<'l>),
Int(IntT),
#[debug("{_0:?}")]
#[display("{_0}")]
Float(&'l FloatT<'l>),
Float(FloatT),
#[debug("{_0:?}")]
#[display("{_0}")]
@@ -33,29 +54,61 @@ pub enum Type<'l> {
#[debug("{_0:?}")]
#[display("{_0}")]
Func(&'l FuncT<'l>),
#[debug("{_0:?}")]
#[display("{_0}")]
Type(&'l TypeT<'l>),
#[debug("{_0:?}")]
#[display("{_0}")]
ConstStr(&'l ConstStrT<'l>),
}
impl<'l> Type<'l> {
pub fn ctx(&self) -> Ctx<'l> {
pub fn ctx(&self) -> &'l Context<'l> {
match self.non_default_ctx() {
Some(ctx) => ctx,
None => unsafe {
static DEFAULT: OnceLock<&'static Context> = OnceLock::new();
static ALLOCATOR: OnceLock<SyncArenaAllocator> = OnceLock::new();
let ctx: &'static Context = DEFAULT.get_or_init(|| {
let allocator: &'static SyncArenaAllocator =
ALLOCATOR.get_or_init(|| SyncArenaAllocator::default());
Context::new(allocator)
});
std::mem::transmute(ctx)
},
}
}
fn non_default_ctx(&self) -> Option<&'l Context<'l>> {
match self {
Type::Void(t) => t.ctx,
Type::Char(t) => t.ctx,
Type::Bool(t) => t.ctx,
Type::Int(t) => t.ctx,
Type::Float(t) => t.ctx,
Type::Ptr(t) => t.base.ctx(),
Type::Ref(t) => t.base.ctx(),
Type::Func(t) => t.ret_t.ctx(),
Type::Type(t) => t.ctx,
Type::ConstStr(t) => t.ctx,
Type::Void => None,
Type::Char => None,
Type::Bool => None,
Type::Type => None,
Type::ConstStr => None,
Type::Int(_) => None,
Type::Float(_) => None,
Type::Ptr(_) => None,
Type::Ref(_) => None,
Type::Func(f) => match f.ret_t.non_default_ctx() {
Some(ctx) => Some(ctx),
None => f.par_t.iter().find_map(|t| t.non_default_ctx()),
},
}
}
}
#[rustfmt::skip]
impl Type<'_> {
pub const I8: Self = Type::Int(IntT { signed: true, precision: 8 });
pub const I16: Self = Type::Int(IntT { signed: true, precision: 16 });
pub const I32: Self = Type::Int(IntT { signed: true, precision: 32 });
pub const I64: Self = Type::Int(IntT { signed: true, precision: 64 });
pub const I128: Self = Type::Int(IntT { signed: true, precision: 128 });
pub const ISIZE: Self = Type::Int(IntT { signed: true, precision: u32::MAX });
pub const U8: Self = Type::Int(IntT { signed: false, precision: 8 });
pub const U16: Self = Type::Int(IntT { signed: false, precision: 16 });
pub const U32: Self = Type::Int(IntT { signed: false, precision: 32 });
pub const U64: Self = Type::Int(IntT { signed: false, precision: 64 });
pub const U128: Self = Type::Int(IntT { signed: false, precision: 128 });
pub const USIZE: Self = Type::Int(IntT { signed: false, precision: u32::MAX });
pub const F16: Self = Type::Float(FloatT { precision: 16 });
pub const F32: Self = Type::Float(FloatT { precision: 32 });
pub const F64: Self = Type::Float(FloatT { precision: 64 });
}
+104
View File
@@ -0,0 +1,104 @@
use crate::{functions::Function, types::Type};
use derive_more::{Debug, *};
use half::f16;
use std::hash::Hash;
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
pub enum Int {
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
}
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq)]
pub enum Float {
F16(f16),
F32(f32),
F64(f64),
}
impl Eq for Float {}
impl Hash for Float {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
Float::F16(v) => v.to_ne_bytes().hash(state),
Float::F32(v) => v.to_ne_bytes().hash(state),
Float::F64(v) => v.to_ne_bytes().hash(state),
}
}
}
#[derive(Debug, Display, Deref, DerefMut, Clone, Copy, From, PartialEq, Eq, Hash)]
#[debug("{:?}", _0)]
#[display("{}", _0)]
pub struct Const<T>(T);
impl<'l, T: 'l> Into<AnyConst<'l>> for &'l Const<T>
where
for<'a> &'a T: Into<AnyConst<'a>>,
{
fn into(self) -> AnyConst<'l> {
(&self.0).into()
}
}
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
#[from(forward)]
pub enum AnyConst<'l> {
#[display("void")]
#[debug("void")]
Void,
#[debug("{:?}", _0)]
#[display("{}", _0)]
Bool(bool),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Char(char),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Int(Int),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Float(Float),
#[debug("{:?}", _0)]
#[display("\"{}\"", _0)]
Str(&'l str),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Function(&'l Function<'l>),
Type(Type<'l>),
}
impl<'l> AnyConst<'l> {
pub fn ty(&self) -> Type<'l> {
match self {
Self::Void => Type::Void,
Self::Bool(_) => Type::Bool,
Self::Char(_) => Type::Char,
Self::Type(_) => Type::Type,
Self::Int(Int::I8(_)) => Type::I8,
Self::Int(Int::I16(_)) => Type::I16,
Self::Int(Int::I32(_)) => Type::I32,
Self::Int(Int::I64(_)) => Type::I64,
Self::Int(Int::I128(_)) => Type::I128,
Self::Int(Int::U8(_)) => Type::U8,
Self::Int(Int::U16(_)) => Type::U16,
Self::Int(Int::U32(_)) => Type::U32,
Self::Int(Int::U64(_)) => Type::U64,
Self::Int(Int::U128(_)) => Type::U128,
Self::Float(Float::F16(_)) => Type::F16,
Self::Float(Float::F32(_)) => Type::F32,
Self::Float(Float::F64(_)) => Type::F64,
_ => todo!("{self:?}"),
}
}
}
+15 -133
View File
@@ -1,13 +1,11 @@
use crate::{
assembly::Context,
functions::{Function, ir::Instruction},
types::Type,
};
use crate::{functions::ir::Instruction, types::Type};
use bitflags::bitflags;
use derive_more::{Debug, Display};
use half::f16;
use derive_more::{Debug, Display, *};
use std::hash::Hash;
mod constants;
pub use constants::*;
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ValueFlags: u16 {
@@ -20,140 +18,24 @@ bitflags! {
}
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Int {
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
}
#[derive(Debug, Display, Clone, Copy, PartialEq)]
pub enum Float {
F16(f16),
F32(f32),
F64(f64),
}
impl Eq for Float {}
impl Hash for Float {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
Float::F16(v) => v.to_ne_bytes().hash(state),
Float::F32(v) => v.to_ne_bytes().hash(state),
Float::F64(v) => v.to_ne_bytes().hash(state),
}
}
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ConstData<'l> {
#[display("()")]
#[debug("()")]
Void,
#[debug("{:?}", _0)]
#[display("{}", _0)]
Bool(bool),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Char(char),
#[debug("{:?}", _0)]
#[display("\"{}\"", _0)]
Str(&'l str),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Int(Int),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Float(Float),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Function(&'l Function<'l>),
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[debug("{:?}", data)]
#[display("{}", data)]
pub struct Const<'l> {
pub ctx: &'l Context<'l>,
pub data: ConstData<'l>,
}
impl<'l> Const<'l> {
pub fn flags(&self) -> ValueFlags {
ValueFlags::Const
}
pub fn ty(&self) -> Type<'l> {
let ctx = self.ctx;
match self.data {
ConstData::Void => ctx.void_t(),
ConstData::Char(_) => ctx.char_t(),
ConstData::Bool(_) => ctx.bool_t(),
ConstData::Str(_) => ctx.const_str_t(),
ConstData::Int(v) => match v {
Int::I8(_) => ctx.i8_t(),
Int::I16(_) => ctx.i16_t(),
Int::I32(_) => ctx.i32_t(),
Int::I64(_) => ctx.i64_t(),
Int::I128(_) => ctx.i128_t(),
Int::U8(_) => ctx.u8_t(),
Int::U16(_) => ctx.u16_t(),
Int::U32(_) => ctx.u32_t(),
Int::U64(_) => ctx.u64_t(),
Int::U128(_) => ctx.u128_t(),
},
ConstData::Float(v) => match v {
Float::F16(_) => ctx.f16_t(),
Float::F32(_) => ctx.f32_t(),
Float::F64(_) => ctx.f64_t(),
},
ConstData::Function(v) => Type::Func(v.ty),
}
}
}
impl<'l> Into<Value<'l>> for &'l Const<'l> {
fn into(self) -> Value<'l> {
Value::Const(self)
}
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
pub enum Value<'l> {
#[display("{}", _0)]
Const(&'l Const<'l>),
#[display("{}", _0)]
Type(Type<'l>),
#[display("<function>")]
Func(&'l Function<'l>),
#[display("%{}", _0.id())]
#[display("{_0}")]
Constant(AnyConst<'l>),
#[display("{_0}")]
Instruction(&'l Instruction<'l>),
}
impl<'l> Value<'l> {
pub fn flags(&self) -> ValueFlags {
match self {
Value::Const(c) => c.flags(),
Value::Type(_) => ValueFlags::Type,
Value::Func(_) => ValueFlags::Function,
Value::Instruction(i) => i.value_flags(),
}
impl From<Int> for Value<'_> {
fn from(value: Int) -> Self {
Value::Constant(AnyConst::Int(value))
}
}
impl<'l> Value<'l> {
pub fn ty(&self) -> Type<'l> {
match self {
Value::Const(v) => v.ty(),
Value::Type(v) => v.ctx().type_t(),
Value::Func(v) => Type::Func(v.ty),
Value::Constant(v) => v.ty(),
Value::Instruction(v) => v.value_ty(),
}
}