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