Skip to main content

wasmtime_environ/
module_types.rs

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