wasmtime_environ/
module_types.rs

1use crate::PrimaryMap;
2use core::ops::{Index, Range};
3use cranelift_entity::{packed_option::PackedOption, SecondaryMap};
4use serde_derive::{Deserialize, Serialize};
5use wasmtime_types::{ModuleInternedRecGroupIndex, ModuleInternedTypeIndex, WasmSubType};
6
7/// All types used in a core wasm module.
8///
9/// Note that accessing this type is primarily done through the `Index`
10/// implementations for this type.
11#[derive(Default, Serialize, Deserialize)]
12pub struct ModuleTypes {
13    rec_groups: PrimaryMap<ModuleInternedRecGroupIndex, Range<ModuleInternedTypeIndex>>,
14    wasm_types: PrimaryMap<ModuleInternedTypeIndex, WasmSubType>,
15    trampoline_types: SecondaryMap<ModuleInternedTypeIndex, PackedOption<ModuleInternedTypeIndex>>,
16}
17
18impl ModuleTypes {
19    /// Returns an iterator over all the wasm function signatures found within
20    /// this module.
21    pub fn wasm_types(
22        &self,
23    ) -> impl ExactSizeIterator<Item = (ModuleInternedTypeIndex, &WasmSubType)> {
24        self.wasm_types.iter()
25    }
26
27    /// Get the type at the specified index, if it exists.
28    pub fn get(&self, ty: ModuleInternedTypeIndex) -> Option<&WasmSubType> {
29        self.wasm_types.get(ty)
30    }
31
32    /// Get an iterator over all recursion groups defined in this module and
33    /// their elements.
34    pub fn rec_groups(
35        &self,
36    ) -> impl ExactSizeIterator<Item = (ModuleInternedRecGroupIndex, Range<ModuleInternedTypeIndex>)> + '_
37    {
38        self.rec_groups.iter().map(|(k, v)| (k, v.clone()))
39    }
40
41    /// Get the elements within an already-defined rec group.
42    pub fn rec_group_elements(
43        &self,
44        rec_group: ModuleInternedRecGroupIndex,
45    ) -> impl ExactSizeIterator<Item = ModuleInternedTypeIndex> {
46        let range = &self.rec_groups[rec_group];
47        (range.start.as_u32()..range.end.as_u32()).map(|i| ModuleInternedTypeIndex::from_u32(i))
48    }
49
50    /// Returns the number of types interned.
51    pub fn len_types(&self) -> usize {
52        self.wasm_types.len()
53    }
54
55    /// Adds a new type to this interned list of types.
56    pub fn push(&mut self, ty: WasmSubType) -> ModuleInternedTypeIndex {
57        self.wasm_types.push(ty)
58    }
59
60    /// Iterate over the trampoline function types that this module requires.
61    ///
62    /// Yields pairs of (1) a function type and (2) its associated trampoline
63    /// type. They might be the same.
64    ///
65    /// See the docs for `WasmFuncType::trampoline_type` for details on
66    /// trampoline types.
67    pub fn trampoline_types(
68        &self,
69    ) -> impl Iterator<Item = (ModuleInternedTypeIndex, ModuleInternedTypeIndex)> + '_ {
70        self.trampoline_types
71            .iter()
72            .filter_map(|(k, v)| v.expand().map(|v| (k, v)))
73    }
74
75    /// Get the trampoline type for the given function type.
76    ///
77    /// See the docs for `WasmFuncType::trampoline_type` for details on
78    /// trampoline types.
79    pub fn trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex {
80        debug_assert!(self[ty].is_func());
81        self.trampoline_types[ty].unwrap()
82    }
83}
84
85/// Methods that only exist for `ModuleTypesBuilder`.
86#[cfg(feature = "compile")]
87impl ModuleTypes {
88    /// Associate `trampoline_ty` as the trampoline type for `for_ty`.
89    ///
90    /// This is really only for use by the `ModuleTypesBuilder`.
91    pub fn set_trampoline_type(
92        &mut self,
93        for_ty: ModuleInternedTypeIndex,
94        trampoline_ty: ModuleInternedTypeIndex,
95    ) {
96        use cranelift_entity::packed_option::ReservedValue;
97
98        debug_assert!(!for_ty.is_reserved_value());
99        debug_assert!(!trampoline_ty.is_reserved_value());
100        debug_assert!(self.wasm_types[for_ty].is_func());
101        debug_assert!(self.trampoline_types[for_ty].is_none());
102        debug_assert!(self.wasm_types[trampoline_ty]
103            .unwrap_func()
104            .is_trampoline_type());
105
106        self.trampoline_types[for_ty] = Some(trampoline_ty).into();
107    }
108
109    /// Adds a new rec group to this interned list of types.
110    pub fn push_rec_group(
111        &mut self,
112        range: Range<ModuleInternedTypeIndex>,
113    ) -> ModuleInternedRecGroupIndex {
114        self.rec_groups.push(range)
115    }
116
117    /// Reserves space for `amt` more types.
118    pub fn reserve(&mut self, amt: usize) {
119        self.wasm_types.reserve(amt)
120    }
121
122    /// Returns the next return value of `push_rec_group`.
123    pub fn next_rec_group(&self) -> ModuleInternedRecGroupIndex {
124        self.rec_groups.next_key()
125    }
126
127    /// Returns the next return value of `push`.
128    pub fn next_ty(&self) -> ModuleInternedTypeIndex {
129        self.wasm_types.next_key()
130    }
131}
132
133impl Index<ModuleInternedTypeIndex> for ModuleTypes {
134    type Output = WasmSubType;
135
136    fn index(&self, sig: ModuleInternedTypeIndex) -> &WasmSubType {
137        &self.wasm_types[sig]
138    }
139}