Big restructure pt.1

This commit is contained in:
Mia
2026-02-26 19:40:27 +01:00
parent 02f2ddfc67
commit f4334e79f6
32 changed files with 905 additions and 842 deletions
@@ -1,24 +1,41 @@
use crate::{
assembly::intrinsic_types::make_intrinsic_types,
functions::Function,
types::{
Type,
derivations::{FuncT, TypeDerivations},
intrinsics::*,
},
values::{Const, Int},
values::{Const, ConstData, Int},
};
use derive_more::Debug;
use leaf_allocators::SyncAllocator;
use scc::HashMap;
use std::{hash::Hash, sync::OnceLock};
use std::{borrow::Cow, hash::Hash, sync::OnceLock};
#[derive(derive_more::Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[debug("{major}.{minor}.{patch}.{build}")]
pub struct Version {
pub major: u16,
pub minor: u16,
pub patch: u16,
pub build: u16,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AssemblyIdentifier {
pub version: Version,
pub name: Cow<'static, str>,
}
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 Const<'l>, &'l Const<'l>>,
constants: HashMap<&'l ConstData<'l>, &'l Const<'l>>,
intrinsics: OnceLock<Box<intrinsic_types::IntrinsicTypesArray<'l>>>,
assemblies: HashMap<AssemblyIdentifier, &'l Assembly<'l>>,
}
impl Eq for Context<'_> {}
@@ -31,30 +48,91 @@ impl PartialEq for Context<'_> {
impl Hash for Context<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self as *const Self).hash(state);
std::ptr::hash(self, state);
}
}
impl<'l> Context<'l> {
pub fn new(alloc: &'l dyn SyncAllocator) -> &'l Context<'l> {
pub fn new(alloc: &'l dyn SyncAllocator) -> &'l Self {
let ctx = alloc.alloc(Self {
alloc,
constants: HashMap::new(),
derivations: TypeDerivations::new(alloc),
intrinsics: OnceLock::new(),
assemblies: Default::default(),
});
ctx.intrinsics
.set(Box::new(intrinsic_types::make_intrinsic_types(ctx)))
.set(Box::new(make_intrinsic_types(ctx)))
.unwrap();
ctx
}
pub fn get_assembly(&'l self, ident: &AssemblyIdentifier) -> Option<&'l Assembly<'l>> {
self.assemblies.get_sync(ident).map(|v| *v)
}
pub fn get_or_create_assembly(&'l self, ident: AssemblyIdentifier) -> &'l Assembly<'l> {
&*self
.assemblies
.entry_sync(ident.clone())
.or_insert_with(|| Assembly::new(self, ident))
}
}
#[derive(Debug)]
pub struct Assembly<'l> {
#[debug(skip)]
ctx: &'l Context<'l>,
ident: AssemblyIdentifier,
#[debug("{:#?}", {
let mut c = vec![];
constants.iter_sync(|k, _| {c.push(*k); true});
c
})]
constants: HashMap<&'l Const<'l>, &'l Const<'l>>,
}
impl Eq for Assembly<'_> {}
impl PartialEq for Assembly<'_> {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other)
}
}
impl Hash for Assembly<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self as *const Self).hash(state);
}
}
impl<'l> Assembly<'l> {
pub fn new(ctx: &'l Context<'l>, ident: AssemblyIdentifier) -> &'l Self {
let assembly = ctx.alloc.alloc(Self {
ctx,
ident,
constants: HashMap::new(),
});
assembly
}
pub fn ctx(&self) -> Ctx<'l> {
self.ctx
}
pub fn create_function(&'l self, ty: &'l FuncT<'l>) -> &'l Function<'l> {
self.alloc.alloc(Function {
let func = self.ctx.alloc.alloc(Function {
ty,
name: OnceLock::new(),
body: OnceLock::new(),
ctx: self,
})
declaring_assembly: self,
});
let constant = self.ctx.alloc.alloc(Const {
ctx: self.ctx,
data: ConstData::Function(func),
});
self.constants.insert_sync(constant, constant).unwrap();
func
}
}
@@ -68,11 +146,11 @@ macro_rules! create_const {
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) {
if let Some(existing) = self.constants.get_sync(&constant.data) {
return *existing;
}
let constant = self.alloc.alloc(constant);
*self.constants.entry_sync(constant).or_insert(constant)
*self.constants.entry_sync(&constant.data).or_insert(constant)
}
}
)*
@@ -80,22 +158,22 @@ macro_rules! create_const {
}
create_const! {
impl i8: |ctx, val| Const::Int(Int::I8(val), ctx),
impl i16: |ctx, val| Const::Int(Int::I16(val), ctx),
impl i32: |ctx, val| Const::Int(Int::I32(val), ctx),
impl i64: |ctx, val| Const::Int(Int::I64(val), ctx),
impl i128: |ctx, val| Const::Int(Int::I128(val), ctx),
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::Int(Int::U8(val), ctx),
impl u16: |ctx, val| Const::Int(Int::U16(val), ctx),
impl u32: |ctx, val| Const::Int(Int::U32(val), ctx),
impl u64: |ctx, val| Const::Int(Int::U64(val), ctx),
impl u128: |ctx, val| Const::Int(Int::U128(val), ctx),
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::Void(ctx),
impl char: |ctx, val| Const::Char(val, ctx),
impl bool: |ctx, val| Const::Bool(val, ctx),
impl &'l str: |ctx, val| Const::Str(val, ctx),
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 {
@@ -111,7 +189,7 @@ mod intrinsic_types {
pub type IntrinsicTypesArray<'l> = [Type<'l>; IntrinsicTypeKind::COUNT as usize];
pub fn make_intrinsic_types<'l>(ctx: Ctx<'l>) -> IntrinsicTypesArray<'l> {
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];
+5 -5
View File
@@ -1,5 +1,5 @@
use crate::{
context::Ctx,
assembly::Ctx,
functions::{Function, FunctionBody},
types::{Type, derivations::*},
values::{Value, ValueFlags},
@@ -55,7 +55,7 @@ impl<'l> Into<Value<'l>> for &'l Instruction<'l> {
impl<'l> Instruction<'l> {
#[inline]
pub fn ctx(&self) -> Ctx<'l> {
self.parent_block.func.ctx
self.parent_block.func.declaring_assembly.ctx()
}
#[inline]
@@ -342,7 +342,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 => self.block.func.ctx().void_t(),
};
if value_ty != ret_t {
return Err(format!(
@@ -377,7 +377,7 @@ impl<'l> BlockBuilder<'l> {
if self.has_termination() {
return Err(format!("Block #{} has already terminated", self.block.id).into());
}
let instruction = &*self.block.func.ctx.alloc.alloc(Instruction {
let instruction = &*self.block.func.ctx().alloc.alloc(Instruction {
id: Id(UnsafeCell::new(u32::MAX)),
parent_block: self.block,
variant,
@@ -420,7 +420,7 @@ impl<'l> FunctionBodyBuilder<'l> {
}
pub fn create_block(&mut self) -> &'l Block<'l> {
let block = &*self.func.ctx.alloc.alloc(Block {
let block = &*self.func.ctx().alloc.alloc(Block {
id: self.blocks.len() as u32,
func: self.func,
instructions: OnceLock::new(),
+24 -5
View File
@@ -1,23 +1,27 @@
use crate::{
context::Ctx,
assembly::{Assembly, Ctx},
functions::ir::{Block, FunctionBodyBuilder},
types::derivations::FuncT,
};
use std::{fmt::Debug as FmtDebug, sync::OnceLock};
use std::{
fmt::{Debug as FmtDebug, Display},
hash::Hash,
sync::OnceLock,
};
pub mod ir;
#[non_exhaustive]
pub struct Function<'l> {
pub ty: &'l FuncT<'l>,
pub name: OnceLock<&'l str>,
pub(crate) body: OnceLock<FunctionBody<'l>>,
pub(crate) ctx: Ctx<'l>,
pub(crate) declaring_assembly: &'l Assembly<'l>,
}
impl<'l> Function<'l> {
pub fn ctx(&self) -> Ctx<'l> {
self.ctx
self.declaring_assembly.ctx()
}
pub fn body(&self) -> Option<&FunctionBody<'l>> {
@@ -40,6 +44,15 @@ impl PartialEq for Function<'_> {
}
}
impl Display for Function<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.name.get() {
Some(n) => write!(f, "{} @ {}", self.ty, n),
None => Display::fmt(&self.ty, f),
}
}
}
impl FmtDebug for Function<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let body: &dyn FmtDebug = match self.body() {
@@ -54,6 +67,12 @@ impl FmtDebug for Function<'_> {
}
}
impl Hash for Function<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
std::ptr::hash(self, state);
}
}
#[non_exhaustive]
pub struct FunctionBody<'l> {
pub blocks: Vec<&'l Block<'l>>,
+1 -1
View File
@@ -1,4 +1,4 @@
pub mod context;
pub mod assembly;
pub mod functions;
pub mod types;
pub mod values;
+1 -1
View File
@@ -122,7 +122,7 @@ impl Display for FuncT<'_> {
write!(f, "{separator}{ty}")?;
separator = ", ";
}
write!(f, ") -> {}", self.ret_t)?;
write!(f, ") {}", self.ret_t)?;
Ok(())
}
}
+7 -2
View File
@@ -1,5 +1,6 @@
use crate::{context::Ctx, types::Type};
use crate::{assembly::Ctx, types::Type};
use derive_more::{Debug, Display};
use std::fmt::Display;
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("type")]
@@ -68,7 +69,11 @@ impl<'l> Into<Type<'l>> for &'l ConstStrT<'l> {
#[non_exhaustive]
#[derive(Debug, Display, PartialEq, Eq, Hash)]
#[display("{}{}", if *signed { "i" } else { "u" }, precision)]
#[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,
+1 -1
View File
@@ -2,7 +2,7 @@ pub mod derivations;
pub mod intrinsics;
use crate::{
context::Ctx,
assembly::Ctx,
types::{derivations::*, intrinsics::*},
};
use derive_more::{Debug, Display};
+39 -29
View File
@@ -1,4 +1,8 @@
use crate::{context::Ctx, functions::ir::Instruction, types::Type};
use crate::{
assembly::Context,
functions::{Function, ir::Instruction},
types::Type,
};
use bitflags::bitflags;
use derive_more::{Debug, Display};
use half::f16;
@@ -12,6 +16,7 @@ bitflags! {
const Const = 0b00000001_00000000;
const ConstOnly = 0b00000011_00000000;
const Type = 0b00000111_00000000;
const Function = 0b00001011_00000000;
}
}
@@ -50,51 +55,51 @@ impl Hash for Float {
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Const<'l> {
pub enum ConstData<'l> {
#[display("()")]
#[debug("()")]
Void(Ctx<'l>),
Void,
#[debug("{:?}", _0)]
#[display("{}", _0)]
Bool(bool, Ctx<'l>),
Bool(bool),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Char(char, Ctx<'l>),
Char(char),
#[debug("{:?}", _0)]
#[display("\"{}\"", _0)]
Str(&'l str, Ctx<'l>),
Str(&'l str),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Int(Int, Ctx<'l>),
Int(Int),
#[debug("{:?}", _0)]
#[display("{}", _0)]
Float(Float, Ctx<'l>),
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 {
match self {
Const::Void(_) => ValueFlags::Const,
Const::Char(_, _) => ValueFlags::Const,
Const::Bool(_, _) => ValueFlags::Const,
Const::Str(_, _) => ValueFlags::Const,
Const::Int(_, _) => ValueFlags::Const,
Const::Float(_, _) => ValueFlags::Const,
}
ValueFlags::Const
}
pub fn ty(&self) -> Type<'l> {
match self {
Const::Void(ctx) => ctx.void_t(),
Const::Char(_, ctx) => ctx.char_t(),
Const::Bool(_, ctx) => ctx.bool_t(),
Const::Str(_, ctx) => ctx.const_str_t(),
Const::Int(v, ctx) => match v {
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(),
@@ -106,11 +111,12 @@ impl<'l> Const<'l> {
Int::U64(_) => ctx.u64_t(),
Int::U128(_) => ctx.u128_t(),
},
Const::Float(v, ctx) => match v {
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),
}
}
}
@@ -121,12 +127,14 @@ impl<'l> Into<Value<'l>> for &'l Const<'l> {
}
}
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq)]
pub enum Value<'l> {
#[display("{}", _0)]
Const(&'l Const<'l>),
#[display("{}", _0)]
Type(Type<'l>),
#[display("<function>")]
Func(&'l Function<'l>),
#[display("%{}", _0.id())]
Instruction(&'l Instruction<'l>),
}
@@ -136,6 +144,7 @@ impl<'l> Value<'l> {
match self {
Value::Const(c) => c.flags(),
Value::Type(_) => ValueFlags::Type,
Value::Func(_) => ValueFlags::Function,
Value::Instruction(i) => i.value_flags(),
}
}
@@ -144,6 +153,7 @@ impl<'l> Value<'l> {
match self {
Value::Const(v) => v.ty(),
Value::Type(v) => v.ctx().type_t(),
Value::Func(v) => Type::Func(v.ty),
Value::Instruction(v) => v.value_ty(),
}
}