Structs and comptime reflection stuff

This commit is contained in:
Mia
2026-03-07 01:42:06 +01:00
parent 81d1dfe3d3
commit fb84e09391
18 changed files with 1399 additions and 321 deletions
+1 -1
View File
@@ -9,6 +9,6 @@ boxcar = "0.2.14"
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"
leaf_allocators = { path = "../allocators" }
fxhash = "0.2.1"
indexmap = "2.13.0"
+17 -3
View File
@@ -1,6 +1,9 @@
use crate::{
functions::Function,
types::derivations::{FuncT, TypeDerivations},
types::{
compound::StructT,
derivations::{FuncT, TypeDerivations},
},
};
use derive_more::{Debug, Display};
use fxhash::FxBuildHasher;
@@ -76,6 +79,9 @@ impl<'l> Context<'l> {
}
pub fn intern_str(&'l self, str: &str) -> &'l str {
if str.is_empty() {
return "";
}
if let Some(value) = self.strings.get_sync(str) {
return *value;
}
@@ -124,10 +130,18 @@ impl<'l> Assembly<'l> {
&self.ident
}
pub fn create_function(&'l self, ty: &'l FuncT<'l>) -> &'l Function<'l> {
pub fn create_struct(&'l self, name: &str) -> &'l StructT<'l> {
self.ctx().alloc.alloc(StructT {
name: self.ctx().intern_str(name),
fields: OnceLock::new(),
declaring_assembly: self,
})
}
pub fn create_function(&'l self, ty: &'l FuncT<'l>, name: &str) -> &'l Function<'l> {
let func = self.ctx.alloc.alloc(Function {
ty,
name: OnceLock::new(),
name: self.ctx().intern_str(name),
body: OnceLock::new(),
declaring_assembly: self,
});
+286 -85
View File
@@ -1,8 +1,8 @@
use crate::{
assembly::Ctx,
functions::{Function, FunctionBody},
types::{IntT, Type, derivations::*},
values::{Value, ValueFlags},
types::{IntT, Type, compound::StructT, derivations::*},
values::{AnyConst, AnyValue, Value, ValueFlags, default_associated_values},
};
use derive_more::{Debug, Display};
use std::{borrow::Cow, cell::UnsafeCell, hash::Hash, ops::Deref, sync::OnceLock};
@@ -56,19 +56,10 @@ impl<'l> Instruction<'l> {
pub fn id(&self) -> u32 {
unsafe { *self.id.0.get() }
}
}
pub fn value_flags(&self) -> ValueFlags {
match self.variant {
InstructionVariant::StackAlloc(_) => ValueFlags::LValue,
InstructionVariant::GetElementPtr(v, _) if v.flags().contains(ValueFlags::LValue) => {
ValueFlags::LValue
}
InstructionVariant::Reinterpret(_, _, f) => f,
_ => ValueFlags::empty(),
}
}
pub fn value_ty(&'l self) -> Type<'l> {
impl<'l> Value<'l> for &'l Instruction<'l> {
fn ty(&self) -> Type<'l> {
match self.variant {
InstructionVariant::Return(_) => Type::Void,
InstructionVariant::Store(_, _) => Type::Void,
@@ -88,6 +79,15 @@ impl<'l> Instruction<'l> {
}) => base.make_ref(*mutable).into(),
_ => unreachable!(),
},
InstructionVariant::GetElementVal(v, i) => match v.ty() {
Type::Struct(StructT { fields, .. }) => {
let AnyValue::Constant(AnyConst::Str(name)) = i else {
unreachable!()
};
fields.get().unwrap()[name].ty
}
_ => unreachable!(),
},
InstructionVariant::IAdd(a, _) => a.ty(),
InstructionVariant::ISub(a, _) => a.ty(),
InstructionVariant::IMul(a, _) => a.ty(),
@@ -96,12 +96,15 @@ impl<'l> Instruction<'l> {
InstructionVariant::SExt(_, t) => Type::Int(t),
InstructionVariant::ZExt(_, t) => Type::Int(t),
InstructionVariant::Trunc(_, t) => Type::Int(t),
InstructionVariant::IntToPtr(_, t) => Type::Ptr(t),
InstructionVariant::PtrToInt(_, t) => Type::Int(t),
InstructionVariant::FAdd(a, _) => a.ty(),
InstructionVariant::FSub(a, _) => a.ty(),
InstructionVariant::FMul(a, _) => a.ty(),
InstructionVariant::FDiv(a, _) => a.ty(),
InstructionVariant::FMod(a, _) => a.ty(),
InstructionVariant::ICmp(_, _, _) => Type::Bool,
InstructionVariant::MakeStruct(t, _) => Type::Struct(t),
InstructionVariant::Call(f, _) => f.ty.ret_t,
InstructionVariant::Jump(_) => Type::Void,
InstructionVariant::Branch { .. } => Type::Void,
@@ -109,6 +112,23 @@ impl<'l> Instruction<'l> {
_ => todo!("{self:?}"),
}
}
fn flags(&self) -> ValueFlags {
match self.variant {
InstructionVariant::StackAlloc(_) => ValueFlags::LValue,
InstructionVariant::GetElementPtr(v, _) if v.is_lvalue() => ValueFlags::LValue,
InstructionVariant::Reinterpret(_, _, f) => f,
_ => ValueFlags::empty(),
}
}
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
default_associated_values(self, name)
}
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Instruction(self)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -126,37 +146,42 @@ pub enum InstructionVariant<'l> {
StackAlloc(Type<'l>),
GCAlloc(Type<'l>),
Load(Value<'l>),
Store(Value<'l>, Value<'l>),
GetElementPtr(Value<'l>, Value<'l>),
Load(AnyValue<'l>),
Store(AnyValue<'l>, AnyValue<'l>),
GetElementVal(AnyValue<'l>, AnyValue<'l>),
GetElementPtr(AnyValue<'l>, AnyValue<'l>),
IAdd(Value<'l>, Value<'l>),
ISub(Value<'l>, Value<'l>),
IMul(Value<'l>, Value<'l>),
IDiv(Value<'l>, Value<'l>),
IMod(Value<'l>, Value<'l>),
SExt(Value<'l>, IntT),
ZExt(Value<'l>, IntT),
Trunc(Value<'l>, IntT),
FAdd(Value<'l>, Value<'l>),
FSub(Value<'l>, Value<'l>),
FMul(Value<'l>, Value<'l>),
FDiv(Value<'l>, Value<'l>),
FMod(Value<'l>, Value<'l>),
IAdd(AnyValue<'l>, AnyValue<'l>),
ISub(AnyValue<'l>, AnyValue<'l>),
IMul(AnyValue<'l>, AnyValue<'l>),
IDiv(AnyValue<'l>, AnyValue<'l>),
IMod(AnyValue<'l>, AnyValue<'l>),
SExt(AnyValue<'l>, IntT),
ZExt(AnyValue<'l>, IntT),
Trunc(AnyValue<'l>, IntT),
IntToPtr(AnyValue<'l>, &'l PtrT<'l>),
PtrToInt(AnyValue<'l>, IntT),
FAdd(AnyValue<'l>, AnyValue<'l>),
FSub(AnyValue<'l>, AnyValue<'l>),
FMul(AnyValue<'l>, AnyValue<'l>),
FDiv(AnyValue<'l>, AnyValue<'l>),
FMod(AnyValue<'l>, AnyValue<'l>),
ICmp(Value<'l>, Value<'l>, Cmp),
FCmp(Value<'l>, Value<'l>, Cmp),
ICmp(AnyValue<'l>, AnyValue<'l>, Cmp),
FCmp(AnyValue<'l>, AnyValue<'l>, Cmp),
Call(&'l Function<'l>, Vec<Value<'l>>),
MakeStruct(&'l StructT<'l>, &'l [AnyValue<'l>]),
Call(&'l Function<'l>, Vec<AnyValue<'l>>),
Jump(&'l Block<'l>),
Branch {
cond: Value<'l>,
cond: AnyValue<'l>,
true_case: &'l Block<'l>,
false_case: &'l Block<'l>,
},
Return(Option<Value<'l>>),
Return(Option<AnyValue<'l>>),
Reinterpret(Value<'l>, Type<'l>, ValueFlags),
Reinterpret(AnyValue<'l>, Type<'l>, ValueFlags),
}
impl InstructionVariant<'_> {
@@ -172,7 +197,10 @@ impl std::fmt::Debug for InstructionVariant<'_> {
Self::GCAlloc(ty) => write!(f, "gcalloc {ty}"),
Self::Load(v) => write!(f, "load {v}"),
Self::Store(t, v) => write!(f, "store {t}, {v}"),
Self::GetElementPtr(t, v) => write!(f, "gep {t}, {v}"),
Self::GetElementVal(v, i) => write!(f, "gev {v}, {i}"),
Self::GetElementPtr(v, i) => write!(f, "gep {v}, {i}"),
Self::IntToPtr(v, t) => write!(f, "itp {v}, {t}"),
Self::PtrToInt(v, t) => write!(f, "pti {v}, {t}"),
Self::IAdd(a, b) => write!(f, "iadd {a}, {b}"),
Self::ISub(a, b) => write!(f, "isub {a}, {b}"),
Self::IMul(a, b) => write!(f, "imul {a}, {b}"),
@@ -188,11 +216,32 @@ impl std::fmt::Debug for InstructionVariant<'_> {
Self::FMod(a, b) => write!(f, "fmod {a}, {b}"),
Self::ICmp(a, b, c) => write!(f, "icmp {c:?} {a}, {b}"),
Self::FCmp(a, b, c) => write!(f, "fcmp {c:?} {a}, {b}"),
Self::MakeStruct(ty, vals) => {
write!(
f,
"struct {} {{",
match ty.name {
"" => "<anonymous struct>",
_ => ty.name,
}
)?;
let mut separator = "";
for val in *vals {
write!(f, "{separator}{val}")?;
separator = ", ";
}
write!(f, "}}")
}
Self::Call(func, args) => {
write!(
f,
"call {}(",
func.name.get().unwrap_or(&"<anonymous function>")
match func.name {
"" => "<anonymous function>",
_ => func.name,
}
)?;
let mut separator = "";
for arg in args {
@@ -247,16 +296,16 @@ pub type BlockBuilderError<'l> = Cow<'l, str>;
pub type BlockBuilderResult<'l, T> = Result<T, BlockBuilderError<'l>>;
impl<'l> BlockBuilder<'l> {
pub fn stack_alloc(&mut self, ty: Type<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn stack_alloc(&mut self, ty: Type<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
let inst = self.push_instruction(InstructionVariant::StackAlloc(ty))?;
Ok(inst.into())
}
pub fn store(
&mut self,
target: Value<'l>,
value: Value<'l>,
) -> BlockBuilderResult<'l, Value<'l>> {
target: AnyValue<'l>,
value: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let value_ty = value.ty();
let target_ty = target.ty();
match target_ty {
@@ -281,7 +330,7 @@ impl<'l> BlockBuilder<'l> {
Ok(inst.into())
}
pub fn load(&mut self, value: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn load(&mut self, value: AnyValue<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
let value_ty = value.ty();
match value_ty {
Type::Ptr(PtrT { .. }) => {}
@@ -294,7 +343,11 @@ impl<'l> BlockBuilder<'l> {
Ok(inst.into())
}
pub fn add(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn add(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -310,7 +363,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn sub(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn sub(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -326,7 +383,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn mul(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn mul(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -342,7 +403,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn div(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn div(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -358,7 +423,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn modulo(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn modulo(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -374,7 +443,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn trunc(&mut self, val: Value<'l>, target: IntT) -> BlockBuilderResult<'l, Value<'l>> {
pub fn trunc(
&mut self,
val: AnyValue<'l>,
target: IntT,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let ty = val.ty();
match ty {
Type::Int(a_ty) if a_ty.precision > target.precision => {
@@ -387,12 +460,29 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn int_to_ptr(
&mut self,
val: AnyValue<'l>,
target: &'l PtrT<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let ty = val.ty();
match ty {
Type::Int(_) => {
let inst = self.push_instruction(InstructionVariant::IntToPtr(val, target))?;
Ok(inst.into())
}
_ => Err(
format!("Cannot convert value of type `{ty}` to pointer type `{target}`.").into(),
),
}
}
pub fn cmp(
&mut self,
a: Value<'l>,
b: Value<'l>,
a: AnyValue<'l>,
b: AnyValue<'l>,
cmp: Cmp,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let [a_ty, b_ty] = [a.ty(), b.ty()];
match (a_ty, b_ty) {
@@ -408,7 +498,11 @@ impl<'l> BlockBuilder<'l> {
}
}
pub fn gep(&mut self, value: Value<'l>, index: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn get_element_ptr(
&mut self,
value: AnyValue<'l>,
index: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let v_ty = value.ty();
let i_ty = index.ty();
@@ -432,7 +526,62 @@ impl<'l> BlockBuilder<'l> {
Ok(inst.into())
}
pub fn jump(&mut self, block: &'l Block<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn get_element_value(
&mut self,
value: AnyValue<'l>,
index: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let v_ty = value.ty();
match v_ty {
Type::Struct(StructT { fields, .. }) => 'val: {
let AnyValue::Constant(AnyConst::Str(field)) = index else {
return Err(
format!("Expeted index type `const str`, found {}.", index.ty()).into(),
);
};
if let Some(fields) = fields.get() {
if fields.contains_key(field) {
let inst =
self.push_instruction(InstructionVariant::GetElementVal(value, index))?;
break 'val Ok(inst.into());
}
}
Err(format!("Struct does not contain field `{field}`.").into())
}
_ => Err(format!("Cannot index a value of type `{}`.", v_ty).into()),
}
}
pub fn make_struct(
&mut self,
struct_ty: &'l StructT<'l>,
values: &'l [AnyValue<'l>],
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let fields = struct_ty.fields.get().unwrap();
if fields.len() != values.len() {
return Err(
format!("Expected {} values, found {}.", fields.len(), values.len()).into(),
);
}
if let Some((i, (a, b))) = fields
.values()
.zip(values)
.enumerate()
.find(|(_, (a, b))| a.ty != b.ty())
{
return Err(format!(
"Invalid valua at position {i}. Expected type `{}`, found `{}`.",
a.ty,
b.ty()
)
.into());
}
let inst = self.push_instruction(InstructionVariant::MakeStruct(struct_ty, values))?;
return Ok(inst.into());
}
pub fn jump(&mut self, block: &'l Block<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
if !std::ptr::eq(block.func, self.block.func) {
return Err("Block does not belong to this function.".into());
}
@@ -442,10 +591,10 @@ impl<'l> BlockBuilder<'l> {
pub fn branch(
&mut self,
cond: Value<'l>,
cond: AnyValue<'l>,
true_case: &'l Block<'l>,
false_case: &'l Block<'l>,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
if !std::ptr::eq(true_case.func, self.block.func) {
return Err("Block does not belong to this function.".into());
}
@@ -466,8 +615,8 @@ impl<'l> BlockBuilder<'l> {
pub fn call(
&mut self,
func: &'l Function<'l>,
args: Vec<Value<'l>>,
) -> BlockBuilderResult<'l, Value<'l>> {
args: Vec<AnyValue<'l>>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let par_t = &*func.ty.par_t;
if par_t.len() != args.len() {
return Err(format!(
@@ -491,7 +640,7 @@ impl<'l> BlockBuilder<'l> {
Ok(inst.into())
}
pub fn ret(&mut self, value: Option<Value<'l>>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn ret(&mut self, value: Option<AnyValue<'l>>) -> BlockBuilderResult<'l, AnyValue<'l>> {
let ret_t = self.block.func.ty.ret_t;
let value_ty = match value {
Some(v) => v.ty(),
@@ -514,10 +663,10 @@ impl<'l> BlockBuilder<'l> {
/// The target reinterpretation must maintain the IR's invariants.
pub unsafe fn reinterpret(
&mut self,
value: Value<'l>,
value: AnyValue<'l>,
ty: Type<'l>,
flags: ValueFlags,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
let inst = self.push_instruction(InstructionVariant::Reinterpret(value, ty, flags))?;
Ok(inst.into())
}
@@ -620,81 +769,133 @@ impl<'l> FunctionBodyBuilder<'l> {
Ok(self.func.body.get().unwrap())
}
pub fn stack_alloc(&mut self, ty: Type<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn stack_alloc(&mut self, ty: Type<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().stack_alloc(ty)
}
pub fn store(
&mut self,
target: Value<'l>,
value: Value<'l>,
) -> BlockBuilderResult<'l, Value<'l>> {
target: AnyValue<'l>,
value: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().store(target, value)
}
pub fn load(&mut self, value: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn load(&mut self, value: AnyValue<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().load(value)
}
pub fn add(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn add(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().add(a, b)
}
pub fn sub(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn sub(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().sub(a, b)
}
pub fn mul(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn mul(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().mul(a, b)
}
pub fn div(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn div(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().div(a, b)
}
pub fn modulo(&mut self, a: Value<'l>, b: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn modulo(
&mut self,
a: AnyValue<'l>,
b: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().modulo(a, b)
}
pub fn trunc(&mut self, val: Value<'l>, target: IntT) -> BlockBuilderResult<'l, Value<'l>> {
pub fn trunc(
&mut self,
val: AnyValue<'l>,
target: IntT,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().trunc(val, target)
}
pub fn int_to_ptr(
&mut self,
val: AnyValue<'l>,
target: &'l PtrT<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().int_to_ptr(val, target)
}
pub fn cmp(
&mut self,
a: Value<'l>,
b: Value<'l>,
a: AnyValue<'l>,
b: AnyValue<'l>,
cmp: Cmp,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().cmp(a, b, cmp)
}
pub fn gep(&mut self, value: Value<'l>, index: Value<'l>) -> BlockBuilderResult<'l, Value<'l>> {
self.current_builder().gep(value, index)
pub fn get_element_ptr(
&mut self,
value: AnyValue<'l>,
index: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().get_element_ptr(value, index)
}
pub fn jump(&mut self, block: &'l Block<'l>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn get_element_value(
&mut self,
value: AnyValue<'l>,
index: AnyValue<'l>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().get_element_value(value, index)
}
pub fn make_struct(
&mut self,
struct_ty: &'l StructT<'l>,
values: &'l [AnyValue<'l>],
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().make_struct(struct_ty, values)
}
pub fn jump(&mut self, block: &'l Block<'l>) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().jump(block)
}
pub fn branch(
&mut self,
cond: Value<'l>,
cond: AnyValue<'l>,
true_case: &'l Block<'l>,
false_case: &'l Block<'l>,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().branch(cond, true_case, false_case)
}
pub fn call(
&mut self,
func: &'l Function<'l>,
args: Vec<Value<'l>>,
) -> BlockBuilderResult<'l, Value<'l>> {
args: Vec<AnyValue<'l>>,
) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().call(func, args)
}
pub fn ret(&mut self, value: Option<Value<'l>>) -> BlockBuilderResult<'l, Value<'l>> {
pub fn ret(&mut self, value: Option<AnyValue<'l>>) -> BlockBuilderResult<'l, AnyValue<'l>> {
self.current_builder().ret(value)
}
@@ -705,10 +906,10 @@ impl<'l> FunctionBodyBuilder<'l> {
/// The target reinterpretation must maintain the IR's invariants.
pub unsafe fn reinterpret(
&mut self,
value: Value<'l>,
value: AnyValue<'l>,
ty: Type<'l>,
flags: ValueFlags,
) -> BlockBuilderResult<'l, Value<'l>> {
) -> BlockBuilderResult<'l, AnyValue<'l>> {
unsafe { self.current_builder().reinterpret(value, ty, flags) }
}
+29 -6
View File
@@ -1,7 +1,8 @@
use crate::{
assembly::{Assembly, Ctx},
functions::ir::{Block, FunctionBodyBuilder},
types::derivations::FuncT,
types::{Type, derivations::FuncT},
values::{AnyConst, AnyValue, Value, ValueFlags, default_associated_values},
};
use std::{
fmt::{Debug as FmtDebug, Display},
@@ -14,7 +15,7 @@ pub mod ir;
#[non_exhaustive]
pub struct Function<'l> {
pub ty: &'l FuncT<'l>,
pub name: OnceLock<&'l str>,
pub name: &'l str,
pub(crate) body: OnceLock<FunctionBody<'l>>,
pub(crate) declaring_assembly: &'l Assembly<'l>,
}
@@ -40,6 +41,28 @@ impl<'l> Function<'l> {
}
}
impl<'l> Value<'l> for &'l Function<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Func(self.ty)
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Function
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
default_associated_values(self, name)
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Function(self))
}
}
impl Eq for Function<'_> {}
impl PartialEq for Function<'_> {
@@ -50,9 +73,9 @@ 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),
match self.name {
"" => Display::fmt(&self.ty, f),
_ => write!(f, "{} @ {}", self.ty, self.name),
}
}
}
@@ -66,7 +89,7 @@ impl FmtDebug for Function<'_> {
f.debug_struct("Function")
.field("ty", &format_args!("{}", self.ty))
.field("name", &self.name.get())
.field("name", &self.name)
.field("body", body)
.finish_non_exhaustive()
}
+71
View File
@@ -0,0 +1,71 @@
use crate::{
assembly::Assembly,
types::Type,
values::{AnyConst, AnyValue, Value, ValueFlags},
};
use derive_more::{Debug, Display};
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use std::{hash::Hash, sync::OnceLock};
pub type FieldMap<'l> = IndexMap<&'l str, Field<'l>, FxBuildHasher>;
#[derive(Debug, Display, Clone)]
#[display("{}", if name.is_empty() { "<anonymous struct>" } else { name })]
pub struct StructT<'l> {
pub name: &'l str,
pub fields: OnceLock<FieldMap<'l>>,
#[debug(ignore)]
pub declaring_assembly: &'l Assembly<'l>,
}
impl Eq for StructT<'_> {}
impl PartialEq for StructT<'_> {
fn eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other)
}
}
impl Hash for StructT<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
std::ptr::hash(self, state);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Field<'l> {
pub name: &'l str,
pub ty: Type<'l>,
pub public: bool,
pub mutable: bool,
}
impl<'l> Value<'l> for &'l StructT<'l> {
fn ty(&self) -> Type<'l> {
Type::Type
}
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
todo!()
}
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Struct(self)))
}
}
struct DebugFields<'l, 'r>(&'r OnceLock<FieldMap<'l>>);
impl std::fmt::Debug for DebugFields<'_, '_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.0.get() {
Some(v) => std::fmt::Debug::fmt(v, f),
None => f.write_str("{}"),
}
}
}
+133 -8
View File
@@ -61,13 +61,12 @@ impl<'l> TypeDerivations<'l> {
.fun_t
.entry_sync((ret_t, par_t.clone()))
.or_insert_with(|| {
let ctx = ret_t.ctx();
for ty in par_t.iter() {
if ty.ctx() != ctx {
panic!("All types must share the same context.");
}
}
(&*self.alloc.alloc(FuncT { ret_t, par_t })).into()
(&*self.alloc.alloc(FuncT {
ret_t,
par_t,
par_t_const: OnceLock::new(),
}))
.into()
})
else {
unreachable!()
@@ -99,6 +98,32 @@ pub struct PtrT<'l> {
pub mutable: bool,
}
impl<'l> Value<'l> for &'l PtrT<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"base" => Some(self.base.as_any_value()),
"mutable" => Some(self.mutable.as_any_value()),
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Ptr(self)))
}
}
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display("&{}{}", if *mutable { "mut " } else { "" }, *base)]
@@ -108,6 +133,32 @@ pub struct RefT<'l> {
pub mutable: bool,
}
impl<'l> Value<'l> for &'l RefT<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"base" => Some(self.base.as_any_value()),
"mutable" => Some(self.mutable.as_any_value()),
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Ref(self)))
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ArrayT<'l> {
@@ -116,6 +167,35 @@ pub struct ArrayT<'l> {
pub length: Option<u32>,
}
impl<'l> Value<'l> for &'l ArrayT<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"base" => Some(self.base.as_any_value()),
"length" => match self.length {
None => None,
Some(len) => Some(len.as_any_value()),
},
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Array(self)))
}
}
impl Display for ArrayT<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.length {
@@ -126,10 +206,55 @@ impl Display for ArrayT<'_> {
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone)]
pub struct FuncT<'l> {
pub ret_t: Type<'l>,
pub par_t: Arc<[Type<'l>]>,
par_t_const: OnceLock<Vec<AnyConst<'l>>>,
}
impl Eq for FuncT<'_> {}
impl PartialEq for FuncT<'_> {
fn eq(&self, other: &Self) -> bool {
self.ret_t == other.ret_t && self.par_t == other.par_t
}
}
impl Hash for FuncT<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.ret_t.hash(state);
self.par_t.hash(state);
}
}
impl<'l> Value<'l> for &'l FuncT<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"ret_t" => Some(self.ret_t.as_any_value()),
"par_t" => Some(AnyValue::Constant(AnyConst::Array(
self.par_t_const
.get_or_init(|| self.par_t.iter().map(|t| AnyConst::Type(*t)).collect()),
))),
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Func(self)))
}
}
impl Display for FuncT<'_> {
+109 -11
View File
@@ -1,8 +1,13 @@
use crate::{assembly::Context, types::derivations::*};
use crate::{
assembly::Context,
types::{compound::*, derivations::*},
values::{AnyConst, AnyValue, Value, ValueFlags, default_associated_values},
};
use derive_more::{Debug, Display, From, TryInto};
use leaf_allocators::SyncArenaAllocator;
use std::{fmt::Display, sync::OnceLock};
pub mod compound;
pub mod derivations;
#[non_exhaustive]
@@ -18,6 +23,32 @@ pub struct IntT {
pub precision: u32,
}
impl<'l> Value<'l> for IntT {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"signed" => Some(self.signed.as_any_value()),
"precision" => Some(self.precision.as_any_value()),
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Int(*self)))
}
}
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Hash)]
#[display("f{}", precision)]
@@ -26,6 +57,31 @@ pub struct FloatT {
pub precision: u32,
}
impl<'l> Value<'l> for FloatT {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match name {
"precision" => Some(self.precision.as_any_value()),
_ => default_associated_values(self, name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(Type::Float(*self)))
}
}
#[non_exhaustive]
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
pub enum Type<'l> {
@@ -58,6 +114,10 @@ pub enum Type<'l> {
#[debug("{_0:?}")]
#[display("{_0}")]
Func(&'l FuncT<'l>),
#[debug("{_0:?}")]
#[display("{_0}")]
Struct(&'l StructT<'l>),
}
impl<'l> Type<'l> {
@@ -65,16 +125,7 @@ impl<'l> Type<'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)
},
None => Self::default_ctx(),
}
}
@@ -94,8 +145,55 @@ impl<'l> Type<'l> {
Some(ctx) => Some(ctx),
None => f.par_t.iter().find_map(|t| t.non_default_ctx()),
},
Type::Struct(s) => Some(s.declaring_assembly.ctx()),
}
}
fn default_ctx() -> &'l Context<'l> {
static ALLOCATOR: OnceLock<SyncArenaAllocator> = OnceLock::new();
static DEFAULT: OnceLock<&'static Context> = OnceLock::new();
let ctx: &'static Context = DEFAULT.get_or_init(|| {
let allocator: &'static SyncArenaAllocator =
ALLOCATOR.get_or_init(SyncArenaAllocator::default);
Context::new(allocator)
});
unsafe { std::mem::transmute(ctx) }
}
}
impl<'l> Value<'l> for Type<'l> {
#[inline]
fn ty(&self) -> Type<'l> {
Type::Type
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Type
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match self {
Type::Void => default_associated_values(self, name),
Type::Char => default_associated_values(self, name),
Type::Bool => default_associated_values(self, name),
Type::Type => default_associated_values(self, name),
Type::ConstStr => default_associated_values(self, name),
Type::Int(t) => t.get_associated_value(name),
Type::Float(t) => t.get_associated_value(name),
Type::Ptr(t) => t.get_associated_value(name),
Type::Ref(t) => t.get_associated_value(name),
Type::Array(t) => t.get_associated_value(name),
Type::Func(t) => t.get_associated_value(name),
Type::Struct(t) => t.get_associated_value(name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Type(*self))
}
}
#[rustfmt::skip]
+186 -42
View File
@@ -1,7 +1,7 @@
use crate::{
functions::Function,
types::{Type, derivations::ArrayT},
values::ValueFlags,
types::{Type, compound::StructT, derivations::ArrayT},
values::{AnyValue, Value, ValueFlags, default_associated_values},
};
use derive_more::{Debug, *};
use half::f16;
@@ -12,18 +12,66 @@ pub enum Int {
I8(i8),
I16(i16),
I32(i32),
I64(i64),
#[from]
I64(i64),
I128(i128),
ISize(i128),
ISize(i64),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
#[from]
U64(u64),
U128(u128),
USize(u128),
USize(u64),
}
impl<'l> Value<'l> for Int {
#[inline]
fn ty(&self) -> Type<'l> {
match self {
Int::I8(v) => v.ty(),
Int::I16(v) => v.ty(),
Int::I32(v) => v.ty(),
Int::I64(v) => v.ty(),
Int::I128(v) => v.ty(),
Int::ISize(_) => Type::ISIZE,
Int::U8(v) => v.ty(),
Int::U16(v) => v.ty(),
Int::U32(v) => v.ty(),
Int::U64(v) => v.ty(),
Int::U128(v) => v.ty(),
Int::USize(_) => Type::USIZE,
}
}
#[inline]
fn flags(&self) -> ValueFlags {
default_value_flags(self)
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match self {
Int::I8(v) => v.get_associated_value(name),
Int::I16(v) => v.get_associated_value(name),
Int::I32(v) => v.get_associated_value(name),
Int::I64(v) => v.get_associated_value(name),
Int::I128(v) => v.get_associated_value(name),
Int::ISize(v) => v.get_associated_value(name),
Int::U8(v) => v.get_associated_value(name),
Int::U16(v) => v.get_associated_value(name),
Int::U32(v) => v.get_associated_value(name),
Int::U64(v) => v.get_associated_value(name),
Int::U128(v) => v.get_associated_value(name),
Int::USize(v) => v.get_associated_value(name),
}
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Int(*self))
}
}
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq)]
@@ -33,6 +81,33 @@ pub enum Float {
F64(f64),
}
impl<'l> Value<'l> for Float {
#[inline]
fn ty(&self) -> Type<'l> {
match self {
Float::F16(v) => v.ty(),
Float::F32(v) => v.ty(),
Float::F64(v) => v.ty(),
_ => unreachable!(),
}
}
#[inline]
fn flags(&self) -> ValueFlags {
ValueFlags::Const
}
#[inline]
fn get_associated_value(&self, _name: &str) -> Option<AnyValue<'l>> {
None
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
AnyValue::Constant(AnyConst::Float(*self))
}
}
impl Eq for Float {}
impl Hash for Float {
@@ -45,20 +120,6 @@ impl Hash for Float {
}
}
#[derive(Debug, Display, Deref, DerefMut, Clone, Copy, From, PartialEq, Eq, Hash)]
#[debug("{:?}", _0)]
#[display("{}", _0)]
pub struct Const<T>(T);
impl<'l, T: 'l> From<&'l Const<T>> for AnyConst<'l>
where
for<'a> &'a T: Into<AnyConst<'a>>,
{
fn from(val: &'l Const<T>) -> Self {
(&val.0).into()
}
}
struct ListDisplay<'l>(&'l [AnyConst<'l>]);
impl std::fmt::Display for ListDisplay<'_> {
@@ -71,6 +132,19 @@ impl std::fmt::Display for ListDisplay<'_> {
}
}
struct StructDisplay<'l>(&'l StructT<'l>, &'l [AnyConst<'l>]);
impl std::fmt::Display for StructDisplay<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} ", self.0)?;
let mut list = f.debug_list();
for ele in self.1 {
list.entry(&format_args!("{ele}"));
}
list.finish()
}
}
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
#[from(forward)]
pub enum AnyConst<'l> {
@@ -98,45 +172,115 @@ pub enum AnyConst<'l> {
#[debug("{:?}", _0)]
#[display("{}", ListDisplay(_0))]
Array(&'l [AnyConst<'l>]),
#[debug("{:?}", _0)]
#[display("{}", StructDisplay(_0, _1))]
Struct(&'l StructT<'l>, &'l [AnyConst<'l>]),
Type(Type<'l>),
}
impl<'l> AnyConst<'l> {
pub fn ty(&self) -> Type<'l> {
impl<'l> Value<'l> for AnyConst<'l> {
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::ISize(_)) => Type::ISIZE,
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::Int(Int::USize(_)) => Type::USIZE,
Self::Float(Float::F16(_)) => Type::F16,
Self::Float(Float::F32(_)) => Type::F32,
Self::Float(Float::F64(_)) => Type::F64,
Self::Bool(v) => v.ty(),
Self::Char(v) => v.ty(),
Self::Type(v) => v.ty(),
Self::Int(v) => v.ty(),
Self::Float(v) => v.ty(),
Self::Array([]) => Type::Array(&ArrayT {
base: Type::Void,
length: Some(0),
}),
Self::Array(a @ [v, ..]) => Type::Array(v.ty().make_array(Some(a.len() as u32))),
Self::Str(s) => s.ty(),
Self::Struct(t, _) => Type::Struct(t),
_ => todo!("{self:?}"),
}
}
pub fn flags(&self) -> super::ValueFlags {
fn flags(&self) -> super::ValueFlags {
match self {
AnyConst::Function(_) => ValueFlags::Function,
AnyConst::Function(f) => ValueFlags::Function,
AnyConst::Type(_) => ValueFlags::Type,
_ => ValueFlags::Const,
}
}
fn get_associated_value(&self, name: &str) -> Option<super::AnyValue<'l>> {
match self {
AnyConst::Void => ().get_associated_value(name),
AnyConst::Bool(v) => v.get_associated_value(name),
AnyConst::Char(v) => v.get_associated_value(name),
AnyConst::Int(v) => v.get_associated_value(name),
AnyConst::Float(v) => v.get_associated_value(name),
AnyConst::Str(v) => v.get_associated_value(name),
AnyConst::Function(f) => f.get_associated_value(name),
AnyConst::Array(_) => default_associated_values(self, name),
AnyConst::Struct(t, _) => t.get_associated_value(name),
AnyConst::Type(t) => t.get_associated_value(name),
}
}
fn as_any_value(&self) -> super::AnyValue<'l> {
AnyValue::Constant(*self)
}
}
#[inline]
fn default_value_flags(_: &dyn Value) -> ValueFlags {
ValueFlags::Const
}
macro_rules! impl_value {
($(
$variant:ident : $ty:ty | $leaf_ty:expr => |$ident:ident| $expr:expr,
)*) => {
$(
impl<'l> Value<'l> for $ty {
#[inline]
fn ty(&self) -> Type<'l> {
$leaf_ty
}
#[inline]
fn flags(&self) -> ValueFlags {
default_value_flags(self)
}
#[inline]
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
default_associated_values(self, name)
}
#[inline]
fn as_any_value(&self) -> AnyValue<'l> {
let $ident = self;
$expr
}
}
)*
};
}
impl_value! {
Void: () | Type::Void => |_v| AnyValue::Constant(AnyConst::Void),
Char: char | Type::Char => |v| AnyValue::Constant(AnyConst::Char(*v)),
Bool: bool | Type::Bool => |v| AnyValue::Constant(AnyConst::Bool(*v)),
I8 : i8 | Type::I8 => |v| AnyValue::Constant(AnyConst::Int(Int::I8(*v))),
I16 : i16 | Type::I16 => |v| AnyValue::Constant(AnyConst::Int(Int::I16(*v))),
I32 : i32 | Type::I32 => |v| AnyValue::Constant(AnyConst::Int(Int::I32(*v))),
I64 : i64 | Type::I64 => |v| AnyValue::Constant(AnyConst::Int(Int::I64(*v))),
I128: i128 | Type::I128 => |v| AnyValue::Constant(AnyConst::Int(Int::I128(*v))),
U8 : u8 | Type::U8 => |v| AnyValue::Constant(AnyConst::Int(Int::U8(*v))),
U16 : u16 | Type::U16 => |v| AnyValue::Constant(AnyConst::Int(Int::U16(*v))),
U32 : u32 | Type::U32 => |v| AnyValue::Constant(AnyConst::Int(Int::U32(*v))),
U64 : u64 | Type::U64 => |v| AnyValue::Constant(AnyConst::Int(Int::U64(*v))),
U128: u128 | Type::U128 => |v| AnyValue::Constant(AnyConst::Int(Int::U128(*v))),
F16 : f16 | Type::F16 => |v| AnyValue::Constant(AnyConst::Float(Float::F16(*v))),
F32 : f32 | Type::F32 => |v| AnyValue::Constant(AnyConst::Float(Float::F32(*v))),
F64 : f64 | Type::F64 => |v| AnyValue::Constant(AnyConst::Float(Float::F64(*v))),
ConstStr: &'l str | Type::ConstStr => |v| AnyValue::Constant(AnyConst::Str(*v)),
}
+48 -13
View File
@@ -23,7 +23,7 @@ bitflags! {
}
#[derive(Debug, Display, Clone, Copy, From, TryInto, PartialEq, Eq, Hash)]
pub enum Value<'l> {
pub enum AnyValue<'l> {
#[display("{_0}")]
Constant(AnyConst<'l>),
#[display("{_0}")]
@@ -34,27 +34,62 @@ pub enum Value<'l> {
Parameter(usize, &'l Function<'l>),
}
impl From<Int> for Value<'_> {
impl From<Int> for AnyValue<'_> {
fn from(value: Int) -> Self {
Value::Constant(AnyConst::Int(value))
AnyValue::Constant(AnyConst::Int(value))
}
}
impl<'l> Value<'l> {
pub fn ty(&self) -> Type<'l> {
pub trait Value<'l> {
fn ty(&self) -> Type<'l>;
fn flags(&self) -> ValueFlags;
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>>;
fn as_any_value(&self) -> AnyValue<'l>;
#[inline]
fn is_const(&self) -> bool {
self.flags().contains(ValueFlags::Const)
}
#[inline]
fn is_lvalue(&self) -> bool {
self.flags().contains(ValueFlags::LValue)
}
}
impl<'l> Value<'l> for AnyValue<'l> {
fn ty(&self) -> Type<'l> {
match self {
Value::Constant(v) => v.ty(),
Value::Instruction(v) => v.value_ty(),
Value::Parameter(i, f) => f.ty.par_t[*i],
AnyValue::Constant(v) => v.ty(),
AnyValue::Instruction(v) => v.ty(),
AnyValue::Parameter(i, f) => f.ty.par_t[*i],
}
}
pub fn flags(&self) -> ValueFlags {
fn flags(&self) -> ValueFlags {
match self {
Value::Instruction(v) => v.value_flags(),
Value::Parameter(_, _) => ValueFlags::empty(),
Value::Constant(c) => c.flags(),
_ => todo!("{self:?}"),
AnyValue::Instruction(v) => v.flags(),
AnyValue::Parameter(_, _) => ValueFlags::empty(),
AnyValue::Constant(c) => c.flags(),
}
}
fn get_associated_value(&self, name: &str) -> Option<AnyValue<'l>> {
match self {
AnyValue::Constant(v) => v.get_associated_value(name),
AnyValue::Instruction(v) => todo!(),
AnyValue::Parameter(_, _) => default_associated_values(self, name),
}
}
fn as_any_value(&self) -> AnyValue<'l> {
*self
}
}
pub(crate) fn default_associated_values<'l>(v: &dyn Value<'l>, name: &str) -> Option<AnyValue<'l>> {
match name {
"#type" => Some(AnyValue::Constant(AnyConst::Type(v.ty()))),
_ => None,
}
}