mod keys;
mod layout;
mod materialize;
mod registry;
pub(crate) use layout::{ArrayLayout, Layout, RefKind, ScalarKind, Slot, StructLayout};
pub(crate) use materialize::{array_field, func_sig, struct_fields};
pub(crate) use registry::TypeRegistry;
use crate::engine::Engine;
use crate::value::{
ArrayType, Finality, FuncType, GlobalType, HeapType, Mutability, RefType, StructType,
TableType, ValType,
};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct CanonicalTypeId(u32);
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct GroupId(u32);
impl CanonicalTypeId {
pub(crate) fn new(raw: u32) -> Self {
CanonicalTypeId(raw)
}
fn index(self) -> usize {
self.0 as usize
}
}
impl GroupId {
fn new(raw: u32) -> Self {
GroupId(raw)
}
fn index(self) -> usize {
self.0 as usize
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum AggKind {
Func,
Struct,
Array,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum IrHeap {
Func,
NoFunc,
Extern,
NoExtern,
Any,
Eq,
I31,
Struct,
Array,
Exn,
NoExn,
None,
Concrete(u32, AggKind),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum IrVal {
I32,
I64,
F32,
F64,
V128,
Ref { nullable: bool, heap: IrHeap },
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum IrStorage {
I8,
I16,
Val(IrVal),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) struct IrField {
pub mutable: bool,
pub storage: IrStorage,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) enum CompositeBody {
Func {
params: Vec<IrVal>,
results: Vec<IrVal>,
},
Struct(Vec<IrField>),
Array(IrField),
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct ModuleType {
pub group: u32,
pub finality: Finality,
pub supertype: Option<u32>,
pub body: CompositeBody,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub(crate) struct IrRef {
pub nullable: bool,
pub heap: IrHeap,
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct IrTableType {
pub element: IrRef,
pub min: u64,
pub max: Option<u64>,
pub table64: bool,
}
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub(crate) struct IrGlobalType {
pub content: IrVal,
pub mutable: bool,
}
impl ModuleType {
pub(crate) fn kind(&self) -> AggKind {
match self.body {
CompositeBody::Func { .. } => AggKind::Func,
CompositeBody::Struct(_) => AggKind::Struct,
CompositeBody::Array(_) => AggKind::Array,
}
}
pub(crate) fn func_sig(&self) -> (&[IrVal], &[IrVal]) {
match &self.body {
CompositeBody::Func { params, results } => (params, results),
_ => unreachable!("not a function type"),
}
}
}
pub(crate) fn materialize_val(engine: &Engine, type_ids: &[CanonicalTypeId], v: &IrVal) -> ValType {
match v {
IrVal::I32 => ValType::I32,
IrVal::I64 => ValType::I64,
IrVal::F32 => ValType::F32,
IrVal::F64 => ValType::F64,
IrVal::V128 => ValType::V128,
IrVal::Ref { nullable, heap } => ValType::Ref(RefType::new(
*nullable,
materialize_heap(engine, type_ids, heap),
)),
}
}
pub(crate) fn materialize_heap(
engine: &Engine,
type_ids: &[CanonicalTypeId],
h: &IrHeap,
) -> HeapType {
match h {
IrHeap::Func => HeapType::Func,
IrHeap::NoFunc => HeapType::NoFunc,
IrHeap::Extern => HeapType::Extern,
IrHeap::NoExtern => HeapType::NoExtern,
IrHeap::Any => HeapType::Any,
IrHeap::Eq => HeapType::Eq,
IrHeap::I31 => HeapType::I31,
IrHeap::Struct => HeapType::Struct,
IrHeap::Array => HeapType::Array,
IrHeap::Exn => HeapType::Exn,
IrHeap::NoExn => HeapType::NoExn,
IrHeap::None => HeapType::None,
IrHeap::Concrete(idx, kind) => {
let id = type_ids[*idx as usize];
match kind {
AggKind::Func => HeapType::ConcreteFunc(FuncType::from_id(engine, id)),
AggKind::Struct => HeapType::ConcreteStruct(StructType::from_id(engine, id)),
AggKind::Array => HeapType::ConcreteArray(ArrayType::from_id(engine, id)),
}
}
}
}
pub(crate) fn materialize_ref(engine: &Engine, type_ids: &[CanonicalTypeId], r: &IrRef) -> RefType {
RefType::new(r.nullable, materialize_heap(engine, type_ids, &r.heap))
}
pub(crate) fn materialize_global(
engine: &Engine,
type_ids: &[CanonicalTypeId],
g: &IrGlobalType,
) -> GlobalType {
let mutability = if g.mutable {
Mutability::Var
} else {
Mutability::Const
};
GlobalType::new(materialize_val(engine, type_ids, &g.content), mutability)
}
pub(crate) fn materialize_table(
engine: &Engine,
type_ids: &[CanonicalTypeId],
t: &IrTableType,
) -> TableType {
let element = materialize_ref(engine, type_ids, &t.element);
if t.table64 {
TableType::new64(element, t.min, t.max)
} else {
TableType::new(element, t.min as u32, t.max.map(|m| m as u32))
}
}
pub(crate) fn func_handle(engine: &Engine, canonical_id: CanonicalTypeId) -> FuncType {
FuncType::from_id(engine, canonical_id)
}