1use crate::PanicOnOom as _;
2use crate::component::*;
3use crate::error::{Result, bail};
4use crate::prelude::*;
5use crate::{
6 EngineOrModuleTypeIndex, EntityType, ModuleInternedTypeIndex, ModuleTypes, ModuleTypesBuilder,
7 PrimaryMap, TypeConvert, TypeIndex, WasmHeapType, WasmparserTypeConverter,
8};
9use cranelift_entity::EntityRef;
10use std::collections::HashMap;
11use std::hash::Hash;
12use std::ops::Index;
13use wasmparser::component_types::{
14 ComponentAnyTypeId, ComponentCoreModuleTypeId, ComponentDefinedType, ComponentDefinedTypeId,
15 ComponentEntityType, ComponentFuncTypeId, ComponentInstanceTypeId, ComponentTypeId,
16 ComponentValType, RecordType, ResourceId, TupleType, VariantType,
17};
18use wasmparser::names::KebabString;
19use wasmparser::types::TypesRef;
20use wasmparser::{PrimitiveValType, Validator};
21use wasmtime_component_util::FlagsSize;
22
23mod resources;
24pub use resources::ResourcesBuilder;
25
26pub struct ComponentTypesBuilder {
31 functions: HashMap<TypeFunc, TypeFuncIndex>,
32 lists: HashMap<TypeList, TypeListIndex>,
33 maps: HashMap<TypeMap, TypeMapIndex>,
34 records: HashMap<TypeRecord, TypeRecordIndex>,
35 variants: HashMap<TypeVariant, TypeVariantIndex>,
36 tuples: HashMap<TypeTuple, TypeTupleIndex>,
37 enums: HashMap<TypeEnum, TypeEnumIndex>,
38 flags: HashMap<TypeFlags, TypeFlagsIndex>,
39 options: HashMap<TypeOption, TypeOptionIndex>,
40 results: HashMap<TypeResult, TypeResultIndex>,
41 futures: HashMap<TypeFuture, TypeFutureIndex>,
42 streams: HashMap<TypeStream, TypeStreamIndex>,
43 future_tables: HashMap<TypeFutureTable, TypeFutureTableIndex>,
44 stream_tables: HashMap<TypeStreamTable, TypeStreamTableIndex>,
45 error_context_tables: HashMap<TypeErrorContextTable, TypeComponentLocalErrorContextTableIndex>,
46 fixed_length_lists: HashMap<TypeFixedLengthList, TypeFixedLengthListIndex>,
47
48 component_types: ComponentTypes,
49 module_types: ModuleTypesBuilder,
50
51 type_info: TypeInformationCache,
55
56 resources: ResourcesBuilder,
57
58 abstract_resources: u32,
63}
64
65impl<T> Index<T> for ComponentTypesBuilder
66where
67 ModuleTypes: Index<T>,
68{
69 type Output = <ModuleTypes as Index<T>>::Output;
70 fn index(&self, idx: T) -> &Self::Output {
71 self.module_types.index(idx)
72 }
73}
74
75macro_rules! intern_and_fill_flat_types {
76 ($me:ident, $name:ident, $val:ident) => {{
77 if let Some(idx) = $me.$name.get(&$val) {
78 *idx
79 } else {
80 let idx = $me
81 .component_types
82 .$name
83 .push($val.clone_panic_on_oom())
84 .panic_on_oom();
85 let mut info = TypeInformation::new();
86 info.$name($me, &$val);
87 let idx2 = $me.type_info.$name.push(info);
88 assert_eq!(idx, idx2);
89 $me.$name.insert($val, idx);
90 idx
91 }
92 }};
93}
94
95impl ComponentTypesBuilder {
96 pub fn new(validator: &Validator) -> Self {
98 Self {
99 module_types: ModuleTypesBuilder::new(validator),
100
101 functions: HashMap::default(),
102 lists: HashMap::default(),
103 maps: HashMap::default(),
104 records: HashMap::default(),
105 variants: HashMap::default(),
106 tuples: HashMap::default(),
107 enums: HashMap::default(),
108 flags: HashMap::default(),
109 options: HashMap::default(),
110 results: HashMap::default(),
111 futures: HashMap::default(),
112 streams: HashMap::default(),
113 future_tables: HashMap::default(),
114 stream_tables: HashMap::default(),
115 error_context_tables: HashMap::default(),
116 component_types: ComponentTypes::default(),
117 type_info: TypeInformationCache::default(),
118 resources: ResourcesBuilder::default(),
119 abstract_resources: 0,
120 fixed_length_lists: HashMap::default(),
121 }
122 }
123
124 fn export_type_def(
125 &mut self,
126 export_items: &TryPrimaryMap<ExportIndex, Export>,
127 idx: ExportIndex,
128 ) -> TypeDef {
129 match &export_items[idx] {
130 Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(*ty),
131 Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
132 TypeDef::Module(*ty)
133 }
134 Export::Instance { ty, .. } => TypeDef::ComponentInstance(*ty),
135 Export::Type(ty) => *ty,
136 }
137 }
138
139 pub fn finish(mut self, component: &Component) -> (ComponentTypes, TypeComponentIndex) {
143 let mut component_ty = TypeComponent::default();
144 for (_, (name, ty)) in component.import_types.iter() {
145 component_ty
146 .imports
147 .insert(name.clone_panic_on_oom(), ty.clone_panic_on_oom())
148 .panic_on_oom();
149 }
150 for (name, (ty, data)) in component.exports.raw_iter() {
151 component_ty
152 .exports
153 .insert(
154 name.clone_panic_on_oom(),
155 ComponentExtern {
156 data: data.clone_panic_on_oom(),
157 ty: self.export_type_def(&component.export_items, *ty),
158 },
159 )
160 .panic_on_oom();
161 }
162 let ty = self
163 .component_types
164 .components
165 .push(component_ty)
166 .panic_on_oom();
167
168 self.component_types.module_types = Some(self.module_types.finish());
169 (self.component_types, ty)
170 }
171
172 pub fn module_types_builder(&self) -> &ModuleTypesBuilder {
177 &self.module_types
178 }
179
180 pub fn module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder {
182 &mut self.module_types
183 }
184
185 pub(super) fn component_types(&self) -> &ComponentTypes {
187 &self.component_types
188 }
189
190 pub fn num_resource_tables(&self) -> usize {
193 self.component_types.resource_tables.len()
194 }
195
196 pub fn resource_owned_by_own_instance(
198 &self,
199 ty: TypeResourceTableIndex,
200 defined_resource_instance: impl FnOnce(ResourceIndex) -> Option<RuntimeComponentInstanceIndex>,
201 ) -> bool {
202 self.component_types
203 .resource_owned_by_own_instance(ty, defined_resource_instance)
204 }
205
206 pub fn num_future_tables(&self) -> usize {
209 self.component_types.future_tables.len()
210 }
211
212 pub fn num_stream_tables(&self) -> usize {
215 self.component_types.stream_tables.len()
216 }
217
218 pub fn num_error_context_tables(&self) -> usize {
221 self.component_types.error_context_tables.len()
222 }
223
224 pub fn resources_mut(&mut self) -> &mut ResourcesBuilder {
226 &mut self.resources
227 }
228
229 pub fn resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes) {
232 (&mut self.resources, &self.component_types)
233 }
234
235 pub fn convert_component_func_type(
238 &mut self,
239 types: TypesRef<'_>,
240 id: ComponentFuncTypeId,
241 ) -> Result<TypeFuncIndex> {
242 assert_eq!(types.id(), self.module_types.validator_id());
243 let ty = &types[id];
244 let param_names = ty
245 .params
246 .iter()
247 .map(|(name, _)| TryString::try_from(name.as_str()))
248 .try_collect::<TryVec<_>, _>()?;
249 let params = ty
250 .params
251 .iter()
252 .map(|(_name, ty)| self.valtype(types, ty))
253 .collect::<Result<_>>()?;
254 let results = ty
255 .result
256 .iter()
257 .map(|ty| self.valtype(types, ty))
258 .collect::<Result<_>>()?;
259 let params = self.new_tuple_type(params);
260 let results = self.new_tuple_type(results);
261 let ty = TypeFunc {
262 async_: ty.async_,
263 param_names,
264 params,
265 results,
266 };
267 Ok(self.add_func_type(ty))
268 }
269
270 pub fn convert_component_item(
273 &mut self,
274 types: TypesRef<'_>,
275 ty: &wasmparser::component_types::ComponentItem,
276 ) -> Result<ComponentExtern> {
277 Ok(ComponentExtern {
278 ty: self.convert_component_entity_type(types, ty.ty)?,
279 data: ComponentExternData {
280 implements: ty.implements.clone().map(Into::into),
281 external_id: ty.external_id.clone().map(Into::into),
282 },
283 })
284 }
285
286 pub fn convert_component_entity_type(
289 &mut self,
290 types: TypesRef<'_>,
291 ty: ComponentEntityType,
292 ) -> Result<TypeDef> {
293 assert_eq!(types.id(), self.module_types.validator_id());
294 Ok(match ty {
295 ComponentEntityType::Module(id) => TypeDef::Module(self.convert_module(types, id)?),
296 ComponentEntityType::Component(id) => {
297 TypeDef::Component(self.convert_component(types, id)?)
298 }
299 ComponentEntityType::Instance(id) => {
300 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
301 }
302 ComponentEntityType::Func(id) => {
303 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
304 }
305 ComponentEntityType::Type { created, .. } => match created {
306 ComponentAnyTypeId::Defined(id) => {
307 TypeDef::Interface(self.defined_type(types, id)?)
308 }
309 ComponentAnyTypeId::Resource(id) => {
310 TypeDef::Resource(self.resource_id(id.resource()))
311 }
312 _ => bail!("unsupported type export"),
313 },
314 ComponentEntityType::Value(_) => bail!("values not supported"),
315 })
316 }
317
318 pub fn convert_type(&mut self, types: TypesRef<'_>, id: ComponentAnyTypeId) -> Result<TypeDef> {
320 assert_eq!(types.id(), self.module_types.validator_id());
321 Ok(match id {
322 ComponentAnyTypeId::Defined(id) => TypeDef::Interface(self.defined_type(types, id)?),
323 ComponentAnyTypeId::Component(id) => {
324 TypeDef::Component(self.convert_component(types, id)?)
325 }
326 ComponentAnyTypeId::Instance(id) => {
327 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
328 }
329 ComponentAnyTypeId::Func(id) => {
330 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
331 }
332 ComponentAnyTypeId::Resource(id) => TypeDef::Resource(self.resource_id(id.resource())),
333 })
334 }
335
336 fn convert_component(
337 &mut self,
338 types: TypesRef<'_>,
339 id: ComponentTypeId,
340 ) -> Result<TypeComponentIndex> {
341 assert_eq!(types.id(), self.module_types.validator_id());
342 let ty = &types[id];
343 let mut result = TypeComponent::default();
344 for (name, ty) in ty.imports.iter() {
345 self.register_abstract_component_entity_type(types, ty.ty);
346 result
347 .imports
348 .insert(name.clone().into(), self.convert_component_item(types, ty)?)?;
349 }
350 for (name, ty) in ty.exports.iter() {
351 self.register_abstract_component_entity_type(types, ty.ty);
352 result
353 .exports
354 .insert(name.clone().into(), self.convert_component_item(types, ty)?)?;
355 }
356 Ok(self.component_types.components.push(result)?)
357 }
358
359 pub(crate) fn convert_instance(
360 &mut self,
361 types: TypesRef<'_>,
362 id: ComponentInstanceTypeId,
363 ) -> Result<TypeComponentInstanceIndex> {
364 assert_eq!(types.id(), self.module_types.validator_id());
365 let ty = &types[id];
366 let mut result = TypeComponentInstance::default();
367 for (name, ty) in ty.exports.iter() {
368 self.register_abstract_component_entity_type(types, ty.ty);
369 result
370 .exports
371 .insert(name.clone().into(), self.convert_component_item(types, ty)?)?;
372 }
373 Ok(self.component_types.component_instances.push(result)?)
374 }
375
376 fn register_abstract_component_entity_type(
377 &mut self,
378 types: TypesRef<'_>,
379 ty: ComponentEntityType,
380 ) {
381 let mut path = Vec::new();
382 self.resources.register_abstract_component_entity_type(
383 &types,
384 ty,
385 &mut path,
386 &mut |_path| {
387 self.abstract_resources += 1;
388 AbstractResourceIndex::from_u32(self.abstract_resources)
389 },
390 );
391 }
392
393 pub(crate) fn convert_module(
394 &mut self,
395 types: TypesRef<'_>,
396 id: ComponentCoreModuleTypeId,
397 ) -> Result<TypeModuleIndex> {
398 assert_eq!(types.id(), self.module_types.validator_id());
399 let ty = &types[id];
400
401 for id in ty.types.iter() {
404 self.module_types_builder_mut().intern_type(types, *id)?;
405 }
406
407 let mut result = TypeModule::default();
408 for ((module, field), ty) in ty.imports.iter() {
409 result.imports.insert(
410 (module.clone().into(), field.clone().into()),
411 self.entity_type(types, ty)?,
412 )?;
413 }
414 for (name, ty) in ty.exports.iter() {
415 result
416 .exports
417 .insert(name.clone().into(), self.entity_type(types, ty)?)?;
418 }
419 Ok(self.component_types.modules.push(result)?)
420 }
421
422 fn entity_type(
423 &mut self,
424 types: TypesRef<'_>,
425 ty: &wasmparser::types::EntityType,
426 ) -> Result<EntityType> {
427 use wasmparser::types::EntityType::*;
428
429 assert_eq!(types.id(), self.module_types.validator_id());
430 Ok(match ty {
431 Func(id) => EntityType::Function({
432 self.module_types_builder_mut()
433 .intern_type(types, *id)?
434 .into()
435 }),
436 Table(ty) => EntityType::Table(self.convert_table_type(ty)?),
437 Memory(ty) => EntityType::Memory((*ty).into()),
438 Global(ty) => EntityType::Global(self.convert_global_type(ty)?),
439 Tag(id) => {
440 let func = self.module_types_builder_mut().intern_type(types, *id)?;
441 let exc = self
442 .module_types_builder_mut()
443 .define_exception_type_for_tag(func);
444 EntityType::Tag(crate::types::Tag {
445 signature: func.into(),
446 exception: exc.into(),
447 })
448 }
449 FuncExact(_) => bail!("custom-descriptors proposal not implemented"),
450 })
451 }
452
453 pub fn defined_type(
455 &mut self,
456 types: TypesRef<'_>,
457 id: ComponentDefinedTypeId,
458 ) -> Result<InterfaceType> {
459 assert_eq!(types.id(), self.module_types.validator_id());
460 Ok(match &types[id] {
461 ComponentDefinedType::Primitive(ty) => self.primitive_type(ty)?,
462 ComponentDefinedType::Record(e) => InterfaceType::Record(self.record_type(types, e)?),
463 ComponentDefinedType::Variant(e) => {
464 InterfaceType::Variant(self.variant_type(types, e)?)
465 }
466 ComponentDefinedType::List { element, .. } => {
467 InterfaceType::List(self.list_type(types, element)?)
468 }
469 ComponentDefinedType::Map { key, value, .. } => {
470 InterfaceType::Map(self.map_type(types, key, value)?)
471 }
472 ComponentDefinedType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(types, e)?),
473 ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
474 ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
475 ComponentDefinedType::Option { ty, .. } => {
476 InterfaceType::Option(self.option_type(types, ty)?)
477 }
478 ComponentDefinedType::Result { ok, err, .. } => {
479 InterfaceType::Result(self.result_type(types, ok, err)?)
480 }
481 ComponentDefinedType::Own(r) => InterfaceType::Own(self.resource_id(r.resource())),
482 ComponentDefinedType::Borrow(r) => {
483 InterfaceType::Borrow(self.resource_id(r.resource()))
484 }
485 ComponentDefinedType::Future { ty, .. } => {
486 InterfaceType::Future(self.future_table_type(types, ty)?)
487 }
488 ComponentDefinedType::Stream { ty, .. } => {
489 InterfaceType::Stream(self.stream_table_type(types, ty)?)
490 }
491 ComponentDefinedType::FixedLengthList {
492 element, length, ..
493 } => InterfaceType::FixedLengthList(
494 self.fixed_length_list_type(types, element, *length)?,
495 ),
496 })
497 }
498
499 pub fn error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
501 self.error_context_table_type()
502 }
503
504 pub(crate) fn valtype(
505 &mut self,
506 types: TypesRef<'_>,
507 ty: &ComponentValType,
508 ) -> Result<InterfaceType> {
509 assert_eq!(types.id(), self.module_types.validator_id());
510 match ty {
511 ComponentValType::Primitive(p) => self.primitive_type(p),
512 ComponentValType::Type(id) => self.defined_type(types, *id),
513 }
514 }
515
516 fn primitive_type(&mut self, ty: &PrimitiveValType) -> Result<InterfaceType> {
517 match ty {
518 wasmparser::PrimitiveValType::Bool => Ok(InterfaceType::Bool),
519 wasmparser::PrimitiveValType::S8 => Ok(InterfaceType::S8),
520 wasmparser::PrimitiveValType::U8 => Ok(InterfaceType::U8),
521 wasmparser::PrimitiveValType::S16 => Ok(InterfaceType::S16),
522 wasmparser::PrimitiveValType::U16 => Ok(InterfaceType::U16),
523 wasmparser::PrimitiveValType::S32 => Ok(InterfaceType::S32),
524 wasmparser::PrimitiveValType::U32 => Ok(InterfaceType::U32),
525 wasmparser::PrimitiveValType::S64 => Ok(InterfaceType::S64),
526 wasmparser::PrimitiveValType::U64 => Ok(InterfaceType::U64),
527 wasmparser::PrimitiveValType::F32 => Ok(InterfaceType::Float32),
528 wasmparser::PrimitiveValType::F64 => Ok(InterfaceType::Float64),
529 wasmparser::PrimitiveValType::Char => Ok(InterfaceType::Char),
530 wasmparser::PrimitiveValType::String => Ok(InterfaceType::String),
531 wasmparser::PrimitiveValType::ErrorContext => Ok(InterfaceType::ErrorContext(
532 self.error_context_table_type()?,
533 )),
534 }
535 }
536
537 fn record_type(&mut self, types: TypesRef<'_>, ty: &RecordType) -> Result<TypeRecordIndex> {
538 assert_eq!(types.id(), self.module_types.validator_id());
539 let fields = ty
540 .fields
541 .iter()
542 .map(|(name, ty)| {
543 Ok(RecordField {
544 name: TryString::try_from(name.as_str())?,
545 ty: self.valtype(types, ty)?,
546 })
547 })
548 .try_collect::<TryVec<_>, Error>()?;
549 let abi = CanonicalAbiInfo::record(
550 fields
551 .iter()
552 .map(|field| self.component_types.canonical_abi(&field.ty)),
553 );
554 Ok(self.add_record_type(TypeRecord { fields, abi }))
555 }
556
557 fn variant_type(&mut self, types: TypesRef<'_>, ty: &VariantType) -> Result<TypeVariantIndex> {
558 assert_eq!(types.id(), self.module_types.validator_id());
559 let cases = ty
560 .cases
561 .iter()
562 .map(|(name, case)| {
563 Ok((
564 TryString::try_from(name.as_str())?,
565 match &case.ty.as_ref() {
566 Some(ty) => Some(self.valtype(types, ty)?),
567 None => None,
568 },
569 ))
570 })
571 .try_collect::<TryIndexMap<_, _>, Error>()?;
572 let (info, abi) = VariantInfo::new(
573 cases
574 .iter()
575 .map(|(_, c)| c.as_ref().map(|ty| self.component_types.canonical_abi(ty))),
576 );
577 Ok(self.add_variant_type(TypeVariant { cases, abi, info }))
578 }
579
580 fn tuple_type(&mut self, types: TypesRef<'_>, ty: &TupleType) -> Result<TypeTupleIndex> {
581 assert_eq!(types.id(), self.module_types.validator_id());
582 let types = ty
583 .types
584 .iter()
585 .map(|ty| self.valtype(types, ty))
586 .collect::<Result<Box<[_]>>>()?;
587 Ok(self.new_tuple_type(types))
588 }
589
590 pub(crate) fn new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex {
591 let abi = CanonicalAbiInfo::record(
592 types
593 .iter()
594 .map(|ty| self.component_types.canonical_abi(ty)),
595 );
596 self.add_tuple_type(TypeTuple {
597 types: types.into(),
598 abi,
599 })
600 }
601
602 fn fixed_length_list_type(
603 &mut self,
604 types: TypesRef<'_>,
605 ty: &ComponentValType,
606 size: u32,
607 ) -> Result<TypeFixedLengthListIndex> {
608 assert_eq!(types.id(), self.module_types.validator_id());
609 let element = self.valtype(types, ty)?;
610 Ok(self.new_fixed_length_list_type(element, size))
611 }
612
613 pub(crate) fn new_fixed_length_list_type(
614 &mut self,
615 element: InterfaceType,
616 size: u32,
617 ) -> TypeFixedLengthListIndex {
618 let element_abi = self.component_types.canonical_abi(&element);
619 let abi = CanonicalAbiInfo::fixed_length_list_static(
620 element_abi,
621 size.try_into().expect("size should fit into usize"),
622 );
623 self.add_fixed_length_list_type(TypeFixedLengthList { element, size, abi })
624 }
625
626 fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
627 let flags = TypeFlags {
628 names: flags
629 .iter()
630 .map(|s| TryString::try_from(s.as_str()))
631 .try_collect::<TryIndexSet<_>, _>()
632 .panic_on_oom(),
633 abi: CanonicalAbiInfo::flags(flags.len()),
634 };
635 self.add_flags_type(flags)
636 }
637
638 fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
639 let names = variants
640 .iter()
641 .map(|s| TryString::try_from(s.as_str()))
642 .try_collect::<TryIndexSet<_>, _>()
643 .panic_on_oom();
644 let (info, abi) = VariantInfo::new(names.iter().map(|_| None));
645 self.add_enum_type(TypeEnum { names, abi, info })
646 }
647
648 fn option_type(
649 &mut self,
650 types: TypesRef<'_>,
651 ty: &ComponentValType,
652 ) -> Result<TypeOptionIndex> {
653 assert_eq!(types.id(), self.module_types.validator_id());
654 let ty = self.valtype(types, ty)?;
655 let (info, abi) = VariantInfo::new([None, Some(self.component_types.canonical_abi(&ty))]);
656 Ok(self.add_option_type(TypeOption { ty, abi, info }))
657 }
658
659 fn result_type(
660 &mut self,
661 types: TypesRef<'_>,
662 ok: &Option<ComponentValType>,
663 err: &Option<ComponentValType>,
664 ) -> Result<TypeResultIndex> {
665 assert_eq!(types.id(), self.module_types.validator_id());
666 let ok = match ok {
667 Some(ty) => Some(self.valtype(types, ty)?),
668 None => None,
669 };
670 let err = match err {
671 Some(ty) => Some(self.valtype(types, ty)?),
672 None => None,
673 };
674 let (info, abi) = VariantInfo::new([
675 ok.as_ref().map(|t| self.component_types.canonical_abi(t)),
676 err.as_ref().map(|t| self.component_types.canonical_abi(t)),
677 ]);
678 Ok(self.add_result_type(TypeResult { ok, err, abi, info }))
679 }
680
681 fn future_table_type(
682 &mut self,
683 types: TypesRef<'_>,
684 ty: &Option<ComponentValType>,
685 ) -> Result<TypeFutureTableIndex> {
686 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
687 let ty = self.add_future_type(TypeFuture { payload });
688 Ok(self.add_future_table_type(TypeFutureTable {
689 ty,
690 instance: self.resources.get_current_instance().unwrap(),
691 }))
692 }
693
694 fn stream_table_type(
695 &mut self,
696 types: TypesRef<'_>,
697 ty: &Option<ComponentValType>,
698 ) -> Result<TypeStreamTableIndex> {
699 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
700 let ty = self.add_stream_type(TypeStream { payload });
701 Ok(self.add_stream_table_type(TypeStreamTable {
702 ty,
703 instance: self.resources.get_current_instance().unwrap(),
704 }))
705 }
706
707 pub fn error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
710 Ok(self.add_error_context_table_type(TypeErrorContextTable {
711 instance: self.resources.get_current_instance().unwrap(),
712 }))
713 }
714
715 fn list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<TypeListIndex> {
716 assert_eq!(types.id(), self.module_types.validator_id());
717 let element = self.valtype(types, ty)?;
718 Ok(self.add_list_type(TypeList { element }))
719 }
720
721 fn map_type(
722 &mut self,
723 types: TypesRef<'_>,
724 key: &ComponentValType,
725 value: &ComponentValType,
726 ) -> Result<TypeMapIndex> {
727 assert_eq!(types.id(), self.module_types.validator_id());
728 let key_ty = self.valtype(types, key)?;
729 let value_ty = self.valtype(types, value)?;
730 let key_abi = self.component_types.canonical_abi(&key_ty);
731 let value_abi = self.component_types.canonical_abi(&value_ty);
732 let entry_abi = CanonicalAbiInfo::record([key_abi, value_abi].into_iter());
733
734 let mut offset32 = 0;
735 key_abi.next_field32(&mut offset32);
736 let value_offset32 = value_abi.next_field32(&mut offset32);
737
738 let mut offset64 = 0;
739 key_abi.next_field64(&mut offset64);
740 let value_offset64 = value_abi.next_field64(&mut offset64);
741
742 Ok(self.add_map_type(TypeMap {
743 key: key_ty,
744 value: value_ty,
745 entry_abi,
746 value_offset32,
747 value_offset64,
748 }))
749 }
750
751 pub fn resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex {
754 self.resources.convert(id, &mut self.component_types)
755 }
756
757 pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
759 intern(&mut self.functions, &mut self.component_types.functions, ty)
760 }
761
762 pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
764 intern_and_fill_flat_types!(self, records, ty)
765 }
766
767 pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
769 intern_and_fill_flat_types!(self, flags, ty)
770 }
771
772 pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
774 intern_and_fill_flat_types!(self, tuples, ty)
775 }
776
777 pub fn add_fixed_length_list_type(
779 &mut self,
780 ty: TypeFixedLengthList,
781 ) -> TypeFixedLengthListIndex {
782 intern_and_fill_flat_types!(self, fixed_length_lists, ty)
783 }
784
785 pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
787 intern_and_fill_flat_types!(self, variants, ty)
788 }
789
790 pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
792 intern_and_fill_flat_types!(self, enums, ty)
793 }
794
795 pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
797 intern_and_fill_flat_types!(self, options, ty)
798 }
799
800 pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
802 intern_and_fill_flat_types!(self, results, ty)
803 }
804
805 pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
807 intern_and_fill_flat_types!(self, lists, ty)
808 }
809
810 pub fn add_map_type(&mut self, ty: TypeMap) -> TypeMapIndex {
812 intern_and_fill_flat_types!(self, maps, ty)
813 }
814
815 pub fn add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex {
817 intern(&mut self.futures, &mut self.component_types.futures, ty)
818 }
819
820 pub fn add_future_table_type(&mut self, ty: TypeFutureTable) -> TypeFutureTableIndex {
822 intern(
823 &mut self.future_tables,
824 &mut self.component_types.future_tables,
825 ty,
826 )
827 }
828
829 pub fn add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex {
831 intern(&mut self.streams, &mut self.component_types.streams, ty)
832 }
833
834 pub fn add_stream_table_type(&mut self, ty: TypeStreamTable) -> TypeStreamTableIndex {
836 intern(
837 &mut self.stream_tables,
838 &mut self.component_types.stream_tables,
839 ty,
840 )
841 }
842
843 pub fn add_error_context_table_type(
845 &mut self,
846 ty: TypeErrorContextTable,
847 ) -> TypeComponentLocalErrorContextTableIndex {
848 intern(
849 &mut self.error_context_tables,
850 &mut self.component_types.error_context_tables,
851 ty,
852 )
853 }
854
855 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
857 self.component_types.canonical_abi(ty)
858 }
859
860 pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
866 self.type_information(ty).flat.as_flat_types()
867 }
868
869 pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
872 self.type_information(ty).handles.has_borrow()
873 }
874
875 fn ty_contains_any_handle(&self, ty: &InterfaceType) -> bool {
878 self.type_information(ty).handles.has_any()
879 }
880
881 pub fn ty_contains_string(&self, ty: &InterfaceType) -> bool {
883 self.type_information(ty).has_string
884 }
885
886 pub fn func_contains_any_handle(&self, ty: TypeFuncIndex) -> bool {
889 let ty = &self[ty];
890 let params = &self[ty.params].types;
891 let results = &self[ty.results].types;
892 params
893 .iter()
894 .chain(results.iter())
895 .any(|ty| self.ty_contains_any_handle(ty))
896 }
897
898 fn type_information(&self, ty: &InterfaceType) -> &TypeInformation {
899 match ty {
900 InterfaceType::U8
901 | InterfaceType::S8
902 | InterfaceType::Bool
903 | InterfaceType::U16
904 | InterfaceType::S16
905 | InterfaceType::U32
906 | InterfaceType::S32
907 | InterfaceType::Char => {
908 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I32);
909 &INFO
910 }
911 InterfaceType::Own(_)
912 | InterfaceType::Future(_)
913 | InterfaceType::Stream(_)
914 | InterfaceType::ErrorContext(_) => {
915 static INFO: TypeInformation = {
916 let mut info = TypeInformation::primitive(FlatType::I32);
917 info.handles = Handles::NoBorrow;
918 info
919 };
920 &INFO
921 }
922 InterfaceType::Borrow(_) => {
923 static INFO: TypeInformation = {
924 let mut info = TypeInformation::primitive(FlatType::I32);
925 info.handles = Handles::Borrow;
926 info
927 };
928 &INFO
929 }
930 InterfaceType::U64 | InterfaceType::S64 => {
931 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I64);
932 &INFO
933 }
934 InterfaceType::Float32 => {
935 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F32);
936 &INFO
937 }
938 InterfaceType::Float64 => {
939 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F64);
940 &INFO
941 }
942 InterfaceType::String => {
943 static INFO: TypeInformation = {
944 let mut info = TypeInformation::string();
945 info.has_string = true;
946 info
947 };
948 &INFO
949 }
950
951 InterfaceType::List(i) => &self.type_info.lists[*i],
952 InterfaceType::Map(i) => &self.type_info.maps[*i],
953 InterfaceType::Record(i) => &self.type_info.records[*i],
954 InterfaceType::Variant(i) => &self.type_info.variants[*i],
955 InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
956 InterfaceType::Flags(i) => &self.type_info.flags[*i],
957 InterfaceType::Enum(i) => &self.type_info.enums[*i],
958 InterfaceType::Option(i) => &self.type_info.options[*i],
959 InterfaceType::Result(i) => &self.type_info.results[*i],
960 InterfaceType::FixedLengthList(i) => &self.type_info.fixed_length_lists[*i],
961 }
962 }
963}
964
965impl TypeConvert for ComponentTypesBuilder {
966 fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
967 self.module_type_converter().lookup_heap_type(index)
968 }
969
970 fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
971 self.module_type_converter().lookup_type_index(index)
972 }
973}
974
975impl ComponentTypesBuilder {
976 fn module_type_converter(
977 &self,
978 ) -> WasmparserTypeConverter<'_, impl Fn(TypeIndex) -> ModuleInternedTypeIndex> {
979 WasmparserTypeConverter::new(&self.module_types, |_| {
982 unreachable!("component-level types don't use module type indices")
983 })
984 }
985}
986
987fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut TryPrimaryMap<U, T>, item: T) -> U
988where
989 T: Hash + TryClone + Eq,
990 U: Copy + EntityRef,
991{
992 if let Some(idx) = map.get(&item) {
993 return *idx;
994 }
995 let idx = list.push(item.clone_panic_on_oom()).panic_on_oom();
996 map.insert(item, idx);
997 return idx;
998}
999
1000struct FlatTypesStorage {
1001 memory32: [FlatType; MAX_FLAT_TYPES],
1006 memory64: [FlatType; MAX_FLAT_TYPES],
1007
1008 len: u8,
1012}
1013
1014impl FlatTypesStorage {
1015 const fn new() -> FlatTypesStorage {
1016 FlatTypesStorage {
1017 memory32: [FlatType::I32; MAX_FLAT_TYPES],
1018 memory64: [FlatType::I32; MAX_FLAT_TYPES],
1019 len: 0,
1020 }
1021 }
1022
1023 fn as_flat_types(&self) -> Option<FlatTypes<'_>> {
1024 let len = usize::from(self.len);
1025 if len > MAX_FLAT_TYPES {
1026 assert_eq!(len, MAX_FLAT_TYPES + 1);
1027 None
1028 } else {
1029 Some(FlatTypes {
1030 memory32: &self.memory32[..len],
1031 memory64: &self.memory64[..len],
1032 })
1033 }
1034 }
1035
1036 fn push(&mut self, t32: FlatType, t64: FlatType) -> bool {
1043 let len = usize::from(self.len);
1044 if len < MAX_FLAT_TYPES {
1045 self.memory32[len] = t32;
1046 self.memory64[len] = t64;
1047 self.len += 1;
1048 true
1049 } else {
1050 if len == MAX_FLAT_TYPES {
1053 self.len += 1;
1054 }
1055 false
1056 }
1057 }
1058}
1059
1060impl FlatType {
1061 fn join(&mut self, other: FlatType) {
1062 if *self == other {
1063 return;
1064 }
1065 *self = match (*self, other) {
1066 (FlatType::I32, FlatType::F32) | (FlatType::F32, FlatType::I32) => FlatType::I32,
1067 _ => FlatType::I64,
1068 };
1069 }
1070}
1071
1072#[derive(Default)]
1073struct TypeInformationCache {
1074 records: PrimaryMap<TypeRecordIndex, TypeInformation>,
1075 variants: PrimaryMap<TypeVariantIndex, TypeInformation>,
1076 tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
1077 enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
1078 flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
1079 options: PrimaryMap<TypeOptionIndex, TypeInformation>,
1080 results: PrimaryMap<TypeResultIndex, TypeInformation>,
1081 lists: PrimaryMap<TypeListIndex, TypeInformation>,
1082 maps: PrimaryMap<TypeMapIndex, TypeInformation>,
1083 fixed_length_lists: PrimaryMap<TypeFixedLengthListIndex, TypeInformation>,
1084}
1085
1086#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1088enum Handles {
1089 None,
1091
1092 NoBorrow,
1096
1097 Borrow,
1099}
1100
1101impl Handles {
1102 const fn has_any(self) -> bool {
1104 !matches!(self, Handles::None)
1105 }
1106
1107 const fn has_borrow(self) -> bool {
1109 matches!(self, Handles::Borrow)
1110 }
1111
1112 const fn join(a: Self, b: Self) -> Handles {
1114 match (a, b) {
1115 (Handles::Borrow, _) | (_, Handles::Borrow) => Handles::Borrow,
1116 (Handles::NoBorrow, _) | (_, Handles::NoBorrow) => Handles::NoBorrow,
1117 (Handles::None, Handles::None) => Handles::None,
1118 }
1119 }
1120}
1121
1122struct TypeInformation {
1123 flat: FlatTypesStorage,
1124
1125 handles: Handles,
1127
1128 has_string: bool,
1130}
1131
1132impl TypeInformation {
1133 const fn new() -> TypeInformation {
1134 TypeInformation {
1135 flat: FlatTypesStorage::new(),
1136 handles: Handles::None,
1137 has_string: false,
1138 }
1139 }
1140
1141 const fn primitive(flat: FlatType) -> TypeInformation {
1142 let mut info = TypeInformation::new();
1143 info.flat.memory32[0] = flat;
1144 info.flat.memory64[0] = flat;
1145 info.flat.len = 1;
1146 info
1147 }
1148
1149 const fn string() -> TypeInformation {
1150 let mut info = TypeInformation::new();
1151 info.flat.memory32[0] = FlatType::I32;
1152 info.flat.memory32[1] = FlatType::I32;
1153 info.flat.memory64[0] = FlatType::I64;
1154 info.flat.memory64[1] = FlatType::I64;
1155 info.flat.len = 2;
1156 info
1157 }
1158
1159 fn build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>) {
1162 for info in types {
1163 self.handles = Handles::join(self.handles, info.handles);
1164 self.has_string |= info.has_string;
1165 match info.flat.as_flat_types() {
1166 Some(types) => {
1167 for (t32, t64) in types.memory32.iter().zip(types.memory64) {
1168 if !self.flat.push(*t32, *t64) {
1169 break;
1170 }
1171 }
1172 }
1173 None => {
1174 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1175 }
1176 }
1177 }
1178 }
1179
1180 fn build_variant<'a, I>(&mut self, cases: I)
1192 where
1193 I: IntoIterator<Item = Option<&'a TypeInformation>>,
1194 {
1195 let cases = cases.into_iter();
1196 self.flat.push(FlatType::I32, FlatType::I32);
1197
1198 for info in cases {
1199 let info = match info {
1200 Some(info) => info,
1201 None => continue,
1204 };
1205 self.handles = Handles::join(self.handles, info.handles);
1206 self.has_string |= info.has_string;
1207
1208 if usize::from(self.flat.len) > MAX_FLAT_TYPES {
1211 continue;
1212 }
1213
1214 let types = match info.flat.as_flat_types() {
1215 Some(types) => types,
1216 None => {
1219 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1220 continue;
1221 }
1222 };
1223 if types.memory32.len() >= MAX_FLAT_TYPES {
1227 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1228 continue;
1229 }
1230 let dst = self
1231 .flat
1232 .memory32
1233 .iter_mut()
1234 .zip(&mut self.flat.memory64)
1235 .skip(1);
1236 for (i, ((t32, t64), (dst32, dst64))) in types
1237 .memory32
1238 .iter()
1239 .zip(types.memory64)
1240 .zip(dst)
1241 .enumerate()
1242 {
1243 if i + 1 < usize::from(self.flat.len) {
1244 dst32.join(*t32);
1247 dst64.join(*t64);
1248 } else {
1249 self.flat.len += 1;
1254 *dst32 = *t32;
1255 *dst64 = *t64;
1256 }
1257 }
1258 }
1259 }
1260
1261 fn records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord) {
1262 self.build_record(ty.fields.iter().map(|f| types.type_information(&f.ty)));
1263 }
1264
1265 fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
1266 self.build_record(ty.types.iter().map(|t| types.type_information(t)));
1267 }
1268
1269 fn fixed_length_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedLengthList) {
1270 let element_info = types.type_information(&ty.element);
1271 self.handles = element_info.handles;
1272 self.has_string = element_info.has_string;
1273 match element_info.flat.as_flat_types() {
1274 Some(types) => {
1275 'outer: for _ in 0..ty.size {
1276 for (t32, t64) in types.memory32.iter().zip(types.memory64) {
1277 if !self.flat.push(*t32, *t64) {
1278 break 'outer;
1279 }
1280 }
1281 }
1282 }
1283 None => self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap(),
1284 }
1285 }
1286
1287 fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
1288 self.flat.push(FlatType::I32, FlatType::I32);
1289 }
1290
1291 fn flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags) {
1292 match FlagsSize::from_count(ty.names.len()) {
1293 FlagsSize::Size0 => {}
1294 FlagsSize::Size1 | FlagsSize::Size2 => {
1295 self.flat.push(FlatType::I32, FlatType::I32);
1296 }
1297 FlagsSize::Size4Plus(n) => {
1298 for _ in 0..n {
1299 self.flat.push(FlatType::I32, FlatType::I32);
1300 }
1301 }
1302 }
1303 }
1304
1305 fn variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant) {
1306 self.build_variant(
1307 ty.cases
1308 .iter()
1309 .map(|(_, c)| c.as_ref().map(|ty| types.type_information(ty))),
1310 )
1311 }
1312
1313 fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
1314 self.build_variant([
1315 ty.ok.as_ref().map(|ty| types.type_information(ty)),
1316 ty.err.as_ref().map(|ty| types.type_information(ty)),
1317 ])
1318 }
1319
1320 fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
1321 self.build_variant([None, Some(types.type_information(&ty.ty))]);
1322 }
1323
1324 fn lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList) {
1325 *self = TypeInformation::string();
1326 let info = types.type_information(&ty.element);
1327 self.handles = info.handles;
1328 self.has_string = info.has_string;
1329 }
1330
1331 fn maps(&mut self, types: &ComponentTypesBuilder, ty: &TypeMap) {
1332 *self = TypeInformation::string();
1335 let key_info = types.type_information(&ty.key);
1336 let value_info = types.type_information(&ty.value);
1337 self.handles = Handles::join(key_info.handles, value_info.handles);
1338 self.has_string = key_info.has_string || value_info.has_string;
1339 }
1340}