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