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