1 use crate::{
2     ModuleInternedRecGroupIndex, ModuleInternedTypeIndex, PanicOnOom as _, TypeTrace, WasmSubType,
3     packed_option::PackedOption, prelude::*,
4 };
5 use core::ops::{Index, Range};
6 use 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)]
13 pub 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 
20 impl TypeTrace for ModuleTypes {
trace<F, E>(&self, func: &mut F) -> Result<(), E> where F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,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 
trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E> where F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,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 
42 impl ModuleTypes {
43     /// Returns an iterator over all the wasm function signatures found within
44     /// this module.
wasm_types( &self, ) -> impl ExactSizeIterator<Item = (ModuleInternedTypeIndex, &WasmSubType)>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.
get(&self, ty: ModuleInternedTypeIndex) -> Option<&WasmSubType>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.
rec_groups( &self, ) -> impl ExactSizeIterator<Item = (ModuleInternedRecGroupIndex, Range<ModuleInternedTypeIndex>)> + '_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.
rec_group_elements( &self, rec_group: ModuleInternedRecGroupIndex, ) -> impl ExactSizeIterator<Item = ModuleInternedTypeIndex> + use<>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.
len_types(&self) -> usize75     pub fn len_types(&self) -> usize {
76         self.wasm_types.len()
77     }
78 
79     /// Adds a new type to this interned list of types.
push(&mut self, ty: WasmSubType) -> ModuleInternedTypeIndex80     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.
trampoline_types( &self, ) -> impl Iterator<Item = (ModuleInternedTypeIndex, ModuleInternedTypeIndex)> + '_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.
trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex103     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.
iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut WasmSubType>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")]
116 impl ModuleTypes {
117     /// Associate `trampoline_ty` as the trampoline type for `for_ty`.
set_trampoline_type( &mut self, for_ty: ModuleInternedTypeIndex, trampoline_ty: ModuleInternedTypeIndex, )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.
push_rec_group( &mut self, range: Range<ModuleInternedTypeIndex>, ) -> ModuleInternedRecGroupIndex141     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.
reserve(&mut self, amt: usize)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`.
next_rec_group(&self) -> ModuleInternedRecGroupIndex154     pub fn next_rec_group(&self) -> ModuleInternedRecGroupIndex {
155         self.rec_groups.next_key()
156     }
157 
158     /// Returns the next return value of `push`.
next_ty(&self) -> ModuleInternedTypeIndex159     pub fn next_ty(&self) -> ModuleInternedTypeIndex {
160         self.wasm_types.next_key()
161     }
162 }
163 
164 impl Index<ModuleInternedTypeIndex> for ModuleTypes {
165     type Output = WasmSubType;
166 
index(&self, sig: ModuleInternedTypeIndex) -> &WasmSubType167     fn index(&self, sig: ModuleInternedTypeIndex) -> &WasmSubType {
168         &self.wasm_types[sig]
169     }
170 }
171