wasmtime_environ/
module_types.rs

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