1 use crate::{ 2 EngineOrModuleTypeIndex, EntityRef, ModuleInternedRecGroupIndex, ModuleInternedTypeIndex, 3 ModuleTypes, PanicOnOom as _, TypeConvert, TypeIndex, WasmArrayType, WasmCompositeInnerType, 4 WasmCompositeType, WasmExnType, WasmFieldType, WasmFuncType, WasmHeapType, WasmResult, 5 WasmStorageType, WasmStructType, WasmSubType, 6 collections::{TryClone as _, TryCow}, 7 wasm_unsupported, 8 }; 9 use std::{ 10 collections::{HashMap, hash_map::Entry}, 11 ops::Index, 12 }; 13 use wasmparser::{UnpackedIndex, Validator, ValidatorId}; 14 15 /// A type marking the start of a recursion group's definition. 16 /// 17 /// This is initialized by `ModuleTypesBuilder::start_rec_group` and then 18 /// finished in `ModuleTypes::end_rec_group` after all of the types in the rec 19 /// group have been defined. 20 struct RecGroupStart { 21 rec_group_index: ModuleInternedRecGroupIndex, 22 start: ModuleInternedTypeIndex, 23 end: ModuleInternedTypeIndex, 24 } 25 26 /// A builder for [`ModuleTypes`]. 27 pub struct ModuleTypesBuilder { 28 /// The ID of the validator that this builder is configured for. Using a 29 /// different validator, or multiple validators, with this builder would 30 /// result in silliness because our `wasmparser::types::*Id`s are only 31 /// unique within the context of a particular validator. Getting this wrong 32 /// could result in generating calls to functions of the wrong type, for 33 /// example. So therefore we always assert that a builder instances is only 34 /// ever paired with a particular validator context. 35 validator_id: ValidatorId, 36 37 /// The canonicalized and deduplicated set of types we are building. 38 types: ModuleTypes, 39 40 /// The set of trampoline-compatible function types we have already added to 41 /// `self.types`. We do this additional level of deduping, on top of what 42 /// `wasmparser` already does, so we can quickly and easily get the 43 /// trampoline type for a given function type if we've already interned one. 44 trampoline_types: HashMap<WasmFuncType, ModuleInternedTypeIndex>, 45 46 /// An interning map for exception types corresponding to function 47 /// types used by tags. Tags are nominal, but the underlying 48 /// Wasmtime types describe only the object layout and so are 49 /// structural. 50 exception_types: HashMap<ModuleInternedTypeIndex, ModuleInternedTypeIndex>, 51 52 /// A map from already-interned `wasmparser` types to their corresponding 53 /// Wasmtime type. 54 wasmparser_to_wasmtime: HashMap<wasmparser::types::CoreTypeId, ModuleInternedTypeIndex>, 55 56 /// The set of recursion groups we have already seen and interned. 57 already_seen: HashMap<wasmparser::types::RecGroupId, ModuleInternedRecGroupIndex>, 58 59 /// If we are in the middle of defining a recursion group, this is the 60 /// metadata about the recursion group we started defining. 61 defining_rec_group: Option<RecGroupStart>, 62 } 63 64 impl ModuleTypesBuilder { 65 /// Construct a new `ModuleTypesBuilder` using the given validator. new(validator: &Validator) -> Self66 pub fn new(validator: &Validator) -> Self { 67 Self { 68 validator_id: validator.id(), 69 types: ModuleTypes::default(), 70 trampoline_types: HashMap::default(), 71 exception_types: HashMap::default(), 72 wasmparser_to_wasmtime: HashMap::default(), 73 already_seen: HashMap::default(), 74 defining_rec_group: None, 75 } 76 } 77 78 /// Reserves space for `amt` more type signatures. reserve_wasm_signatures(&mut self, amt: usize)79 pub fn reserve_wasm_signatures(&mut self, amt: usize) { 80 self.types.reserve(amt); 81 self.wasmparser_to_wasmtime.reserve(amt); 82 self.already_seen.reserve(amt); 83 } 84 85 /// Get the id of the validator that this builder is configured for. validator_id(&self) -> ValidatorId86 pub fn validator_id(&self) -> ValidatorId { 87 self.validator_id 88 } 89 90 /// Intern a recursion group and all of its types into this builder. 91 /// 92 /// If the recursion group has already been interned, then it is reused. 93 /// 94 /// Panics if given types from a different validator than the one that this 95 /// builder is associated with. intern_rec_group( &mut self, validator_types: wasmparser::types::TypesRef<'_>, rec_group_id: wasmparser::types::RecGroupId, ) -> WasmResult<ModuleInternedRecGroupIndex>96 pub fn intern_rec_group( 97 &mut self, 98 validator_types: wasmparser::types::TypesRef<'_>, 99 rec_group_id: wasmparser::types::RecGroupId, 100 ) -> WasmResult<ModuleInternedRecGroupIndex> { 101 assert_eq!(validator_types.id(), self.validator_id); 102 103 if let Some(interned) = self.already_seen.get(&rec_group_id) { 104 return Ok(*interned); 105 } 106 107 self.define_new_rec_group(validator_types, rec_group_id) 108 } 109 110 /// Define a new recursion group that we haven't already interned. define_new_rec_group( &mut self, validator_types: wasmparser::types::TypesRef<'_>, rec_group_id: wasmparser::types::RecGroupId, ) -> WasmResult<ModuleInternedRecGroupIndex>111 fn define_new_rec_group( 112 &mut self, 113 validator_types: wasmparser::types::TypesRef<'_>, 114 rec_group_id: wasmparser::types::RecGroupId, 115 ) -> WasmResult<ModuleInternedRecGroupIndex> { 116 assert_eq!(validator_types.id(), self.validator_id); 117 118 self.start_rec_group( 119 validator_types, 120 validator_types.rec_group_elements(rec_group_id), 121 ); 122 123 for id in validator_types.rec_group_elements(rec_group_id) { 124 let ty = &validator_types[id]; 125 let wasm_ty = WasmparserTypeConverter::new(self, |_| { 126 unreachable!("no need to lookup indexes; we already have core type IDs") 127 }) 128 .with_rec_group(validator_types, rec_group_id) 129 .convert_sub_type(ty)?; 130 self.wasm_sub_type_in_rec_group(id, wasm_ty); 131 } 132 133 let rec_group_index = self.end_rec_group(rec_group_id); 134 135 // Iterate over all the types we just defined and make sure that every 136 // function type has an associated trampoline type. This needs to happen 137 // *after* we finish defining the rec group because we may need to 138 // intern new function types, which would conflict with the contiguous 139 // range of type indices we pre-reserved for the rec group elements. 140 for ty in self.rec_group_elements(rec_group_index) { 141 if self.types[ty].is_func() { 142 let trampoline = self.intern_trampoline_type(ty); 143 self.types.set_trampoline_type(ty, trampoline); 144 } 145 } 146 147 Ok(rec_group_index) 148 } 149 150 /// Get or create the trampoline function type for the given function 151 /// type. Returns the interned type index of the trampoline function type. intern_trampoline_type( &mut self, for_func_ty: ModuleInternedTypeIndex, ) -> ModuleInternedTypeIndex152 fn intern_trampoline_type( 153 &mut self, 154 for_func_ty: ModuleInternedTypeIndex, 155 ) -> ModuleInternedTypeIndex { 156 let sub_ty = &self.types[for_func_ty]; 157 let trampoline = sub_ty.unwrap_func().trampoline_type().panic_on_oom(); 158 159 if let Some(idx) = self.trampoline_types.get(&trampoline) { 160 // We've already interned this trampoline type; reuse it. 161 *idx 162 } else { 163 // We have not already interned this trampoline type. 164 match trampoline { 165 // The trampoline type is the same as the original function 166 // type. We can reuse the definition and its index, but still 167 // need to intern the type into our `trampoline_types` map so we 168 // can reuse it in the future. 169 TryCow::Borrowed(f) => { 170 self.trampoline_types 171 .insert(f.clone_panic_on_oom(), for_func_ty); 172 for_func_ty 173 } 174 // The trampoline type is different from the original function 175 // type. Define the trampoline type and then intern it in 176 // `trampoline_types` so we can reuse it in the future. 177 TryCow::Owned(f) => { 178 let idx = self.types.push(WasmSubType { 179 is_final: true, 180 supertype: None, 181 composite_type: WasmCompositeType { 182 inner: WasmCompositeInnerType::Func(f.clone_panic_on_oom()), 183 shared: sub_ty.composite_type.shared, 184 }, 185 }); 186 187 // The trampoline type is its own trampoline type. 188 self.types.set_trampoline_type(idx, idx); 189 190 let next = self.types.next_ty(); 191 self.types.push_rec_group(idx..next); 192 self.trampoline_types.insert(f, idx); 193 idx 194 } 195 } 196 } 197 } 198 199 /// Start defining a recursion group. start_rec_group( &mut self, validator_types: wasmparser::types::TypesRef<'_>, elems: impl ExactSizeIterator<Item = wasmparser::types::CoreTypeId>, )200 fn start_rec_group( 201 &mut self, 202 validator_types: wasmparser::types::TypesRef<'_>, 203 elems: impl ExactSizeIterator<Item = wasmparser::types::CoreTypeId>, 204 ) { 205 log::trace!("Starting rec group of length {}", elems.len()); 206 207 assert!(self.defining_rec_group.is_none()); 208 assert_eq!(validator_types.id(), self.validator_id); 209 210 // Eagerly define the reverse map's entries for this rec group's types 211 // so that we can use them when converting `wasmparser` types to our 212 // types. 213 let len = elems.len(); 214 for (i, wasmparser_id) in elems.enumerate() { 215 let interned = ModuleInternedTypeIndex::new(self.types.len_types() + i); 216 log::trace!( 217 "Reserving {interned:?} for {wasmparser_id:?} = {:?}", 218 validator_types[wasmparser_id] 219 ); 220 221 let old_entry = self.wasmparser_to_wasmtime.insert(wasmparser_id, interned); 222 debug_assert_eq!( 223 old_entry, None, 224 "should not have already inserted {wasmparser_id:?}" 225 ); 226 } 227 228 self.defining_rec_group = Some(RecGroupStart { 229 rec_group_index: self.types.next_rec_group(), 230 start: self.types.next_ty(), 231 end: ModuleInternedTypeIndex::new(self.types.len_types() + len), 232 }); 233 } 234 235 /// Finish defining a recursion group. end_rec_group( &mut self, rec_group_id: wasmparser::types::RecGroupId, ) -> ModuleInternedRecGroupIndex236 fn end_rec_group( 237 &mut self, 238 rec_group_id: wasmparser::types::RecGroupId, 239 ) -> ModuleInternedRecGroupIndex { 240 let RecGroupStart { 241 rec_group_index, 242 start, 243 end, 244 } = self 245 .defining_rec_group 246 .take() 247 .expect("should be defining a rec group"); 248 249 log::trace!("Ending rec group {start:?}..{end:?}"); 250 251 debug_assert!(start.index() < self.types.len_types()); 252 debug_assert_eq!( 253 end, 254 self.types.next_ty(), 255 "should have defined the number of types declared in `start_rec_group`" 256 ); 257 258 let idx = self.types.push_rec_group(start..end); 259 debug_assert_eq!(idx, rec_group_index); 260 261 self.already_seen.insert(rec_group_id, rec_group_index); 262 rec_group_index 263 } 264 265 /// Intern a type into this builder and get its Wasmtime index. 266 /// 267 /// This will intern not only the single given type, but the type's entire 268 /// rec group. This helper method is provided as a convenience so that 269 /// callers don't have to get the type's rec group, intern the rec group, 270 /// and then look up the Wasmtime index for the original type themselves. intern_type( &mut self, validator_types: wasmparser::types::TypesRef<'_>, id: wasmparser::types::CoreTypeId, ) -> WasmResult<ModuleInternedTypeIndex>271 pub fn intern_type( 272 &mut self, 273 validator_types: wasmparser::types::TypesRef<'_>, 274 id: wasmparser::types::CoreTypeId, 275 ) -> WasmResult<ModuleInternedTypeIndex> { 276 assert!(self.defining_rec_group.is_none()); 277 assert_eq!(validator_types.id(), self.validator_id); 278 279 let rec_group_id = validator_types.rec_group_id_of(id); 280 debug_assert!( 281 validator_types 282 .rec_group_elements(rec_group_id) 283 .any(|e| e == id) 284 ); 285 286 let interned_rec_group = self.intern_rec_group(validator_types, rec_group_id)?; 287 288 let interned_type = self.wasmparser_to_wasmtime[&id]; 289 debug_assert!( 290 self.rec_group_elements(interned_rec_group) 291 .any(|e| e == interned_type) 292 ); 293 294 Ok(interned_type) 295 } 296 297 /// Define a new Wasm type while we are defining a rec group. wasm_sub_type_in_rec_group( &mut self, id: wasmparser::types::CoreTypeId, ty: WasmSubType, ) -> ModuleInternedTypeIndex298 fn wasm_sub_type_in_rec_group( 299 &mut self, 300 id: wasmparser::types::CoreTypeId, 301 ty: WasmSubType, 302 ) -> ModuleInternedTypeIndex { 303 assert!( 304 self.defining_rec_group.is_some(), 305 "must be defining a rec group to define new types" 306 ); 307 308 let module_interned_index = self.types.push(ty); 309 debug_assert_eq!( 310 self.wasmparser_to_wasmtime.get(&id), 311 Some(&module_interned_index), 312 "should have reserved the right module-interned index for this wasmparser type already" 313 ); 314 315 module_interned_index 316 } 317 318 /// Define a new exception type when we see a function type used 319 /// in a tag. 320 /// 321 /// The returned `ModuleInternedTypeIndex` gives us a Wasmtime 322 /// type which corresponds to the exception object layout, but 323 /// note that these types do not exist in the Wasm spec: at the 324 /// Wasm level, only function types exist (and tags and exception 325 /// instructions reference them). For implementation reasons, we 326 /// need a separate type to describe the exception object layout, 327 /// and this registers and provides that type. define_exception_type_for_tag( &mut self, for_func_ty: ModuleInternedTypeIndex, ) -> ModuleInternedTypeIndex328 pub fn define_exception_type_for_tag( 329 &mut self, 330 for_func_ty: ModuleInternedTypeIndex, 331 ) -> ModuleInternedTypeIndex { 332 match self.exception_types.entry(for_func_ty) { 333 Entry::Occupied(o) => *o.get(), 334 Entry::Vacant(v) => { 335 let fields = self.types[for_func_ty] 336 .unwrap_func() 337 .params() 338 .iter() 339 .map(|valtype| WasmFieldType { 340 element_type: WasmStorageType::Val(*valtype), 341 mutable: false, 342 }) 343 .collect(); 344 let idx = self.types.push(WasmSubType { 345 is_final: true, 346 supertype: None, 347 composite_type: WasmCompositeType { 348 inner: WasmCompositeInnerType::Exn(WasmExnType { 349 func_ty: EngineOrModuleTypeIndex::Module(for_func_ty), 350 fields, 351 }), 352 shared: false, 353 }, 354 }); 355 let next = self.types.next_ty(); 356 self.types.push_rec_group(idx..next); 357 *v.insert(idx) 358 } 359 } 360 } 361 362 /// Returns the result [`ModuleTypes`] of this builder. finish(self) -> ModuleTypes363 pub fn finish(self) -> ModuleTypes { 364 self.types 365 } 366 367 /// Get the elements within an already-defined rec group. rec_group_elements( &self, rec_group: ModuleInternedRecGroupIndex, ) -> impl ExactSizeIterator<Item = ModuleInternedTypeIndex> + use<>368 pub fn rec_group_elements( 369 &self, 370 rec_group: ModuleInternedRecGroupIndex, 371 ) -> impl ExactSizeIterator<Item = ModuleInternedTypeIndex> + use<> { 372 self.types.rec_group_elements(rec_group) 373 } 374 375 /// Returns an iterator over all the unique wasm types defined thus far 376 /// within this builder. wasm_types(&self) -> impl Iterator<Item = (ModuleInternedTypeIndex, &WasmSubType)>377 pub fn wasm_types(&self) -> impl Iterator<Item = (ModuleInternedTypeIndex, &WasmSubType)> { 378 self.types.wasm_types() 379 } 380 381 /// Get an iterator over all function types and their associated trampoline 382 /// type. trampoline_types( &self, ) -> impl Iterator<Item = (ModuleInternedTypeIndex, ModuleInternedTypeIndex)> + '_383 pub fn trampoline_types( 384 &self, 385 ) -> impl Iterator<Item = (ModuleInternedTypeIndex, ModuleInternedTypeIndex)> + '_ { 386 self.types.trampoline_types() 387 } 388 389 /// Get the associated trampoline type for the given function type. trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex390 pub fn trampoline_type(&self, ty: ModuleInternedTypeIndex) -> ModuleInternedTypeIndex { 391 self.types.trampoline_type(ty) 392 } 393 394 /// Get and unwrap a [`WasmStructType`] for the given struct index. 395 /// 396 /// # Panics 397 /// 398 /// Panics if the unwrapped type is not a struct. 399 /// 400 /// # Errors 401 /// 402 /// For now, fails with an unsupported error if the type is shared. unwrap_struct(&self, ty: ModuleInternedTypeIndex) -> WasmResult<&WasmStructType>403 pub fn unwrap_struct(&self, ty: ModuleInternedTypeIndex) -> WasmResult<&WasmStructType> { 404 let composite_type = &self.types[ty].composite_type; 405 if composite_type.shared { 406 return Err(wasm_unsupported!("shared structs are not yet implemented")); 407 } 408 Ok(composite_type.inner.unwrap_struct()) 409 } 410 411 /// Get and unwrap a [`WasmArrayType`] for the given array index. 412 /// 413 /// # Panics 414 /// 415 /// Panics if the unwrapped type is not an array. 416 /// 417 /// # Errors 418 /// 419 /// For now, fails with an unsupported error if the type is shared. unwrap_array(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmArrayType>420 pub fn unwrap_array(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmArrayType> { 421 let composite_type = &self.types[interned_ty].composite_type; 422 if composite_type.shared { 423 return Err(wasm_unsupported!("shared arrays are not yet implemented")); 424 } 425 Ok(composite_type.inner.unwrap_array()) 426 } 427 428 /// Get and unwrap a [`WasmExnType`] for the given exception-type index. 429 /// 430 /// # Panics 431 /// 432 /// Panics if the unwrapped type is not an exception type. 433 /// 434 /// # Errors 435 /// 436 /// For now, fails with an unsupported error if the type is shared. unwrap_exn(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmExnType>437 pub fn unwrap_exn(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmExnType> { 438 let composite_type = &self.types[interned_ty].composite_type; 439 if composite_type.shared { 440 return Err(wasm_unsupported!( 441 "shared exceptions are not yet implemented" 442 )); 443 } 444 Ok(composite_type.inner.unwrap_exn()) 445 } 446 447 /// Get and unwrap a [`WasmFuncType`] for the given function-type index. 448 /// 449 /// # Panics 450 /// 451 /// Panics if the unwrapped type is not a function type. 452 /// 453 /// # Errors 454 /// 455 /// For now, fails with an unsupported error if the type is shared. unwrap_func(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmFuncType>456 pub fn unwrap_func(&self, interned_ty: ModuleInternedTypeIndex) -> WasmResult<&WasmFuncType> { 457 let composite_type = &self.types[interned_ty].composite_type; 458 if composite_type.shared { 459 return Err(wasm_unsupported!( 460 "shared functions are not yet implemented" 461 )); 462 } 463 Ok(composite_type.inner.unwrap_func()) 464 } 465 } 466 467 // Forward the indexing impl to the internal `ModuleTypes` 468 impl<T> Index<T> for ModuleTypesBuilder 469 where 470 ModuleTypes: Index<T>, 471 { 472 type Output = <ModuleTypes as Index<T>>::Output; 473 index(&self, sig: T) -> &Self::Output474 fn index(&self, sig: T) -> &Self::Output { 475 &self.types[sig] 476 } 477 } 478 479 /// A convert from `wasmparser` types to Wasmtime types. 480 pub struct WasmparserTypeConverter<'a, F> { 481 types: &'a ModuleTypesBuilder, 482 lookup_type_idx: F, 483 rec_group_context: Option<( 484 wasmparser::types::TypesRef<'a>, 485 wasmparser::types::RecGroupId, 486 )>, 487 } 488 489 impl<'a, F> WasmparserTypeConverter<'a, F> { 490 /// Construct a new type converter from `wasmparser` types to Wasmtime types. new(types: &'a ModuleTypesBuilder, lookup_type_idx: F) -> Self491 pub fn new(types: &'a ModuleTypesBuilder, lookup_type_idx: F) -> Self { 492 Self { 493 types, 494 lookup_type_idx, 495 rec_group_context: None, 496 } 497 } 498 499 /// Configure this converter to be within the context of defining the 500 /// current rec group. with_rec_group( &mut self, wasmparser_types: wasmparser::types::TypesRef<'a>, rec_group: wasmparser::types::RecGroupId, ) -> &Self501 pub fn with_rec_group( 502 &mut self, 503 wasmparser_types: wasmparser::types::TypesRef<'a>, 504 rec_group: wasmparser::types::RecGroupId, 505 ) -> &Self { 506 self.rec_group_context = Some((wasmparser_types, rec_group)); 507 self 508 } 509 } 510 511 impl<F> TypeConvert for WasmparserTypeConverter<'_, F> 512 where 513 F: Fn(TypeIndex) -> ModuleInternedTypeIndex, 514 { lookup_heap_type(&self, index: UnpackedIndex) -> WasmHeapType515 fn lookup_heap_type(&self, index: UnpackedIndex) -> WasmHeapType { 516 match index { 517 UnpackedIndex::Id(id) => { 518 let interned = self.types.wasmparser_to_wasmtime[&id]; 519 let index = EngineOrModuleTypeIndex::Module(interned); 520 521 // If this is a forward reference to a type in this type's rec 522 // group that we haven't converted yet, then we won't have an 523 // entry in `wasm_types` yet. In this case, fallback to a 524 // different means of determining whether this is a concrete 525 // array vs struct vs func reference. In this case, we can use 526 // the validator's type context. 527 if let Some(ty) = self.types.types.get(interned) { 528 assert!(!ty.composite_type.shared); 529 match &ty.composite_type.inner { 530 WasmCompositeInnerType::Array(_) => WasmHeapType::ConcreteArray(index), 531 WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index), 532 WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index), 533 WasmCompositeInnerType::Cont(_) => WasmHeapType::ConcreteCont(index), 534 WasmCompositeInnerType::Exn(_) => WasmHeapType::ConcreteExn(index), 535 } 536 } else if let Some((wasmparser_types, _)) = self.rec_group_context.as_ref() { 537 let wasmparser_ty = &wasmparser_types[id].composite_type; 538 assert!(!wasmparser_ty.shared); 539 match &wasmparser_ty.inner { 540 wasmparser::CompositeInnerType::Array(_) => { 541 WasmHeapType::ConcreteArray(index) 542 } 543 wasmparser::CompositeInnerType::Func(_) => { 544 WasmHeapType::ConcreteFunc(index) 545 } 546 wasmparser::CompositeInnerType::Struct(_) => { 547 WasmHeapType::ConcreteStruct(index) 548 } 549 wasmparser::CompositeInnerType::Cont(_) => { 550 WasmHeapType::ConcreteCont(index) 551 } 552 } 553 } else { 554 panic!("forward reference to type outside of rec group?") 555 } 556 } 557 558 UnpackedIndex::Module(module_index) => { 559 let module_index = TypeIndex::from_u32(module_index); 560 let interned = (self.lookup_type_idx)(module_index); 561 let index = EngineOrModuleTypeIndex::Module(interned); 562 563 // See comment above about `wasm_types` maybe not having the 564 // converted sub type yet. However in this case we don't have a 565 // `wasmparser::types::CoreTypeId` on hand, so we have to 566 // indirectly get one by looking it up inside the current rec 567 // group. 568 if let Some(ty) = self.types.types.get(interned) { 569 assert!(!ty.composite_type.shared); 570 match &ty.composite_type.inner { 571 WasmCompositeInnerType::Array(_) => WasmHeapType::ConcreteArray(index), 572 WasmCompositeInnerType::Func(_) => WasmHeapType::ConcreteFunc(index), 573 WasmCompositeInnerType::Struct(_) => WasmHeapType::ConcreteStruct(index), 574 WasmCompositeInnerType::Cont(_) => WasmHeapType::ConcreteCont(index), 575 WasmCompositeInnerType::Exn(_) => WasmHeapType::ConcreteExn(index), 576 } 577 } else if let Some((parser_types, rec_group)) = self.rec_group_context.as_ref() { 578 let rec_group_index = interned.index() - self.types.types.len_types(); 579 let id = parser_types 580 .rec_group_elements(*rec_group) 581 .nth(rec_group_index) 582 .unwrap(); 583 let wasmparser_ty = &parser_types[id].composite_type; 584 assert!(!wasmparser_ty.shared); 585 match &wasmparser_ty.inner { 586 wasmparser::CompositeInnerType::Array(_) => { 587 WasmHeapType::ConcreteArray(index) 588 } 589 wasmparser::CompositeInnerType::Func(_) => { 590 WasmHeapType::ConcreteFunc(index) 591 } 592 wasmparser::CompositeInnerType::Struct(_) => { 593 WasmHeapType::ConcreteStruct(index) 594 } 595 wasmparser::CompositeInnerType::Cont(_) => { 596 WasmHeapType::ConcreteCont(index) 597 } 598 } 599 } else { 600 panic!("forward reference to type outside of rec group?") 601 } 602 } 603 604 UnpackedIndex::RecGroup(_) => unreachable!(), 605 } 606 } 607 lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex608 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex { 609 match index { 610 UnpackedIndex::Id(id) => { 611 let interned = self.types.wasmparser_to_wasmtime[&id]; 612 EngineOrModuleTypeIndex::Module(interned) 613 } 614 UnpackedIndex::Module(module_index) => { 615 let module_index = TypeIndex::from_u32(module_index); 616 let interned = (self.lookup_type_idx)(module_index); 617 EngineOrModuleTypeIndex::Module(interned) 618 } 619 UnpackedIndex::RecGroup(_) => unreachable!(), 620 } 621 } 622 } 623