use crate::{ModuleInternedRecGroupIndex, ModuleInternedTypeIndex, PrimaryMap, WasmSubType};
use core::ops::{Index, Range};
use cranelift_entity::{packed_option::PackedOption, SecondaryMap};
use serde_derive::{Deserialize, Serialize};
#[derive(Default, Serialize, Deserialize)]
pub struct ModuleTypes {
rec_groups: PrimaryMap<ModuleInternedRecGroupIndex, Range<ModuleInternedTypeIndex>>,
wasm_types: PrimaryMap<ModuleInternedTypeIndex, WasmSubType>,
trampoline_types: SecondaryMap<ModuleInternedTypeIndex, PackedOption<ModuleInternedTypeIndex>>,
}
impl ModuleTypes {
pub fn wasm_types(
&self,
) -> impl ExactSizeIterator<Item = (ModuleInternedTypeIndex, &WasmSubType)> {
self.wasm_types.iter()
}
pub fn get(&self, ty: ModuleInternedTypeIndex) -> Option<&WasmSubType> {
self.wasm_types.get(ty)
}
pub fn rec_groups(
&self,
) -> impl ExactSizeIterator<Item = (ModuleInternedRecGroupIndex, Range<ModuleInternedTypeIndex>)> + '_
{
self.rec_groups.iter().map(|(k, v)| (k, v.clone()))
}
pub fn rec_group_elements(
&self,
rec_group: ModuleInternedRecGroupIndex,
) -> impl ExactSizeIterator<Item = ModuleInternedTypeIndex> {
let range = &self.rec_groups[rec_group];
(range.start.as_u32()..range.end.as_u32()).map(|i| ModuleInternedTypeIndex::from_u32(i))
}
pub fn len_types(&self) -> usize {
self.wasm_types.len()
}
pub fn push(&mut self, ty: WasmSubType) -> ModuleInternedTypeIndex {
self.wasm_types.push(ty)
}
pub fn trampoline_types(
&self,
) -> impl Iterator<Item = (ModuleInternedTypeIndex, ModuleInternedTypeIndex)> + '_ {
self.trampoline_types
.iter()
.filter_map(|(k, v)| v.expand().map(|v| (k, v)))
}
pub fn trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex {
debug_assert!(self[ty].is_func());
self.trampoline_types[ty].unwrap()
}
}
#[cfg(feature = "compile")]
impl ModuleTypes {
pub fn set_trampoline_type(
&mut self,
for_ty: ModuleInternedTypeIndex,
trampoline_ty: ModuleInternedTypeIndex,
) {
use cranelift_entity::packed_option::ReservedValue;
debug_assert!(!for_ty.is_reserved_value());
debug_assert!(!trampoline_ty.is_reserved_value());
debug_assert!(self.wasm_types[for_ty].is_func());
debug_assert!(self.trampoline_types[for_ty].is_none());
debug_assert!(self.wasm_types[trampoline_ty]
.unwrap_func()
.is_trampoline_type());
self.trampoline_types[for_ty] = Some(trampoline_ty).into();
}
pub fn push_rec_group(
&mut self,
range: Range<ModuleInternedTypeIndex>,
) -> ModuleInternedRecGroupIndex {
self.rec_groups.push(range)
}
pub fn reserve(&mut self, amt: usize) {
self.wasm_types.reserve(amt)
}
pub fn next_rec_group(&self) -> ModuleInternedRecGroupIndex {
self.rec_groups.next_key()
}
pub fn next_ty(&self) -> ModuleInternedTypeIndex {
self.wasm_types.next_key()
}
}
impl Index<ModuleInternedTypeIndex> for ModuleTypes {
type Output = WasmSubType;
fn index(&self, sig: ModuleInternedTypeIndex) -> &WasmSubType {
&self.wasm_types[sig]
}
}