1use crate::component::*;
2use crate::prelude::*;
3use crate::{
4 EngineOrModuleTypeIndex, EntityType, ModuleInternedTypeIndex, ModuleTypes, ModuleTypesBuilder,
5 PrimaryMap, TypeConvert, WasmHeapType, WasmValType,
6};
7use anyhow::{bail, Result};
8use cranelift_entity::EntityRef;
9use std::collections::HashMap;
10use std::hash::Hash;
11use std::ops::Index;
12use wasmparser::component_types::{
13 ComponentAnyTypeId, ComponentCoreModuleTypeId, ComponentDefinedType, ComponentDefinedTypeId,
14 ComponentEntityType, ComponentFuncTypeId, ComponentInstanceTypeId, ComponentTypeId,
15 ComponentValType, RecordType, ResourceId, TupleType, VariantType,
16};
17use wasmparser::names::KebabString;
18use wasmparser::types::TypesRef;
19use wasmparser::Validator;
20use wasmtime_component_util::FlagsSize;
21
22mod resources;
23pub use resources::ResourcesBuilder;
24
25const MAX_TYPE_DEPTH: u32 = 100;
33
34pub struct ComponentTypesBuilder {
39 functions: HashMap<TypeFunc, TypeFuncIndex>,
40 lists: HashMap<TypeList, TypeListIndex>,
41 records: HashMap<TypeRecord, TypeRecordIndex>,
42 variants: HashMap<TypeVariant, TypeVariantIndex>,
43 tuples: HashMap<TypeTuple, TypeTupleIndex>,
44 enums: HashMap<TypeEnum, TypeEnumIndex>,
45 flags: HashMap<TypeFlags, TypeFlagsIndex>,
46 options: HashMap<TypeOption, TypeOptionIndex>,
47 results: HashMap<TypeResult, TypeResultIndex>,
48 futures: HashMap<TypeFuture, TypeFutureIndex>,
49 streams: HashMap<TypeStream, TypeStreamIndex>,
50 future_tables: HashMap<TypeFutureTable, TypeFutureTableIndex>,
51 stream_tables: HashMap<TypeStreamTable, TypeStreamTableIndex>,
52 error_context_tables: HashMap<TypeErrorContextTable, TypeComponentLocalErrorContextTableIndex>,
53 task_returns: HashMap<TypeTaskReturn, TypeTaskReturnIndex>,
54
55 component_types: ComponentTypes,
56 module_types: ModuleTypesBuilder,
57
58 type_info: TypeInformationCache,
62
63 resources: ResourcesBuilder,
64}
65
66impl<T> Index<T> for ComponentTypesBuilder
67where
68 ModuleTypes: Index<T>,
69{
70 type Output = <ModuleTypes as Index<T>>::Output;
71 fn index(&self, idx: T) -> &Self::Output {
72 self.module_types.index(idx)
73 }
74}
75
76macro_rules! intern_and_fill_flat_types {
77 ($me:ident, $name:ident, $val:ident) => {{
78 if let Some(idx) = $me.$name.get(&$val) {
79 *idx
80 } else {
81 let idx = $me.component_types.$name.push($val.clone());
82 let mut info = TypeInformation::new();
83 info.$name($me, &$val);
84 let idx2 = $me.type_info.$name.push(info);
85 assert_eq!(idx, idx2);
86 $me.$name.insert($val, idx);
87 idx
88 }
89 }};
90}
91
92impl ComponentTypesBuilder {
93 pub fn new(validator: &Validator) -> Self {
95 Self {
96 module_types: ModuleTypesBuilder::new(validator),
97
98 functions: HashMap::default(),
99 lists: HashMap::default(),
100 records: HashMap::default(),
101 variants: HashMap::default(),
102 tuples: HashMap::default(),
103 enums: HashMap::default(),
104 flags: HashMap::default(),
105 options: HashMap::default(),
106 results: HashMap::default(),
107 futures: HashMap::default(),
108 streams: HashMap::default(),
109 future_tables: HashMap::default(),
110 stream_tables: HashMap::default(),
111 error_context_tables: HashMap::default(),
112 task_returns: HashMap::default(),
113 component_types: ComponentTypes::default(),
114 type_info: TypeInformationCache::default(),
115 resources: ResourcesBuilder::default(),
116 }
117 }
118
119 fn export_type_def(
120 &mut self,
121 export_items: &PrimaryMap<ExportIndex, Export>,
122 idx: ExportIndex,
123 ) -> TypeDef {
124 match &export_items[idx] {
125 Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(*ty),
126 Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
127 TypeDef::Module(*ty)
128 }
129 Export::Instance { ty, .. } => TypeDef::ComponentInstance(*ty),
130 Export::Type(ty) => *ty,
131 }
132 }
133
134 pub fn finish(mut self, component: &Component) -> (ComponentTypes, TypeComponentIndex) {
138 let mut component_ty = TypeComponent::default();
139 for (_, (name, ty)) in component.import_types.iter() {
140 component_ty.imports.insert(name.clone(), *ty);
141 }
142 for (name, ty) in component.exports.raw_iter() {
143 component_ty.exports.insert(
144 name.clone(),
145 self.export_type_def(&component.export_items, *ty),
146 );
147 }
148 let ty = self.component_types.components.push(component_ty);
149
150 self.component_types.module_types = Some(self.module_types.finish());
151 (self.component_types, ty)
152 }
153
154 pub fn find_resource_drop_signature(&self) -> Option<ModuleInternedTypeIndex> {
164 self.module_types
165 .wasm_types()
166 .find(|(_, ty)| {
167 ty.as_func().map_or(false, |sig| {
168 sig.params().len() == 1
169 && sig.returns().len() == 0
170 && sig.params()[0] == WasmValType::I32
171 })
172 })
173 .map(|(i, _)| i)
174 }
175
176 pub fn module_types_builder(&self) -> &ModuleTypesBuilder {
181 &self.module_types
182 }
183
184 pub fn module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder {
186 &mut self.module_types
187 }
188
189 pub(super) fn component_types(&self) -> &ComponentTypes {
191 &self.component_types
192 }
193
194 pub fn num_resource_tables(&self) -> usize {
197 self.component_types.resource_tables.len()
198 }
199
200 pub fn num_future_tables(&self) -> usize {
203 self.component_types.future_tables.len()
204 }
205
206 pub fn num_stream_tables(&self) -> usize {
209 self.component_types.stream_tables.len()
210 }
211
212 pub fn num_error_context_tables(&self) -> usize {
215 self.component_types.error_context_tables.len()
216 }
217
218 pub fn resources_mut(&mut self) -> &mut ResourcesBuilder {
220 &mut self.resources
221 }
222
223 pub fn resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes) {
226 (&mut self.resources, &self.component_types)
227 }
228
229 pub fn convert_component_func_type(
232 &mut self,
233 types: TypesRef<'_>,
234 id: ComponentFuncTypeId,
235 ) -> Result<TypeFuncIndex> {
236 assert_eq!(types.id(), self.module_types.validator_id());
237 let ty = &types[id];
238 let param_names = ty.params.iter().map(|(name, _)| name.to_string()).collect();
239 let params = ty
240 .params
241 .iter()
242 .map(|(_name, ty)| self.valtype(types, ty))
243 .collect::<Result<_>>()?;
244 let results = ty
245 .results
246 .iter()
247 .map(|(_name, ty)| self.valtype(types, ty))
248 .collect::<Result<_>>()?;
249 let params = self.new_tuple_type(params);
250 let results = self.new_tuple_type(results);
251 let (task_return_type32, task_return_type64) =
252 if let Some(types) = self.flat_types(&InterfaceType::Tuple(results)) {
253 (types.memory32.to_vec(), types.memory64.to_vec())
254 } else {
255 (vec![FlatType::I32], vec![FlatType::I64])
256 };
257 let ty = TypeFunc {
258 param_names,
259 params,
260 results,
261 task_return_type32: self.add_task_return_type(TypeTaskReturn {
262 params: task_return_type32,
263 }),
264 task_return_type64: self.add_task_return_type(TypeTaskReturn {
265 params: task_return_type64,
266 }),
267 };
268 Ok(self.add_func_type(ty))
269 }
270
271 pub fn convert_component_entity_type(
274 &mut self,
275 types: TypesRef<'_>,
276 ty: ComponentEntityType,
277 ) -> Result<TypeDef> {
278 assert_eq!(types.id(), self.module_types.validator_id());
279 Ok(match ty {
280 ComponentEntityType::Module(id) => TypeDef::Module(self.convert_module(types, id)?),
281 ComponentEntityType::Component(id) => {
282 TypeDef::Component(self.convert_component(types, id)?)
283 }
284 ComponentEntityType::Instance(id) => {
285 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
286 }
287 ComponentEntityType::Func(id) => {
288 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
289 }
290 ComponentEntityType::Type { created, .. } => match created {
291 ComponentAnyTypeId::Defined(id) => {
292 TypeDef::Interface(self.defined_type(types, id)?)
293 }
294 ComponentAnyTypeId::Resource(id) => {
295 TypeDef::Resource(self.resource_id(id.resource()))
296 }
297 _ => bail!("unsupported type export"),
298 },
299 ComponentEntityType::Value(_) => bail!("values not supported"),
300 })
301 }
302
303 pub fn convert_type(&mut self, types: TypesRef<'_>, id: ComponentAnyTypeId) -> Result<TypeDef> {
305 assert_eq!(types.id(), self.module_types.validator_id());
306 Ok(match id {
307 ComponentAnyTypeId::Defined(id) => TypeDef::Interface(self.defined_type(types, id)?),
308 ComponentAnyTypeId::Component(id) => {
309 TypeDef::Component(self.convert_component(types, id)?)
310 }
311 ComponentAnyTypeId::Instance(id) => {
312 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
313 }
314 ComponentAnyTypeId::Func(id) => {
315 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
316 }
317 ComponentAnyTypeId::Resource(id) => TypeDef::Resource(self.resource_id(id.resource())),
318 })
319 }
320
321 fn convert_component(
322 &mut self,
323 types: TypesRef<'_>,
324 id: ComponentTypeId,
325 ) -> Result<TypeComponentIndex> {
326 assert_eq!(types.id(), self.module_types.validator_id());
327 let ty = &types[id];
328 let mut result = TypeComponent::default();
329 for (name, ty) in ty.imports.iter() {
330 result.imports.insert(
331 name.clone(),
332 self.convert_component_entity_type(types, *ty)?,
333 );
334 }
335 for (name, ty) in ty.exports.iter() {
336 result.exports.insert(
337 name.clone(),
338 self.convert_component_entity_type(types, *ty)?,
339 );
340 }
341 Ok(self.component_types.components.push(result))
342 }
343
344 pub(crate) fn convert_instance(
345 &mut self,
346 types: TypesRef<'_>,
347 id: ComponentInstanceTypeId,
348 ) -> Result<TypeComponentInstanceIndex> {
349 assert_eq!(types.id(), self.module_types.validator_id());
350 let ty = &types[id];
351 let mut result = TypeComponentInstance::default();
352 for (name, ty) in ty.exports.iter() {
353 result.exports.insert(
354 name.clone(),
355 self.convert_component_entity_type(types, *ty)?,
356 );
357 }
358 Ok(self.component_types.component_instances.push(result))
359 }
360
361 pub(crate) fn convert_module(
362 &mut self,
363 types: TypesRef<'_>,
364 id: ComponentCoreModuleTypeId,
365 ) -> Result<TypeModuleIndex> {
366 assert_eq!(types.id(), self.module_types.validator_id());
367 let ty = &types[id];
368 let mut result = TypeModule::default();
369 for ((module, field), ty) in ty.imports.iter() {
370 result.imports.insert(
371 (module.clone(), field.clone()),
372 self.entity_type(types, ty)?,
373 );
374 }
375 for (name, ty) in ty.exports.iter() {
376 result
377 .exports
378 .insert(name.clone(), self.entity_type(types, ty)?);
379 }
380 Ok(self.component_types.modules.push(result))
381 }
382
383 fn entity_type(
384 &mut self,
385 types: TypesRef<'_>,
386 ty: &wasmparser::types::EntityType,
387 ) -> Result<EntityType> {
388 use wasmparser::types::EntityType::*;
389
390 assert_eq!(types.id(), self.module_types.validator_id());
391 Ok(match ty {
392 Func(id) => EntityType::Function({
393 self.module_types_builder_mut()
394 .intern_type(types, *id)?
395 .into()
396 }),
397 Table(ty) => EntityType::Table(self.convert_table_type(ty)?),
398 Memory(ty) => EntityType::Memory((*ty).into()),
399 Global(ty) => EntityType::Global(self.convert_global_type(ty)),
400 Tag(_) => bail!("exceptions proposal not implemented"),
401 })
402 }
403
404 pub fn defined_type(
406 &mut self,
407 types: TypesRef<'_>,
408 id: ComponentDefinedTypeId,
409 ) -> Result<InterfaceType> {
410 assert_eq!(types.id(), self.module_types.validator_id());
411 let ret = match &types[id] {
412 ComponentDefinedType::Primitive(ty) => ty.into(),
413 ComponentDefinedType::Record(e) => InterfaceType::Record(self.record_type(types, e)?),
414 ComponentDefinedType::Variant(e) => {
415 InterfaceType::Variant(self.variant_type(types, e)?)
416 }
417 ComponentDefinedType::List(e) => InterfaceType::List(self.list_type(types, e)?),
418 ComponentDefinedType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(types, e)?),
419 ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
420 ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
421 ComponentDefinedType::Option(e) => InterfaceType::Option(self.option_type(types, e)?),
422 ComponentDefinedType::Result { ok, err } => {
423 InterfaceType::Result(self.result_type(types, ok, err)?)
424 }
425 ComponentDefinedType::Own(r) => InterfaceType::Own(self.resource_id(r.resource())),
426 ComponentDefinedType::Borrow(r) => {
427 InterfaceType::Borrow(self.resource_id(r.resource()))
428 }
429 ComponentDefinedType::Future(ty) => {
430 InterfaceType::Future(self.future_table_type(types, ty)?)
431 }
432 ComponentDefinedType::Stream(ty) => {
433 InterfaceType::Stream(self.stream_table_type(types, ty)?)
434 }
435 ComponentDefinedType::ErrorContext => {
436 InterfaceType::ErrorContext(self.error_context_table_type()?)
437 }
438 };
439 let info = self.type_information(&ret);
440 if info.depth > MAX_TYPE_DEPTH {
441 bail!("type nesting is too deep");
442 }
443 Ok(ret)
444 }
445
446 fn valtype(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<InterfaceType> {
447 assert_eq!(types.id(), self.module_types.validator_id());
448 match ty {
449 ComponentValType::Primitive(p) => Ok(p.into()),
450 ComponentValType::Type(id) => self.defined_type(types, *id),
451 }
452 }
453
454 fn record_type(&mut self, types: TypesRef<'_>, ty: &RecordType) -> Result<TypeRecordIndex> {
455 assert_eq!(types.id(), self.module_types.validator_id());
456 let fields = ty
457 .fields
458 .iter()
459 .map(|(name, ty)| {
460 Ok(RecordField {
461 name: name.to_string(),
462 ty: self.valtype(types, ty)?,
463 })
464 })
465 .collect::<Result<Box<[_]>>>()?;
466 let abi = CanonicalAbiInfo::record(
467 fields
468 .iter()
469 .map(|field| self.component_types.canonical_abi(&field.ty)),
470 );
471 Ok(self.add_record_type(TypeRecord { fields, abi }))
472 }
473
474 fn variant_type(&mut self, types: TypesRef<'_>, ty: &VariantType) -> Result<TypeVariantIndex> {
475 assert_eq!(types.id(), self.module_types.validator_id());
476 let cases = ty
477 .cases
478 .iter()
479 .map(|(name, case)| {
480 if case.refines.is_some() {
483 bail!("refines is not supported at this time");
484 }
485 Ok((
486 name.to_string(),
487 match &case.ty.as_ref() {
488 Some(ty) => Some(self.valtype(types, ty)?),
489 None => None,
490 },
491 ))
492 })
493 .collect::<Result<IndexMap<_, _>>>()?;
494 let (info, abi) = VariantInfo::new(
495 cases
496 .iter()
497 .map(|(_, c)| c.as_ref().map(|ty| self.component_types.canonical_abi(ty))),
498 );
499 Ok(self.add_variant_type(TypeVariant { cases, abi, info }))
500 }
501
502 fn tuple_type(&mut self, types: TypesRef<'_>, ty: &TupleType) -> Result<TypeTupleIndex> {
503 assert_eq!(types.id(), self.module_types.validator_id());
504 let types = ty
505 .types
506 .iter()
507 .map(|ty| self.valtype(types, ty))
508 .collect::<Result<Box<[_]>>>()?;
509 Ok(self.new_tuple_type(types))
510 }
511
512 fn new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex {
513 let abi = CanonicalAbiInfo::record(
514 types
515 .iter()
516 .map(|ty| self.component_types.canonical_abi(ty)),
517 );
518 self.add_tuple_type(TypeTuple { types, abi })
519 }
520
521 fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
522 let flags = TypeFlags {
523 names: flags.iter().map(|s| s.to_string()).collect(),
524 abi: CanonicalAbiInfo::flags(flags.len()),
525 };
526 self.add_flags_type(flags)
527 }
528
529 fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
530 let names = variants
531 .iter()
532 .map(|s| s.to_string())
533 .collect::<IndexSet<_>>();
534 let (info, abi) = VariantInfo::new(names.iter().map(|_| None));
535 self.add_enum_type(TypeEnum { names, abi, info })
536 }
537
538 fn option_type(
539 &mut self,
540 types: TypesRef<'_>,
541 ty: &ComponentValType,
542 ) -> Result<TypeOptionIndex> {
543 assert_eq!(types.id(), self.module_types.validator_id());
544 let ty = self.valtype(types, ty)?;
545 let (info, abi) = VariantInfo::new([None, Some(self.component_types.canonical_abi(&ty))]);
546 Ok(self.add_option_type(TypeOption { ty, abi, info }))
547 }
548
549 fn result_type(
550 &mut self,
551 types: TypesRef<'_>,
552 ok: &Option<ComponentValType>,
553 err: &Option<ComponentValType>,
554 ) -> Result<TypeResultIndex> {
555 assert_eq!(types.id(), self.module_types.validator_id());
556 let ok = match ok {
557 Some(ty) => Some(self.valtype(types, ty)?),
558 None => None,
559 };
560 let err = match err {
561 Some(ty) => Some(self.valtype(types, ty)?),
562 None => None,
563 };
564 let (info, abi) = VariantInfo::new([
565 ok.as_ref().map(|t| self.component_types.canonical_abi(t)),
566 err.as_ref().map(|t| self.component_types.canonical_abi(t)),
567 ]);
568 Ok(self.add_result_type(TypeResult { ok, err, abi, info }))
569 }
570
571 fn future_table_type(
572 &mut self,
573 types: TypesRef<'_>,
574 ty: &Option<ComponentValType>,
575 ) -> Result<TypeFutureTableIndex> {
576 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
577 let ty = self.add_future_type(TypeFuture { payload });
578 Ok(self.add_future_table_type(TypeFutureTable {
579 ty,
580 instance: self.resources.get_current_instance().unwrap(),
581 }))
582 }
583
584 fn stream_table_type(
585 &mut self,
586 types: TypesRef<'_>,
587 ty: &Option<ComponentValType>,
588 ) -> Result<TypeStreamTableIndex> {
589 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
590 let ty = self.add_stream_type(TypeStream { payload });
591 Ok(self.add_stream_table_type(TypeStreamTable {
592 ty,
593 instance: self.resources.get_current_instance().unwrap(),
594 }))
595 }
596
597 pub fn error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
600 Ok(self.add_error_context_table_type(TypeErrorContextTable {
601 instance: self.resources.get_current_instance().unwrap(),
602 }))
603 }
604
605 fn list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<TypeListIndex> {
606 assert_eq!(types.id(), self.module_types.validator_id());
607 let element = self.valtype(types, ty)?;
608 Ok(self.add_list_type(TypeList { element }))
609 }
610
611 pub fn resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex {
614 self.resources.convert(id, &mut self.component_types)
615 }
616
617 pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
619 intern(&mut self.functions, &mut self.component_types.functions, ty)
620 }
621
622 pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
624 intern_and_fill_flat_types!(self, records, ty)
625 }
626
627 pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
629 intern_and_fill_flat_types!(self, flags, ty)
630 }
631
632 pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
634 intern_and_fill_flat_types!(self, tuples, ty)
635 }
636
637 pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
639 intern_and_fill_flat_types!(self, variants, ty)
640 }
641
642 pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
644 intern_and_fill_flat_types!(self, enums, ty)
645 }
646
647 pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
649 intern_and_fill_flat_types!(self, options, ty)
650 }
651
652 pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
654 intern_and_fill_flat_types!(self, results, ty)
655 }
656
657 pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
659 intern_and_fill_flat_types!(self, lists, ty)
660 }
661
662 pub fn add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex {
664 intern(&mut self.futures, &mut self.component_types.futures, ty)
665 }
666
667 pub fn add_future_table_type(&mut self, ty: TypeFutureTable) -> TypeFutureTableIndex {
669 intern(
670 &mut self.future_tables,
671 &mut self.component_types.future_tables,
672 ty,
673 )
674 }
675
676 pub fn add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex {
678 intern(&mut self.streams, &mut self.component_types.streams, ty)
679 }
680
681 pub fn add_stream_table_type(&mut self, ty: TypeStreamTable) -> TypeStreamTableIndex {
683 intern(
684 &mut self.stream_tables,
685 &mut self.component_types.stream_tables,
686 ty,
687 )
688 }
689
690 pub fn add_error_context_table_type(
692 &mut self,
693 ty: TypeErrorContextTable,
694 ) -> TypeComponentLocalErrorContextTableIndex {
695 intern(
696 &mut self.error_context_tables,
697 &mut self.component_types.error_context_tables,
698 ty,
699 )
700 }
701
702 pub fn add_task_return_type(&mut self, ty: TypeTaskReturn) -> TypeTaskReturnIndex {
704 intern(
705 &mut self.task_returns,
706 &mut self.component_types.task_returns,
707 ty,
708 )
709 }
710
711 pub fn get_task_return_type(&self, ty: &TypeTaskReturn) -> Option<TypeTaskReturnIndex> {
714 self.task_returns.get(ty).copied()
715 }
716
717 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
719 self.component_types.canonical_abi(ty)
720 }
721
722 pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
728 self.type_information(ty).flat.as_flat_types()
729 }
730
731 pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
734 self.type_information(ty).has_borrow
735 }
736
737 fn type_information(&self, ty: &InterfaceType) -> &TypeInformation {
738 match ty {
739 InterfaceType::U8
740 | InterfaceType::S8
741 | InterfaceType::Bool
742 | InterfaceType::U16
743 | InterfaceType::S16
744 | InterfaceType::U32
745 | InterfaceType::S32
746 | InterfaceType::Char
747 | InterfaceType::Own(_)
748 | InterfaceType::Future(_)
749 | InterfaceType::Stream(_)
750 | InterfaceType::ErrorContext(_) => {
751 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I32);
752 &INFO
753 }
754 InterfaceType::Borrow(_) => {
755 static INFO: TypeInformation = {
756 let mut info = TypeInformation::primitive(FlatType::I32);
757 info.has_borrow = true;
758 info
759 };
760 &INFO
761 }
762 InterfaceType::U64 | InterfaceType::S64 => {
763 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I64);
764 &INFO
765 }
766 InterfaceType::Float32 => {
767 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F32);
768 &INFO
769 }
770 InterfaceType::Float64 => {
771 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F64);
772 &INFO
773 }
774 InterfaceType::String => {
775 static INFO: TypeInformation = TypeInformation::string();
776 &INFO
777 }
778
779 InterfaceType::List(i) => &self.type_info.lists[*i],
780 InterfaceType::Record(i) => &self.type_info.records[*i],
781 InterfaceType::Variant(i) => &self.type_info.variants[*i],
782 InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
783 InterfaceType::Flags(i) => &self.type_info.flags[*i],
784 InterfaceType::Enum(i) => &self.type_info.enums[*i],
785 InterfaceType::Option(i) => &self.type_info.options[*i],
786 InterfaceType::Result(i) => &self.type_info.results[*i],
787 }
788 }
789}
790
791impl TypeConvert for ComponentTypesBuilder {
792 fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType {
793 panic!("heap types are not supported yet")
794 }
795
796 fn lookup_type_index(&self, _index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
797 panic!("typed references are not supported yet")
798 }
799}
800
801fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U
802where
803 T: Hash + Clone + Eq,
804 U: Copy + EntityRef,
805{
806 if let Some(idx) = map.get(&item) {
807 return *idx;
808 }
809 let idx = list.push(item.clone());
810 map.insert(item, idx);
811 return idx;
812}
813
814struct FlatTypesStorage {
815 memory32: [FlatType; MAX_FLAT_TYPES],
820 memory64: [FlatType; MAX_FLAT_TYPES],
821
822 len: u8,
826}
827
828impl FlatTypesStorage {
829 const fn new() -> FlatTypesStorage {
830 FlatTypesStorage {
831 memory32: [FlatType::I32; MAX_FLAT_TYPES],
832 memory64: [FlatType::I32; MAX_FLAT_TYPES],
833 len: 0,
834 }
835 }
836
837 fn as_flat_types(&self) -> Option<FlatTypes<'_>> {
838 let len = usize::from(self.len);
839 if len > MAX_FLAT_TYPES {
840 assert_eq!(len, MAX_FLAT_TYPES + 1);
841 None
842 } else {
843 Some(FlatTypes {
844 memory32: &self.memory32[..len],
845 memory64: &self.memory64[..len],
846 })
847 }
848 }
849
850 fn push(&mut self, t32: FlatType, t64: FlatType) -> bool {
857 let len = usize::from(self.len);
858 if len < MAX_FLAT_TYPES {
859 self.memory32[len] = t32;
860 self.memory64[len] = t64;
861 self.len += 1;
862 true
863 } else {
864 if len == MAX_FLAT_TYPES {
867 self.len += 1;
868 }
869 false
870 }
871 }
872}
873
874impl FlatType {
875 fn join(&mut self, other: FlatType) {
876 if *self == other {
877 return;
878 }
879 *self = match (*self, other) {
880 (FlatType::I32, FlatType::F32) | (FlatType::F32, FlatType::I32) => FlatType::I32,
881 _ => FlatType::I64,
882 };
883 }
884}
885
886#[derive(Default)]
887struct TypeInformationCache {
888 records: PrimaryMap<TypeRecordIndex, TypeInformation>,
889 variants: PrimaryMap<TypeVariantIndex, TypeInformation>,
890 tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
891 enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
892 flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
893 options: PrimaryMap<TypeOptionIndex, TypeInformation>,
894 results: PrimaryMap<TypeResultIndex, TypeInformation>,
895 lists: PrimaryMap<TypeListIndex, TypeInformation>,
896}
897
898struct TypeInformation {
899 depth: u32,
900 flat: FlatTypesStorage,
901 has_borrow: bool,
902}
903
904impl TypeInformation {
905 const fn new() -> TypeInformation {
906 TypeInformation {
907 depth: 0,
908 flat: FlatTypesStorage::new(),
909 has_borrow: false,
910 }
911 }
912
913 const fn primitive(flat: FlatType) -> TypeInformation {
914 let mut info = TypeInformation::new();
915 info.depth = 1;
916 info.flat.memory32[0] = flat;
917 info.flat.memory64[0] = flat;
918 info.flat.len = 1;
919 info
920 }
921
922 const fn string() -> TypeInformation {
923 let mut info = TypeInformation::new();
924 info.depth = 1;
925 info.flat.memory32[0] = FlatType::I32;
926 info.flat.memory32[1] = FlatType::I32;
927 info.flat.memory64[0] = FlatType::I64;
928 info.flat.memory64[1] = FlatType::I64;
929 info.flat.len = 2;
930 info
931 }
932
933 fn build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>) {
936 self.depth = 1;
937 for info in types {
938 self.depth = self.depth.max(1 + info.depth);
939 self.has_borrow = self.has_borrow || info.has_borrow;
940 match info.flat.as_flat_types() {
941 Some(types) => {
942 for (t32, t64) in types.memory32.iter().zip(types.memory64) {
943 if !self.flat.push(*t32, *t64) {
944 break;
945 }
946 }
947 }
948 None => {
949 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
950 }
951 }
952 }
953 }
954
955 fn build_variant<'a, I>(&mut self, cases: I)
967 where
968 I: IntoIterator<Item = Option<&'a TypeInformation>>,
969 {
970 let cases = cases.into_iter();
971 self.flat.push(FlatType::I32, FlatType::I32);
972 self.depth = 1;
973
974 for info in cases {
975 let info = match info {
976 Some(info) => info,
977 None => continue,
980 };
981 self.depth = self.depth.max(1 + info.depth);
982 self.has_borrow = self.has_borrow || info.has_borrow;
983
984 if usize::from(self.flat.len) > MAX_FLAT_TYPES {
987 continue;
988 }
989
990 let types = match info.flat.as_flat_types() {
991 Some(types) => types,
992 None => {
995 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
996 continue;
997 }
998 };
999 if types.memory32.len() >= MAX_FLAT_TYPES {
1003 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1004 continue;
1005 }
1006 let dst = self
1007 .flat
1008 .memory32
1009 .iter_mut()
1010 .zip(&mut self.flat.memory64)
1011 .skip(1);
1012 for (i, ((t32, t64), (dst32, dst64))) in types
1013 .memory32
1014 .iter()
1015 .zip(types.memory64)
1016 .zip(dst)
1017 .enumerate()
1018 {
1019 if i + 1 < usize::from(self.flat.len) {
1020 dst32.join(*t32);
1023 dst64.join(*t64);
1024 } else {
1025 self.flat.len += 1;
1030 *dst32 = *t32;
1031 *dst64 = *t64;
1032 }
1033 }
1034 }
1035 }
1036
1037 fn records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord) {
1038 self.build_record(ty.fields.iter().map(|f| types.type_information(&f.ty)));
1039 }
1040
1041 fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
1042 self.build_record(ty.types.iter().map(|t| types.type_information(t)));
1043 }
1044
1045 fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
1046 self.depth = 1;
1047 self.flat.push(FlatType::I32, FlatType::I32);
1048 }
1049
1050 fn flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags) {
1051 self.depth = 1;
1052 match FlagsSize::from_count(ty.names.len()) {
1053 FlagsSize::Size0 => {}
1054 FlagsSize::Size1 | FlagsSize::Size2 => {
1055 self.flat.push(FlatType::I32, FlatType::I32);
1056 }
1057 FlagsSize::Size4Plus(n) => {
1058 for _ in 0..n {
1059 self.flat.push(FlatType::I32, FlatType::I32);
1060 }
1061 }
1062 }
1063 }
1064
1065 fn variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant) {
1066 self.build_variant(
1067 ty.cases
1068 .iter()
1069 .map(|(_, c)| c.as_ref().map(|ty| types.type_information(ty))),
1070 )
1071 }
1072
1073 fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
1074 self.build_variant([
1075 ty.ok.as_ref().map(|ty| types.type_information(ty)),
1076 ty.err.as_ref().map(|ty| types.type_information(ty)),
1077 ])
1078 }
1079
1080 fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
1081 self.build_variant([None, Some(types.type_information(&ty.ty))]);
1082 }
1083
1084 fn lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList) {
1085 *self = TypeInformation::string();
1086 let info = types.type_information(&ty.element);
1087 self.depth += info.depth;
1088 self.has_borrow = info.has_borrow;
1089 }
1090}