Big restructure pt.2
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ edition = "2024"
|
||||
[dependencies]
|
||||
bitflags = "2.10.0"
|
||||
boxcar = "0.2.14"
|
||||
derive_more = { version = "2.0.1", features = ["deref", "debug", "display"] }
|
||||
derive_more = { version = "2.0.1", features = ["deref", "deref_mut", "debug", "display", "try_from", "from", "try_into", "into"] }
|
||||
half = "2.7.1"
|
||||
scc = "3.3.7"
|
||||
|
||||
|
||||
+11
-142
@@ -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 }),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!(
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
impl<'l> Type<'l> {
|
||||
pub fn make_ptr(&self, mutable: bool) -> &'l PtrT<'l> {
|
||||
self.ctx().derivations.make_ptr(*self, mutable)
|
||||
}
|
||||
|
||||
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>;
|
||||
pub fn make_ref(&self, mutable: bool) -> &'l RefT<'l> {
|
||||
self.ctx().derivations.make_ref(*self, mutable)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn make_ref(self, mutable: bool) -> &'l RefT<'l> {
|
||||
let ty = self.into();
|
||||
ty.ctx().derivations.make_ref(ty, 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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-132
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
+32
-19
@@ -3,10 +3,11 @@ use arcstr::literal_substr;
|
||||
use leaf_allocators::SyncAllocator;
|
||||
use leaf_assembly::{
|
||||
assembly::{Assembly, AssemblyIdentifier, Context},
|
||||
values::Value,
|
||||
types::{FloatT, IntT, Type},
|
||||
values::{AnyConst, Value},
|
||||
};
|
||||
use leaf_parser::SourceCode;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
use std::{collections::HashMap, sync::Arc, u32};
|
||||
|
||||
mod error;
|
||||
mod scope;
|
||||
@@ -49,23 +50,35 @@ impl<'l> CompilationContext<'l> {
|
||||
.iter()
|
||||
.map(|src| {
|
||||
let mut scope = Scope::new(assembly, src.clone());
|
||||
scope.insert(literal_substr!("void"), Value::Type(self.ctx.void_t()));
|
||||
scope.insert(literal_substr!("i8"), Value::Type(self.ctx.i8_t()));
|
||||
scope.insert(literal_substr!("i16"), Value::Type(self.ctx.i16_t()));
|
||||
scope.insert(literal_substr!("i32"), Value::Type(self.ctx.i32_t()));
|
||||
scope.insert(literal_substr!("i64"), Value::Type(self.ctx.i64_t()));
|
||||
scope.insert(literal_substr!("i128"), Value::Type(self.ctx.i128_t()));
|
||||
scope.insert(literal_substr!("isize"), Value::Type(self.ctx.isize_t()));
|
||||
scope.insert(literal_substr!("u8"), Value::Type(self.ctx.u8_t()));
|
||||
scope.insert(literal_substr!("u16"), Value::Type(self.ctx.u16_t()));
|
||||
scope.insert(literal_substr!("u32"), Value::Type(self.ctx.u32_t()));
|
||||
scope.insert(literal_substr!("u64"), Value::Type(self.ctx.u64_t()));
|
||||
scope.insert(literal_substr!("u128"), Value::Type(self.ctx.u128_t()));
|
||||
scope.insert(literal_substr!("usize"), Value::Type(self.ctx.usize_t()));
|
||||
scope.insert(literal_substr!("f16"), Value::Type(self.ctx.f16_t()));
|
||||
scope.insert(literal_substr!("f32"), Value::Type(self.ctx.f32_t()));
|
||||
scope.insert(literal_substr!("f64"), Value::Type(self.ctx.f64_t()));
|
||||
scope.insert(literal_substr!("type"), Value::Type(self.ctx.type_t()));
|
||||
macro_rules! insert_types {
|
||||
($($id:literal : $ty:expr,)*) => {
|
||||
$(
|
||||
scope.insert(
|
||||
literal_substr!($id),
|
||||
Value::Constant(AnyConst::Type($ty.into())),
|
||||
);
|
||||
)*
|
||||
};
|
||||
}
|
||||
insert_types! {
|
||||
"void": Type::Void,
|
||||
"i8": Type::I8,
|
||||
"i16": Type::I16,
|
||||
"i32": Type::I32,
|
||||
"i64": Type::I64,
|
||||
"i128": Type::I128,
|
||||
"isize": Type::ISIZE,
|
||||
"u8": Type::U8,
|
||||
"u16": Type::U16,
|
||||
"u32": Type::U32,
|
||||
"u64": Type::U64,
|
||||
"u128": Type::U128,
|
||||
"usize": Type::USIZE,
|
||||
"f16": Type::F16,
|
||||
"f32": Type::F32,
|
||||
"f64": Type::F64,
|
||||
"type": Type::Type,
|
||||
}
|
||||
scope
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use arcstr::Substr;
|
||||
use leaf_assembly::{
|
||||
assembly::Assembly,
|
||||
types::{Type, derivations::MakeTypeDerivations},
|
||||
values::Value,
|
||||
types::Type,
|
||||
values::{AnyConst, Value},
|
||||
};
|
||||
use leaf_parser::{
|
||||
SourceCode,
|
||||
@@ -91,12 +91,14 @@ impl<'l> Scope<'l> {
|
||||
par_ty.push(ty);
|
||||
}
|
||||
let fn_ty = ret_ty.make_fn(par_ty);
|
||||
Ok(Value::Func(self.assembly.create_function(fn_ty)))
|
||||
Ok(Value::Constant(AnyConst::Function(
|
||||
self.assembly.create_function(fn_ty),
|
||||
)))
|
||||
}
|
||||
|
||||
fn assert_type(&self, val: Value<'l>) -> Result<Type<'l>, CompilationError> {
|
||||
match val {
|
||||
Value::Type(ty) => Ok(ty),
|
||||
Value::Constant(AnyConst::Type(ty)) => Ok(ty),
|
||||
_ => Err(CompilationError {
|
||||
kind: Kind::NotAType,
|
||||
message: format!("Value is not a type."),
|
||||
|
||||
@@ -5,8 +5,8 @@ use leaf_assembly::{
|
||||
Function,
|
||||
ir::{Cmp, Instruction, InstructionVariant},
|
||||
},
|
||||
types::{Type, intrinsics::IntT},
|
||||
values::{Const, ConstData, Int, Value},
|
||||
types::{IntT, Type},
|
||||
values::{AnyConst, Const, Int, Value},
|
||||
};
|
||||
use scc::HashMap;
|
||||
use std::{alloc::Layout, fmt::Debug, ops::Range, sync::Arc};
|
||||
@@ -112,12 +112,9 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
..
|
||||
},
|
||||
),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U8(v)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U8(v))),
|
||||
) => {
|
||||
assert_eq!(ctx.u8_t(), *ty);
|
||||
assert_eq!(Type::U8, *ty);
|
||||
opcodes.push(OpCode::Store_CL_U8(*v, memory_ranges[&t.id()].start));
|
||||
}
|
||||
|
||||
@@ -128,12 +125,9 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
..
|
||||
},
|
||||
),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U16(v)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U16(v))),
|
||||
) => {
|
||||
assert_eq!(ctx.u16_t(), *ty);
|
||||
assert_eq!(Type::U16, *ty);
|
||||
opcodes.push(OpCode::Store_CL_U16(*v, memory_ranges[&t.id()].start));
|
||||
}
|
||||
|
||||
@@ -144,12 +138,9 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
..
|
||||
},
|
||||
),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U32(v)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U32(v))),
|
||||
) => {
|
||||
assert_eq!(ctx.u32_t(), *ty);
|
||||
assert_eq!(Type::U32, *ty);
|
||||
opcodes.push(OpCode::Store_CL_U32(*v, memory_ranges[&t.id()].start));
|
||||
}
|
||||
|
||||
@@ -160,12 +151,9 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
..
|
||||
},
|
||||
),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U64(v)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U64(v))),
|
||||
) => {
|
||||
assert_eq!(ctx.u64_t(), *ty);
|
||||
assert_eq!(Type::U64, *ty);
|
||||
opcodes.push(OpCode::Store_CL_U64(*v, memory_ranges[&t.id()].start));
|
||||
}
|
||||
|
||||
@@ -212,10 +200,7 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
|
||||
InstructionVariant::IAdd(
|
||||
Value::Instruction(a),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U32(b)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U32(b))),
|
||||
) => {
|
||||
assert!(matches!(
|
||||
a.value_ty(),
|
||||
@@ -226,16 +211,13 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
})
|
||||
));
|
||||
let a = memory_ranges[&a.id()].start;
|
||||
let c = alloc_range!(ctx.u32_t(), inst.id()).start;
|
||||
let c = alloc_range!(Type::U32, inst.id()).start;
|
||||
opcodes.push(OpCode::Add_LC_U32(a, *b, c));
|
||||
}
|
||||
|
||||
InstructionVariant::ICmp(
|
||||
Value::Instruction(a),
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U32(b)),
|
||||
ctx,
|
||||
}),
|
||||
Value::Constant(AnyConst::Int(Int::U32(b))),
|
||||
cmp,
|
||||
) => {
|
||||
assert!(matches!(
|
||||
@@ -247,7 +229,7 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
})
|
||||
));
|
||||
let a = memory_ranges[&a.id()].start;
|
||||
let target = alloc_range!(ctx.bool_t(), inst.id()).start;
|
||||
let target = alloc_range!(Type::Bool, inst.id()).start;
|
||||
match *cmp {
|
||||
Cmp::Eq => opcodes.push(OpCode::CmpEq_LC_U32(a, *b, target)),
|
||||
Cmp::Lt => opcodes.push(OpCode::CmpLt_LC_U32(a, *b, target)),
|
||||
@@ -284,7 +266,7 @@ impl<'l> InstructionCacheEntry<'l> {
|
||||
true_case,
|
||||
false_case,
|
||||
} => {
|
||||
assert!(matches!(i.value_ty(), Type::Bool(_)));
|
||||
assert!(matches!(i.value_ty(), Type::Bool));
|
||||
backpatch.push(opcodes.len());
|
||||
opcodes.push(OpCode::Branch {
|
||||
cond: memory_ranges[&i.id()].start,
|
||||
|
||||
@@ -6,8 +6,8 @@ use fxhash::FxHashMap;
|
||||
use leaf_assembly::{
|
||||
assembly::Ctx,
|
||||
functions::Function,
|
||||
types::{Type, intrinsics::IntT},
|
||||
values::{Const, ConstData, Int, Value},
|
||||
types::{IntT, Type},
|
||||
values::{AnyConst, Int, Value},
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
@@ -211,10 +211,7 @@ impl<'l> Interpreter<'l> {
|
||||
fn push_ctx_val(&mut self, sp: &mut usize, value: &Value) -> Range<usize> {
|
||||
let ptr = &self.stack[*sp] as *const u8;
|
||||
match value {
|
||||
Value::Const(Const {
|
||||
data: ConstData::Int(Int::U32(v)),
|
||||
..
|
||||
}) => {
|
||||
Value::Constant(AnyConst::Int(Int::U32(v))) => {
|
||||
*sp += ptr.align_offset(align_of::<u32>());
|
||||
let range = *sp..*sp + size_of::<u32>();
|
||||
self.stack[range.clone()].copy_from_slice(&v.to_ne_bytes());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use fxhash::FxBuildHasher;
|
||||
use leaf_assembly::types::{Type, derivations::PtrT, intrinsics::IntT};
|
||||
use leaf_assembly::types::{IntT, Type, derivations::PtrT};
|
||||
use scc::HashMap;
|
||||
use std::{
|
||||
alloc::Layout,
|
||||
@@ -43,7 +43,7 @@ impl<'l> GetLayout<Type<'_>> for LayoutCache<'l> {
|
||||
|
||||
fn get_layout(&self, ty: Type<'_>) -> Arc<Self::LayoutT> {
|
||||
match ty {
|
||||
Type::Void(_) => {
|
||||
Type::Void => {
|
||||
static LAYOUT: OnceLock<Arc<TypeLayout>> = OnceLock::new();
|
||||
LAYOUT
|
||||
.get_or_init(|| {
|
||||
@@ -55,7 +55,7 @@ impl<'l> GetLayout<Type<'_>> for LayoutCache<'l> {
|
||||
.clone()
|
||||
}
|
||||
|
||||
Type::Bool(_) => {
|
||||
Type::Bool => {
|
||||
static LAYOUT: OnceLock<Arc<TypeLayout>> = OnceLock::new();
|
||||
LAYOUT
|
||||
.get_or_init(|| {
|
||||
|
||||
+12
-21
@@ -1,7 +1,8 @@
|
||||
use leaf_allocators::SyncArenaAllocator;
|
||||
use leaf_assembly::assembly::{Assembly, AssemblyIdentifier, Context, CreateConst, Version};
|
||||
use leaf_assembly::assembly::{AssemblyIdentifier, Context, Version};
|
||||
use leaf_assembly::functions::ir::Cmp;
|
||||
use leaf_assembly::types::derivations::MakeTypeDerivations;
|
||||
use leaf_assembly::types::Type;
|
||||
use leaf_assembly::values::Int;
|
||||
use leaf_interpreter::interpreter::{AnyValue, Error, Interpreter, NativeFunction};
|
||||
use std::ffi::CStr;
|
||||
use std::time::{Duration, Instant};
|
||||
@@ -14,32 +15,24 @@ fn main() {
|
||||
name: "test".into(),
|
||||
});
|
||||
|
||||
let puts = assembly.create_function(
|
||||
context
|
||||
.void_t()
|
||||
.make_fn([context.u8_t().make_ptr(false).into()]),
|
||||
);
|
||||
let puts = assembly.create_function(Type::Void.make_fn([Type::U8.make_ptr(false).into()]));
|
||||
|
||||
let print_u32 = assembly.create_function(context.void_t().make_fn([context.u32_t().into()]));
|
||||
let print_u32 = assembly.create_function(Type::Void.make_fn([Type::U32.into()]));
|
||||
|
||||
let random_func = {
|
||||
let func = assembly.create_function(context.u32_t().make_fn([]));
|
||||
let func = assembly.create_function(Type::U32.make_fn([]));
|
||||
let mut builder = func.create_body().unwrap();
|
||||
|
||||
let loop_check = builder.create_block();
|
||||
let loop_body = builder.create_block();
|
||||
let loop_end = builder.create_block();
|
||||
|
||||
let var0 = builder.stack_alloc(context.u32_t()).unwrap();
|
||||
let var1 = builder.stack_alloc(context.u32_t()).unwrap();
|
||||
let var0 = builder.stack_alloc(Type::U32).unwrap();
|
||||
let var1 = builder.stack_alloc(Type::U32).unwrap();
|
||||
|
||||
builder
|
||||
.store(var0, context.create_const(42u32).into())
|
||||
.unwrap();
|
||||
builder.store(var0, Int::U32(42).into()).unwrap();
|
||||
|
||||
builder
|
||||
.store(var1, context.create_const(0u32).into())
|
||||
.unwrap();
|
||||
builder.store(var1, Int::U32(0u32).into()).unwrap();
|
||||
|
||||
builder.jump(loop_check).unwrap();
|
||||
builder.set_current_block(loop_check);
|
||||
@@ -49,14 +42,12 @@ fn main() {
|
||||
let c = builder.add(a, b).unwrap();
|
||||
builder.call(print_u32, vec![c]).unwrap();
|
||||
|
||||
let cond = builder
|
||||
.cmp(c, context.create_const(69u32).into(), Cmp::Lt)
|
||||
.unwrap();
|
||||
let cond = builder.cmp(c, Int::U32(69u32).into(), Cmp::Lt).unwrap();
|
||||
builder.branch(cond, loop_body, loop_end).unwrap();
|
||||
|
||||
builder.set_current_block(loop_body);
|
||||
let v = builder.load(var1).unwrap();
|
||||
let v = builder.add(v, context.create_const(1u32).into()).unwrap();
|
||||
let v = builder.add(v, Int::U32(1u32).into()).unwrap();
|
||||
builder.store(var1, v).unwrap();
|
||||
builder.jump(loop_check).unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user