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(id) => {
415 let func = self.module_types_builder_mut().intern_type(types, *id)?;
416 let exc = self
417 .module_types_builder_mut()
418 .define_exception_type_for_tag(func);
419 EntityType::Tag(crate::types::Tag {
420 signature: func.into(),
421 exception: exc.into(),
422 })
423 }
424 FuncExact(_) => bail!("custom-descriptors proposal not implemented"),
425 })
426 }
427
428 pub fn defined_type(
430 &mut self,
431 types: TypesRef<'_>,
432 id: ComponentDefinedTypeId,
433 ) -> Result<InterfaceType> {
434 assert_eq!(types.id(), self.module_types.validator_id());
435 let ret = match &types[id] {
436 ComponentDefinedType::Primitive(ty) => self.primitive_type(ty)?,
437 ComponentDefinedType::Record(e) => InterfaceType::Record(self.record_type(types, e)?),
438 ComponentDefinedType::Variant(e) => {
439 InterfaceType::Variant(self.variant_type(types, e)?)
440 }
441 ComponentDefinedType::List(e) => InterfaceType::List(self.list_type(types, e)?),
442 ComponentDefinedType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(types, e)?),
443 ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
444 ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
445 ComponentDefinedType::Option(e) => InterfaceType::Option(self.option_type(types, e)?),
446 ComponentDefinedType::Result { ok, err } => {
447 InterfaceType::Result(self.result_type(types, ok, err)?)
448 }
449 ComponentDefinedType::Own(r) => InterfaceType::Own(self.resource_id(r.resource())),
450 ComponentDefinedType::Borrow(r) => {
451 InterfaceType::Borrow(self.resource_id(r.resource()))
452 }
453 ComponentDefinedType::Future(ty) => {
454 InterfaceType::Future(self.future_table_type(types, ty)?)
455 }
456 ComponentDefinedType::Stream(ty) => {
457 InterfaceType::Stream(self.stream_table_type(types, ty)?)
458 }
459 ComponentDefinedType::FixedSizeList(..) => {
460 bail!("support not implemented for fixed-size-lists");
461 }
462 };
463 let info = self.type_information(&ret);
464 if info.depth > MAX_TYPE_DEPTH {
465 bail!("type nesting is too deep");
466 }
467 Ok(ret)
468 }
469
470 pub fn error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
472 self.error_context_table_type()
473 }
474
475 pub(crate) fn valtype(
476 &mut self,
477 types: TypesRef<'_>,
478 ty: &ComponentValType,
479 ) -> Result<InterfaceType> {
480 assert_eq!(types.id(), self.module_types.validator_id());
481 match ty {
482 ComponentValType::Primitive(p) => self.primitive_type(p),
483 ComponentValType::Type(id) => self.defined_type(types, *id),
484 }
485 }
486
487 fn primitive_type(&mut self, ty: &PrimitiveValType) -> Result<InterfaceType> {
488 match ty {
489 wasmparser::PrimitiveValType::Bool => Ok(InterfaceType::Bool),
490 wasmparser::PrimitiveValType::S8 => Ok(InterfaceType::S8),
491 wasmparser::PrimitiveValType::U8 => Ok(InterfaceType::U8),
492 wasmparser::PrimitiveValType::S16 => Ok(InterfaceType::S16),
493 wasmparser::PrimitiveValType::U16 => Ok(InterfaceType::U16),
494 wasmparser::PrimitiveValType::S32 => Ok(InterfaceType::S32),
495 wasmparser::PrimitiveValType::U32 => Ok(InterfaceType::U32),
496 wasmparser::PrimitiveValType::S64 => Ok(InterfaceType::S64),
497 wasmparser::PrimitiveValType::U64 => Ok(InterfaceType::U64),
498 wasmparser::PrimitiveValType::F32 => Ok(InterfaceType::Float32),
499 wasmparser::PrimitiveValType::F64 => Ok(InterfaceType::Float64),
500 wasmparser::PrimitiveValType::Char => Ok(InterfaceType::Char),
501 wasmparser::PrimitiveValType::String => Ok(InterfaceType::String),
502 wasmparser::PrimitiveValType::ErrorContext => Ok(InterfaceType::ErrorContext(
503 self.error_context_table_type()?,
504 )),
505 }
506 }
507
508 fn record_type(&mut self, types: TypesRef<'_>, ty: &RecordType) -> Result<TypeRecordIndex> {
509 assert_eq!(types.id(), self.module_types.validator_id());
510 let fields = ty
511 .fields
512 .iter()
513 .map(|(name, ty)| {
514 Ok(RecordField {
515 name: name.to_string(),
516 ty: self.valtype(types, ty)?,
517 })
518 })
519 .collect::<Result<Box<[_]>>>()?;
520 let abi = CanonicalAbiInfo::record(
521 fields
522 .iter()
523 .map(|field| self.component_types.canonical_abi(&field.ty)),
524 );
525 Ok(self.add_record_type(TypeRecord { fields, abi }))
526 }
527
528 fn variant_type(&mut self, types: TypesRef<'_>, ty: &VariantType) -> Result<TypeVariantIndex> {
529 assert_eq!(types.id(), self.module_types.validator_id());
530 let cases = ty
531 .cases
532 .iter()
533 .map(|(name, case)| {
534 if case.refines.is_some() {
537 bail!("refines is not supported at this time");
538 }
539 Ok((
540 name.to_string(),
541 match &case.ty.as_ref() {
542 Some(ty) => Some(self.valtype(types, ty)?),
543 None => None,
544 },
545 ))
546 })
547 .collect::<Result<IndexMap<_, _>>>()?;
548 let (info, abi) = VariantInfo::new(
549 cases
550 .iter()
551 .map(|(_, c)| c.as_ref().map(|ty| self.component_types.canonical_abi(ty))),
552 );
553 Ok(self.add_variant_type(TypeVariant { cases, abi, info }))
554 }
555
556 fn tuple_type(&mut self, types: TypesRef<'_>, ty: &TupleType) -> Result<TypeTupleIndex> {
557 assert_eq!(types.id(), self.module_types.validator_id());
558 let types = ty
559 .types
560 .iter()
561 .map(|ty| self.valtype(types, ty))
562 .collect::<Result<Box<[_]>>>()?;
563 Ok(self.new_tuple_type(types))
564 }
565
566 pub(crate) fn new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex {
567 let abi = CanonicalAbiInfo::record(
568 types
569 .iter()
570 .map(|ty| self.component_types.canonical_abi(ty)),
571 );
572 self.add_tuple_type(TypeTuple { types, abi })
573 }
574
575 fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
576 let flags = TypeFlags {
577 names: flags.iter().map(|s| s.to_string()).collect(),
578 abi: CanonicalAbiInfo::flags(flags.len()),
579 };
580 self.add_flags_type(flags)
581 }
582
583 fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
584 let names = variants
585 .iter()
586 .map(|s| s.to_string())
587 .collect::<IndexSet<_>>();
588 let (info, abi) = VariantInfo::new(names.iter().map(|_| None));
589 self.add_enum_type(TypeEnum { names, abi, info })
590 }
591
592 fn option_type(
593 &mut self,
594 types: TypesRef<'_>,
595 ty: &ComponentValType,
596 ) -> Result<TypeOptionIndex> {
597 assert_eq!(types.id(), self.module_types.validator_id());
598 let ty = self.valtype(types, ty)?;
599 let (info, abi) = VariantInfo::new([None, Some(self.component_types.canonical_abi(&ty))]);
600 Ok(self.add_option_type(TypeOption { ty, abi, info }))
601 }
602
603 fn result_type(
604 &mut self,
605 types: TypesRef<'_>,
606 ok: &Option<ComponentValType>,
607 err: &Option<ComponentValType>,
608 ) -> Result<TypeResultIndex> {
609 assert_eq!(types.id(), self.module_types.validator_id());
610 let ok = match ok {
611 Some(ty) => Some(self.valtype(types, ty)?),
612 None => None,
613 };
614 let err = match err {
615 Some(ty) => Some(self.valtype(types, ty)?),
616 None => None,
617 };
618 let (info, abi) = VariantInfo::new([
619 ok.as_ref().map(|t| self.component_types.canonical_abi(t)),
620 err.as_ref().map(|t| self.component_types.canonical_abi(t)),
621 ]);
622 Ok(self.add_result_type(TypeResult { ok, err, abi, info }))
623 }
624
625 fn future_table_type(
626 &mut self,
627 types: TypesRef<'_>,
628 ty: &Option<ComponentValType>,
629 ) -> Result<TypeFutureTableIndex> {
630 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
631 let ty = self.add_future_type(TypeFuture { payload });
632 Ok(self.add_future_table_type(TypeFutureTable {
633 ty,
634 instance: self.resources.get_current_instance().unwrap(),
635 }))
636 }
637
638 fn stream_table_type(
639 &mut self,
640 types: TypesRef<'_>,
641 ty: &Option<ComponentValType>,
642 ) -> Result<TypeStreamTableIndex> {
643 let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
644 let ty = self.add_stream_type(TypeStream { payload });
645 Ok(self.add_stream_table_type(TypeStreamTable {
646 ty,
647 instance: self.resources.get_current_instance().unwrap(),
648 }))
649 }
650
651 pub fn error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
654 Ok(self.add_error_context_table_type(TypeErrorContextTable {
655 instance: self.resources.get_current_instance().unwrap(),
656 }))
657 }
658
659 fn list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<TypeListIndex> {
660 assert_eq!(types.id(), self.module_types.validator_id());
661 let element = self.valtype(types, ty)?;
662 Ok(self.add_list_type(TypeList { element }))
663 }
664
665 pub fn resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex {
668 self.resources.convert(id, &mut self.component_types)
669 }
670
671 pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
673 intern(&mut self.functions, &mut self.component_types.functions, ty)
674 }
675
676 pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
678 intern_and_fill_flat_types!(self, records, ty)
679 }
680
681 pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
683 intern_and_fill_flat_types!(self, flags, ty)
684 }
685
686 pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
688 intern_and_fill_flat_types!(self, tuples, ty)
689 }
690
691 pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
693 intern_and_fill_flat_types!(self, variants, ty)
694 }
695
696 pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
698 intern_and_fill_flat_types!(self, enums, ty)
699 }
700
701 pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
703 intern_and_fill_flat_types!(self, options, ty)
704 }
705
706 pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
708 intern_and_fill_flat_types!(self, results, ty)
709 }
710
711 pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
713 intern_and_fill_flat_types!(self, lists, ty)
714 }
715
716 pub fn add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex {
718 intern(&mut self.futures, &mut self.component_types.futures, ty)
719 }
720
721 pub fn add_future_table_type(&mut self, ty: TypeFutureTable) -> TypeFutureTableIndex {
723 intern(
724 &mut self.future_tables,
725 &mut self.component_types.future_tables,
726 ty,
727 )
728 }
729
730 pub fn add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex {
732 intern(&mut self.streams, &mut self.component_types.streams, ty)
733 }
734
735 pub fn add_stream_table_type(&mut self, ty: TypeStreamTable) -> TypeStreamTableIndex {
737 intern(
738 &mut self.stream_tables,
739 &mut self.component_types.stream_tables,
740 ty,
741 )
742 }
743
744 pub fn add_error_context_table_type(
746 &mut self,
747 ty: TypeErrorContextTable,
748 ) -> TypeComponentLocalErrorContextTableIndex {
749 intern(
750 &mut self.error_context_tables,
751 &mut self.component_types.error_context_tables,
752 ty,
753 )
754 }
755
756 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
758 self.component_types.canonical_abi(ty)
759 }
760
761 pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
767 self.type_information(ty).flat.as_flat_types()
768 }
769
770 pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
773 self.type_information(ty).has_borrow
774 }
775
776 fn type_information(&self, ty: &InterfaceType) -> &TypeInformation {
777 match ty {
778 InterfaceType::U8
779 | InterfaceType::S8
780 | InterfaceType::Bool
781 | InterfaceType::U16
782 | InterfaceType::S16
783 | InterfaceType::U32
784 | InterfaceType::S32
785 | InterfaceType::Char
786 | InterfaceType::Own(_)
787 | InterfaceType::Future(_)
788 | InterfaceType::Stream(_)
789 | InterfaceType::ErrorContext(_) => {
790 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I32);
791 &INFO
792 }
793 InterfaceType::Borrow(_) => {
794 static INFO: TypeInformation = {
795 let mut info = TypeInformation::primitive(FlatType::I32);
796 info.has_borrow = true;
797 info
798 };
799 &INFO
800 }
801 InterfaceType::U64 | InterfaceType::S64 => {
802 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I64);
803 &INFO
804 }
805 InterfaceType::Float32 => {
806 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F32);
807 &INFO
808 }
809 InterfaceType::Float64 => {
810 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F64);
811 &INFO
812 }
813 InterfaceType::String => {
814 static INFO: TypeInformation = TypeInformation::string();
815 &INFO
816 }
817
818 InterfaceType::List(i) => &self.type_info.lists[*i],
819 InterfaceType::Record(i) => &self.type_info.records[*i],
820 InterfaceType::Variant(i) => &self.type_info.variants[*i],
821 InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
822 InterfaceType::Flags(i) => &self.type_info.flags[*i],
823 InterfaceType::Enum(i) => &self.type_info.enums[*i],
824 InterfaceType::Option(i) => &self.type_info.options[*i],
825 InterfaceType::Result(i) => &self.type_info.results[*i],
826 }
827 }
828}
829
830impl TypeConvert for ComponentTypesBuilder {
831 fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType {
832 panic!("heap types are not supported yet")
833 }
834
835 fn lookup_type_index(&self, _index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
836 panic!("typed references are not supported yet")
837 }
838}
839
840fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U
841where
842 T: Hash + Clone + Eq,
843 U: Copy + EntityRef,
844{
845 if let Some(idx) = map.get(&item) {
846 return *idx;
847 }
848 let idx = list.push(item.clone());
849 map.insert(item, idx);
850 return idx;
851}
852
853struct FlatTypesStorage {
854 memory32: [FlatType; MAX_FLAT_TYPES],
859 memory64: [FlatType; MAX_FLAT_TYPES],
860
861 len: u8,
865}
866
867impl FlatTypesStorage {
868 const fn new() -> FlatTypesStorage {
869 FlatTypesStorage {
870 memory32: [FlatType::I32; MAX_FLAT_TYPES],
871 memory64: [FlatType::I32; MAX_FLAT_TYPES],
872 len: 0,
873 }
874 }
875
876 fn as_flat_types(&self) -> Option<FlatTypes<'_>> {
877 let len = usize::from(self.len);
878 if len > MAX_FLAT_TYPES {
879 assert_eq!(len, MAX_FLAT_TYPES + 1);
880 None
881 } else {
882 Some(FlatTypes {
883 memory32: &self.memory32[..len],
884 memory64: &self.memory64[..len],
885 })
886 }
887 }
888
889 fn push(&mut self, t32: FlatType, t64: FlatType) -> bool {
896 let len = usize::from(self.len);
897 if len < MAX_FLAT_TYPES {
898 self.memory32[len] = t32;
899 self.memory64[len] = t64;
900 self.len += 1;
901 true
902 } else {
903 if len == MAX_FLAT_TYPES {
906 self.len += 1;
907 }
908 false
909 }
910 }
911}
912
913impl FlatType {
914 fn join(&mut self, other: FlatType) {
915 if *self == other {
916 return;
917 }
918 *self = match (*self, other) {
919 (FlatType::I32, FlatType::F32) | (FlatType::F32, FlatType::I32) => FlatType::I32,
920 _ => FlatType::I64,
921 };
922 }
923}
924
925#[derive(Default)]
926struct TypeInformationCache {
927 records: PrimaryMap<TypeRecordIndex, TypeInformation>,
928 variants: PrimaryMap<TypeVariantIndex, TypeInformation>,
929 tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
930 enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
931 flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
932 options: PrimaryMap<TypeOptionIndex, TypeInformation>,
933 results: PrimaryMap<TypeResultIndex, TypeInformation>,
934 lists: PrimaryMap<TypeListIndex, TypeInformation>,
935}
936
937struct TypeInformation {
938 depth: u32,
939 flat: FlatTypesStorage,
940 has_borrow: bool,
941}
942
943impl TypeInformation {
944 const fn new() -> TypeInformation {
945 TypeInformation {
946 depth: 0,
947 flat: FlatTypesStorage::new(),
948 has_borrow: false,
949 }
950 }
951
952 const fn primitive(flat: FlatType) -> TypeInformation {
953 let mut info = TypeInformation::new();
954 info.depth = 1;
955 info.flat.memory32[0] = flat;
956 info.flat.memory64[0] = flat;
957 info.flat.len = 1;
958 info
959 }
960
961 const fn string() -> TypeInformation {
962 let mut info = TypeInformation::new();
963 info.depth = 1;
964 info.flat.memory32[0] = FlatType::I32;
965 info.flat.memory32[1] = FlatType::I32;
966 info.flat.memory64[0] = FlatType::I64;
967 info.flat.memory64[1] = FlatType::I64;
968 info.flat.len = 2;
969 info
970 }
971
972 fn build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>) {
975 self.depth = 1;
976 for info in types {
977 self.depth = self.depth.max(1 + info.depth);
978 self.has_borrow = self.has_borrow || info.has_borrow;
979 match info.flat.as_flat_types() {
980 Some(types) => {
981 for (t32, t64) in types.memory32.iter().zip(types.memory64) {
982 if !self.flat.push(*t32, *t64) {
983 break;
984 }
985 }
986 }
987 None => {
988 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
989 }
990 }
991 }
992 }
993
994 fn build_variant<'a, I>(&mut self, cases: I)
1006 where
1007 I: IntoIterator<Item = Option<&'a TypeInformation>>,
1008 {
1009 let cases = cases.into_iter();
1010 self.flat.push(FlatType::I32, FlatType::I32);
1011 self.depth = 1;
1012
1013 for info in cases {
1014 let info = match info {
1015 Some(info) => info,
1016 None => continue,
1019 };
1020 self.depth = self.depth.max(1 + info.depth);
1021 self.has_borrow = self.has_borrow || info.has_borrow;
1022
1023 if usize::from(self.flat.len) > MAX_FLAT_TYPES {
1026 continue;
1027 }
1028
1029 let types = match info.flat.as_flat_types() {
1030 Some(types) => types,
1031 None => {
1034 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1035 continue;
1036 }
1037 };
1038 if types.memory32.len() >= MAX_FLAT_TYPES {
1042 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1043 continue;
1044 }
1045 let dst = self
1046 .flat
1047 .memory32
1048 .iter_mut()
1049 .zip(&mut self.flat.memory64)
1050 .skip(1);
1051 for (i, ((t32, t64), (dst32, dst64))) in types
1052 .memory32
1053 .iter()
1054 .zip(types.memory64)
1055 .zip(dst)
1056 .enumerate()
1057 {
1058 if i + 1 < usize::from(self.flat.len) {
1059 dst32.join(*t32);
1062 dst64.join(*t64);
1063 } else {
1064 self.flat.len += 1;
1069 *dst32 = *t32;
1070 *dst64 = *t64;
1071 }
1072 }
1073 }
1074 }
1075
1076 fn records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord) {
1077 self.build_record(ty.fields.iter().map(|f| types.type_information(&f.ty)));
1078 }
1079
1080 fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
1081 self.build_record(ty.types.iter().map(|t| types.type_information(t)));
1082 }
1083
1084 fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
1085 self.depth = 1;
1086 self.flat.push(FlatType::I32, FlatType::I32);
1087 }
1088
1089 fn flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags) {
1090 self.depth = 1;
1091 match FlagsSize::from_count(ty.names.len()) {
1092 FlagsSize::Size0 => {}
1093 FlagsSize::Size1 | FlagsSize::Size2 => {
1094 self.flat.push(FlatType::I32, FlatType::I32);
1095 }
1096 FlagsSize::Size4Plus(n) => {
1097 for _ in 0..n {
1098 self.flat.push(FlatType::I32, FlatType::I32);
1099 }
1100 }
1101 }
1102 }
1103
1104 fn variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant) {
1105 self.build_variant(
1106 ty.cases
1107 .iter()
1108 .map(|(_, c)| c.as_ref().map(|ty| types.type_information(ty))),
1109 )
1110 }
1111
1112 fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
1113 self.build_variant([
1114 ty.ok.as_ref().map(|ty| types.type_information(ty)),
1115 ty.err.as_ref().map(|ty| types.type_information(ty)),
1116 ])
1117 }
1118
1119 fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
1120 self.build_variant([None, Some(types.type_information(&ty.ty))]);
1121 }
1122
1123 fn lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList) {
1124 *self = TypeInformation::string();
1125 let info = types.type_information(&ty.element);
1126 self.depth += info.depth;
1127 self.has_borrow = info.has_borrow;
1128 }
1129}