wasmtime_environ/
module_types.rs

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