Big restructure pt.1
This commit is contained in:
@@ -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];
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
@@ -1,4 +1,4 @@
|
||||
pub mod context;
|
||||
pub mod assembly;
|
||||
pub mod functions;
|
||||
pub mod types;
|
||||
pub mod values;
|
||||
|
||||
@@ -122,7 +122,7 @@ impl Display for FuncT<'_> {
|
||||
write!(f, "{separator}{ty}")?;
|
||||
separator = ", ";
|
||||
}
|
||||
write!(f, ") -> {}", self.ret_t)?;
|
||||
write!(f, ") {}", self.ret_t)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user