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