1use crate::component::*;
2use crate::prelude::*;
3use crate::{
4 EntityType, Module, ModuleTypes, ModuleTypesBuilder, PrimaryMap, TypeConvert, WasmHeapType,
5 WasmValType,
6};
7use anyhow::{bail, Result};
8use cranelift_entity::EntityRef;
9use std::collections::HashMap;
10use std::hash::Hash;
11use std::ops::Index;
12use wasmparser::names::KebabString;
13use wasmparser::{types, Validator};
14use wasmtime_component_util::FlagsSize;
15use wasmtime_types::ModuleInternedTypeIndex;
16
17mod resources;
18pub use resources::ResourcesBuilder;
19
20const MAX_TYPE_DEPTH: u32 = 100;
28
29pub struct ComponentTypesBuilder {
34 functions: HashMap<TypeFunc, TypeFuncIndex>,
35 lists: HashMap<TypeList, TypeListIndex>,
36 records: HashMap<TypeRecord, TypeRecordIndex>,
37 variants: HashMap<TypeVariant, TypeVariantIndex>,
38 tuples: HashMap<TypeTuple, TypeTupleIndex>,
39 enums: HashMap<TypeEnum, TypeEnumIndex>,
40 flags: HashMap<TypeFlags, TypeFlagsIndex>,
41 options: HashMap<TypeOption, TypeOptionIndex>,
42 results: HashMap<TypeResult, TypeResultIndex>,
43
44 component_types: ComponentTypes,
45 module_types: ModuleTypesBuilder,
46
47 type_info: TypeInformationCache,
51
52 resources: ResourcesBuilder,
53}
54
55impl<T> Index<T> for ComponentTypesBuilder
56where
57 ModuleTypes: Index<T>,
58{
59 type Output = <ModuleTypes as Index<T>>::Output;
60 fn index(&self, idx: T) -> &Self::Output {
61 self.module_types.index(idx)
62 }
63}
64
65macro_rules! intern_and_fill_flat_types {
66 ($me:ident, $name:ident, $val:ident) => {{
67 if let Some(idx) = $me.$name.get(&$val) {
68 return *idx;
69 }
70 let idx = $me.component_types.$name.push($val.clone());
71 let mut info = TypeInformation::new();
72 info.$name($me, &$val);
73 let idx2 = $me.type_info.$name.push(info);
74 assert_eq!(idx, idx2);
75 $me.$name.insert($val, idx);
76 return idx;
77 }};
78}
79
80impl ComponentTypesBuilder {
81 pub fn new(validator: &Validator) -> Self {
83 Self {
84 module_types: ModuleTypesBuilder::new(validator),
85
86 functions: HashMap::default(),
87 lists: HashMap::default(),
88 records: HashMap::default(),
89 variants: HashMap::default(),
90 tuples: HashMap::default(),
91 enums: HashMap::default(),
92 flags: HashMap::default(),
93 options: HashMap::default(),
94 results: HashMap::default(),
95 component_types: ComponentTypes::default(),
96 type_info: TypeInformationCache::default(),
97 resources: ResourcesBuilder::default(),
98 }
99 }
100
101 fn export_type_def(
102 &mut self,
103 export_items: &PrimaryMap<ExportIndex, Export>,
104 idx: ExportIndex,
105 ) -> TypeDef {
106 match &export_items[idx] {
107 Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(*ty),
108 Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
109 TypeDef::Module(*ty)
110 }
111 Export::Instance { ty, .. } => TypeDef::ComponentInstance(*ty),
112 Export::Type(ty) => *ty,
113 }
114 }
115
116 pub fn finish(mut self, component: &Component) -> (ComponentTypes, TypeComponentIndex) {
120 let mut component_ty = TypeComponent::default();
121 for (_, (name, ty)) in component.import_types.iter() {
122 component_ty.imports.insert(name.clone(), *ty);
123 }
124 for (name, ty) in component.exports.raw_iter() {
125 component_ty.exports.insert(
126 name.clone(),
127 self.export_type_def(&component.export_items, *ty),
128 );
129 }
130 let ty = self.component_types.components.push(component_ty);
131
132 self.component_types.module_types = Some(self.module_types.finish());
133 (self.component_types, ty)
134 }
135
136 pub fn find_resource_drop_signature(&self) -> Option<ModuleInternedTypeIndex> {
146 self.module_types
147 .wasm_types()
148 .find(|(_, ty)| {
149 ty.as_func().map_or(false, |sig| {
150 sig.params().len() == 1
151 && sig.returns().len() == 0
152 && sig.params()[0] == WasmValType::I32
153 })
154 })
155 .map(|(i, _)| i)
156 }
157
158 pub fn module_types_builder(&self) -> &ModuleTypesBuilder {
163 &self.module_types
164 }
165
166 pub fn module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder {
168 &mut self.module_types
169 }
170
171 pub(super) fn component_types(&self) -> &ComponentTypes {
173 &self.component_types
174 }
175
176 pub fn num_resource_tables(&self) -> usize {
179 self.component_types.resource_tables.len()
180 }
181
182 pub fn resources_mut(&mut self) -> &mut ResourcesBuilder {
184 &mut self.resources
185 }
186
187 pub fn resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes) {
190 (&mut self.resources, &self.component_types)
191 }
192
193 pub fn convert_component_func_type(
196 &mut self,
197 types: types::TypesRef<'_>,
198 id: types::ComponentFuncTypeId,
199 ) -> Result<TypeFuncIndex> {
200 assert_eq!(types.id(), self.module_types.validator_id());
201 let ty = &types[id];
202 let params = ty
203 .params
204 .iter()
205 .map(|(_name, ty)| self.valtype(types, ty))
206 .collect::<Result<_>>()?;
207 let results = ty
208 .results
209 .iter()
210 .map(|(_name, ty)| self.valtype(types, ty))
211 .collect::<Result<_>>()?;
212 let ty = TypeFunc {
213 params: self.new_tuple_type(params),
214 results: self.new_tuple_type(results),
215 };
216 Ok(self.add_func_type(ty))
217 }
218
219 pub fn convert_component_entity_type(
222 &mut self,
223 types: types::TypesRef<'_>,
224 ty: types::ComponentEntityType,
225 ) -> Result<TypeDef> {
226 assert_eq!(types.id(), self.module_types.validator_id());
227 Ok(match ty {
228 types::ComponentEntityType::Module(id) => {
229 TypeDef::Module(self.convert_module(types, id)?)
230 }
231 types::ComponentEntityType::Component(id) => {
232 TypeDef::Component(self.convert_component(types, id)?)
233 }
234 types::ComponentEntityType::Instance(id) => {
235 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
236 }
237 types::ComponentEntityType::Func(id) => {
238 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
239 }
240 types::ComponentEntityType::Type { created, .. } => match created {
241 types::ComponentAnyTypeId::Defined(id) => {
242 TypeDef::Interface(self.defined_type(types, id)?)
243 }
244 types::ComponentAnyTypeId::Resource(id) => {
245 TypeDef::Resource(self.resource_id(id.resource()))
246 }
247 _ => bail!("unsupported type export"),
248 },
249 types::ComponentEntityType::Value(_) => bail!("values not supported"),
250 })
251 }
252
253 pub fn convert_type(
255 &mut self,
256 types: types::TypesRef<'_>,
257 id: types::ComponentAnyTypeId,
258 ) -> Result<TypeDef> {
259 assert_eq!(types.id(), self.module_types.validator_id());
260 Ok(match id {
261 types::ComponentAnyTypeId::Defined(id) => {
262 TypeDef::Interface(self.defined_type(types, id)?)
263 }
264 types::ComponentAnyTypeId::Component(id) => {
265 TypeDef::Component(self.convert_component(types, id)?)
266 }
267 types::ComponentAnyTypeId::Instance(id) => {
268 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
269 }
270 types::ComponentAnyTypeId::Func(id) => {
271 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
272 }
273 types::ComponentAnyTypeId::Resource(id) => {
274 TypeDef::Resource(self.resource_id(id.resource()))
275 }
276 })
277 }
278
279 fn convert_component(
280 &mut self,
281 types: types::TypesRef<'_>,
282 id: types::ComponentTypeId,
283 ) -> Result<TypeComponentIndex> {
284 assert_eq!(types.id(), self.module_types.validator_id());
285 let ty = &types[id];
286 let mut result = TypeComponent::default();
287 for (name, ty) in ty.imports.iter() {
288 result.imports.insert(
289 name.clone(),
290 self.convert_component_entity_type(types, *ty)?,
291 );
292 }
293 for (name, ty) in ty.exports.iter() {
294 result.exports.insert(
295 name.clone(),
296 self.convert_component_entity_type(types, *ty)?,
297 );
298 }
299 Ok(self.component_types.components.push(result))
300 }
301
302 pub(crate) fn convert_instance(
303 &mut self,
304 types: types::TypesRef<'_>,
305 id: types::ComponentInstanceTypeId,
306 ) -> Result<TypeComponentInstanceIndex> {
307 assert_eq!(types.id(), self.module_types.validator_id());
308 let ty = &types[id];
309 let mut result = TypeComponentInstance::default();
310 for (name, ty) in ty.exports.iter() {
311 result.exports.insert(
312 name.clone(),
313 self.convert_component_entity_type(types, *ty)?,
314 );
315 }
316 Ok(self.component_types.component_instances.push(result))
317 }
318
319 pub(crate) fn convert_module(
320 &mut self,
321 types: types::TypesRef<'_>,
322 id: types::ComponentCoreModuleTypeId,
323 ) -> Result<TypeModuleIndex> {
324 assert_eq!(types.id(), self.module_types.validator_id());
325 let ty = &types[id];
326 let mut result = TypeModule::default();
327 for ((module, field), ty) in ty.imports.iter() {
328 result.imports.insert(
329 (module.clone(), field.clone()),
330 self.entity_type(types, ty)?,
331 );
332 }
333 for (name, ty) in ty.exports.iter() {
334 result
335 .exports
336 .insert(name.clone(), self.entity_type(types, ty)?);
337 }
338 Ok(self.component_types.modules.push(result))
339 }
340
341 fn entity_type(
342 &mut self,
343 types: types::TypesRef<'_>,
344 ty: &types::EntityType,
345 ) -> Result<EntityType> {
346 assert_eq!(types.id(), self.module_types.validator_id());
347 Ok(match ty {
348 types::EntityType::Func(id) => EntityType::Function({
349 let module = Module::default();
350 self.module_types_builder_mut()
351 .intern_type(&module, types, *id)?
352 .into()
353 }),
354 types::EntityType::Table(ty) => EntityType::Table(self.convert_table_type(ty)?),
355 types::EntityType::Memory(ty) => EntityType::Memory((*ty).into()),
356 types::EntityType::Global(ty) => EntityType::Global(self.convert_global_type(ty)),
357 types::EntityType::Tag(_) => bail!("exceptions proposal not implemented"),
358 })
359 }
360
361 fn defined_type(
362 &mut self,
363 types: types::TypesRef<'_>,
364 id: types::ComponentDefinedTypeId,
365 ) -> Result<InterfaceType> {
366 assert_eq!(types.id(), self.module_types.validator_id());
367 let ret = match &types[id] {
368 types::ComponentDefinedType::Primitive(ty) => ty.into(),
369 types::ComponentDefinedType::Record(e) => {
370 InterfaceType::Record(self.record_type(types, e)?)
371 }
372 types::ComponentDefinedType::Variant(e) => {
373 InterfaceType::Variant(self.variant_type(types, e)?)
374 }
375 types::ComponentDefinedType::List(e) => InterfaceType::List(self.list_type(types, e)?),
376 types::ComponentDefinedType::Tuple(e) => {
377 InterfaceType::Tuple(self.tuple_type(types, e)?)
378 }
379 types::ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
380 types::ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
381 types::ComponentDefinedType::Option(e) => {
382 InterfaceType::Option(self.option_type(types, e)?)
383 }
384 types::ComponentDefinedType::Result { ok, err } => {
385 InterfaceType::Result(self.result_type(types, ok, err)?)
386 }
387 types::ComponentDefinedType::Own(r) => {
388 InterfaceType::Own(self.resource_id(r.resource()))
389 }
390 types::ComponentDefinedType::Borrow(r) => {
391 InterfaceType::Borrow(self.resource_id(r.resource()))
392 }
393 };
394 let info = self.type_information(&ret);
395 if info.depth > MAX_TYPE_DEPTH {
396 bail!("type nesting is too deep");
397 }
398 Ok(ret)
399 }
400
401 fn valtype(
402 &mut self,
403 types: types::TypesRef<'_>,
404 ty: &types::ComponentValType,
405 ) -> Result<InterfaceType> {
406 assert_eq!(types.id(), self.module_types.validator_id());
407 match ty {
408 types::ComponentValType::Primitive(p) => Ok(p.into()),
409 types::ComponentValType::Type(id) => self.defined_type(types, *id),
410 }
411 }
412
413 fn record_type(
414 &mut self,
415 types: types::TypesRef<'_>,
416 ty: &types::RecordType,
417 ) -> Result<TypeRecordIndex> {
418 assert_eq!(types.id(), self.module_types.validator_id());
419 let fields = ty
420 .fields
421 .iter()
422 .map(|(name, ty)| {
423 Ok(RecordField {
424 name: name.to_string(),
425 ty: self.valtype(types, ty)?,
426 })
427 })
428 .collect::<Result<Box<[_]>>>()?;
429 let abi = CanonicalAbiInfo::record(
430 fields
431 .iter()
432 .map(|field| self.component_types.canonical_abi(&field.ty)),
433 );
434 Ok(self.add_record_type(TypeRecord { fields, abi }))
435 }
436
437 fn variant_type(
438 &mut self,
439 types: types::TypesRef<'_>,
440 ty: &types::VariantType,
441 ) -> Result<TypeVariantIndex> {
442 assert_eq!(types.id(), self.module_types.validator_id());
443 let cases = ty
444 .cases
445 .iter()
446 .map(|(name, case)| {
447 if case.refines.is_some() {
450 bail!("refines is not supported at this time");
451 }
452 Ok((
453 name.to_string(),
454 match &case.ty.as_ref() {
455 Some(ty) => Some(self.valtype(types, ty)?),
456 None => None,
457 },
458 ))
459 })
460 .collect::<Result<IndexMap<_, _>>>()?;
461 let (info, abi) = VariantInfo::new(
462 cases
463 .iter()
464 .map(|(_, c)| c.as_ref().map(|ty| self.component_types.canonical_abi(ty))),
465 );
466 Ok(self.add_variant_type(TypeVariant { cases, abi, info }))
467 }
468
469 fn tuple_type(
470 &mut self,
471 types: types::TypesRef<'_>,
472 ty: &types::TupleType,
473 ) -> Result<TypeTupleIndex> {
474 assert_eq!(types.id(), self.module_types.validator_id());
475 let types = ty
476 .types
477 .iter()
478 .map(|ty| self.valtype(types, ty))
479 .collect::<Result<Box<[_]>>>()?;
480 Ok(self.new_tuple_type(types))
481 }
482
483 fn new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex {
484 let abi = CanonicalAbiInfo::record(
485 types
486 .iter()
487 .map(|ty| self.component_types.canonical_abi(ty)),
488 );
489 self.add_tuple_type(TypeTuple { types, abi })
490 }
491
492 fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
493 let flags = TypeFlags {
494 names: flags.iter().map(|s| s.to_string()).collect(),
495 abi: CanonicalAbiInfo::flags(flags.len()),
496 };
497 self.add_flags_type(flags)
498 }
499
500 fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
501 let names = variants
502 .iter()
503 .map(|s| s.to_string())
504 .collect::<IndexSet<_>>();
505 let (info, abi) = VariantInfo::new(names.iter().map(|_| None));
506 self.add_enum_type(TypeEnum { names, abi, info })
507 }
508
509 fn option_type(
510 &mut self,
511 types: types::TypesRef<'_>,
512 ty: &types::ComponentValType,
513 ) -> Result<TypeOptionIndex> {
514 assert_eq!(types.id(), self.module_types.validator_id());
515 let ty = self.valtype(types, ty)?;
516 let (info, abi) = VariantInfo::new([None, Some(self.component_types.canonical_abi(&ty))]);
517 Ok(self.add_option_type(TypeOption { ty, abi, info }))
518 }
519
520 fn result_type(
521 &mut self,
522 types: types::TypesRef<'_>,
523 ok: &Option<types::ComponentValType>,
524 err: &Option<types::ComponentValType>,
525 ) -> Result<TypeResultIndex> {
526 assert_eq!(types.id(), self.module_types.validator_id());
527 let ok = match ok {
528 Some(ty) => Some(self.valtype(types, ty)?),
529 None => None,
530 };
531 let err = match err {
532 Some(ty) => Some(self.valtype(types, ty)?),
533 None => None,
534 };
535 let (info, abi) = VariantInfo::new([
536 ok.as_ref().map(|t| self.component_types.canonical_abi(t)),
537 err.as_ref().map(|t| self.component_types.canonical_abi(t)),
538 ]);
539 Ok(self.add_result_type(TypeResult { ok, err, abi, info }))
540 }
541
542 fn list_type(
543 &mut self,
544 types: types::TypesRef<'_>,
545 ty: &types::ComponentValType,
546 ) -> Result<TypeListIndex> {
547 assert_eq!(types.id(), self.module_types.validator_id());
548 let element = self.valtype(types, ty)?;
549 Ok(self.add_list_type(TypeList { element }))
550 }
551
552 pub fn resource_id(&mut self, id: types::ResourceId) -> TypeResourceTableIndex {
555 self.resources.convert(id, &mut self.component_types)
556 }
557
558 pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
560 intern(&mut self.functions, &mut self.component_types.functions, ty)
561 }
562
563 pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
565 intern_and_fill_flat_types!(self, records, ty)
566 }
567
568 pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
570 intern_and_fill_flat_types!(self, flags, ty)
571 }
572
573 pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
575 intern_and_fill_flat_types!(self, tuples, ty)
576 }
577
578 pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
580 intern_and_fill_flat_types!(self, variants, ty)
581 }
582
583 pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
585 intern_and_fill_flat_types!(self, enums, ty)
586 }
587
588 pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
590 intern_and_fill_flat_types!(self, options, ty)
591 }
592
593 pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
595 intern_and_fill_flat_types!(self, results, ty)
596 }
597
598 pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
600 intern_and_fill_flat_types!(self, lists, ty)
601 }
602
603 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
605 self.component_types.canonical_abi(ty)
606 }
607
608 pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
614 self.type_information(ty).flat.as_flat_types()
615 }
616
617 pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
620 self.type_information(ty).has_borrow
621 }
622
623 fn type_information(&self, ty: &InterfaceType) -> &TypeInformation {
624 match ty {
625 InterfaceType::U8
626 | InterfaceType::S8
627 | InterfaceType::Bool
628 | InterfaceType::U16
629 | InterfaceType::S16
630 | InterfaceType::U32
631 | InterfaceType::S32
632 | InterfaceType::Char
633 | InterfaceType::Own(_) => {
634 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I32);
635 &INFO
636 }
637 InterfaceType::Borrow(_) => {
638 static INFO: TypeInformation = {
639 let mut info = TypeInformation::primitive(FlatType::I32);
640 info.has_borrow = true;
641 info
642 };
643 &INFO
644 }
645 InterfaceType::U64 | InterfaceType::S64 => {
646 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I64);
647 &INFO
648 }
649 InterfaceType::Float32 => {
650 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F32);
651 &INFO
652 }
653 InterfaceType::Float64 => {
654 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F64);
655 &INFO
656 }
657 InterfaceType::String => {
658 static INFO: TypeInformation = TypeInformation::string();
659 &INFO
660 }
661
662 InterfaceType::List(i) => &self.type_info.lists[*i],
663 InterfaceType::Record(i) => &self.type_info.records[*i],
664 InterfaceType::Variant(i) => &self.type_info.variants[*i],
665 InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
666 InterfaceType::Flags(i) => &self.type_info.flags[*i],
667 InterfaceType::Enum(i) => &self.type_info.enums[*i],
668 InterfaceType::Option(i) => &self.type_info.options[*i],
669 InterfaceType::Result(i) => &self.type_info.results[*i],
670 }
671 }
672}
673
674impl TypeConvert for ComponentTypesBuilder {
675 fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType {
676 panic!("heap types are not supported yet")
677 }
678
679 fn lookup_type_index(
680 &self,
681 _index: wasmparser::UnpackedIndex,
682 ) -> wasmtime_types::EngineOrModuleTypeIndex {
683 panic!("typed references are not supported yet")
684 }
685}
686
687fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U
688where
689 T: Hash + Clone + Eq,
690 U: Copy + EntityRef,
691{
692 if let Some(idx) = map.get(&item) {
693 return *idx;
694 }
695 let idx = list.push(item.clone());
696 map.insert(item, idx);
697 return idx;
698}
699
700struct FlatTypesStorage {
701 memory32: [FlatType; MAX_FLAT_TYPES],
706 memory64: [FlatType; MAX_FLAT_TYPES],
707
708 len: u8,
712}
713
714impl FlatTypesStorage {
715 const fn new() -> FlatTypesStorage {
716 FlatTypesStorage {
717 memory32: [FlatType::I32; MAX_FLAT_TYPES],
718 memory64: [FlatType::I32; MAX_FLAT_TYPES],
719 len: 0,
720 }
721 }
722
723 fn as_flat_types(&self) -> Option<FlatTypes<'_>> {
724 let len = usize::from(self.len);
725 if len > MAX_FLAT_TYPES {
726 assert_eq!(len, MAX_FLAT_TYPES + 1);
727 None
728 } else {
729 Some(FlatTypes {
730 memory32: &self.memory32[..len],
731 memory64: &self.memory64[..len],
732 })
733 }
734 }
735
736 fn push(&mut self, t32: FlatType, t64: FlatType) -> bool {
743 let len = usize::from(self.len);
744 if len < MAX_FLAT_TYPES {
745 self.memory32[len] = t32;
746 self.memory64[len] = t64;
747 self.len += 1;
748 true
749 } else {
750 if len == MAX_FLAT_TYPES {
753 self.len += 1;
754 }
755 false
756 }
757 }
758}
759
760impl FlatType {
761 fn join(&mut self, other: FlatType) {
762 if *self == other {
763 return;
764 }
765 *self = match (*self, other) {
766 (FlatType::I32, FlatType::F32) | (FlatType::F32, FlatType::I32) => FlatType::I32,
767 _ => FlatType::I64,
768 };
769 }
770}
771
772#[derive(Default)]
773struct TypeInformationCache {
774 records: PrimaryMap<TypeRecordIndex, TypeInformation>,
775 variants: PrimaryMap<TypeVariantIndex, TypeInformation>,
776 tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
777 enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
778 flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
779 options: PrimaryMap<TypeOptionIndex, TypeInformation>,
780 results: PrimaryMap<TypeResultIndex, TypeInformation>,
781 lists: PrimaryMap<TypeListIndex, TypeInformation>,
782}
783
784struct TypeInformation {
785 depth: u32,
786 flat: FlatTypesStorage,
787 has_borrow: bool,
788}
789
790impl TypeInformation {
791 const fn new() -> TypeInformation {
792 TypeInformation {
793 depth: 0,
794 flat: FlatTypesStorage::new(),
795 has_borrow: false,
796 }
797 }
798
799 const fn primitive(flat: FlatType) -> TypeInformation {
800 let mut info = TypeInformation::new();
801 info.depth = 1;
802 info.flat.memory32[0] = flat;
803 info.flat.memory64[0] = flat;
804 info.flat.len = 1;
805 info
806 }
807
808 const fn string() -> TypeInformation {
809 let mut info = TypeInformation::new();
810 info.depth = 1;
811 info.flat.memory32[0] = FlatType::I32;
812 info.flat.memory32[1] = FlatType::I32;
813 info.flat.memory64[0] = FlatType::I64;
814 info.flat.memory64[1] = FlatType::I64;
815 info.flat.len = 2;
816 info
817 }
818
819 fn build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>) {
822 self.depth = 1;
823 for info in types {
824 self.depth = self.depth.max(1 + info.depth);
825 self.has_borrow = self.has_borrow || info.has_borrow;
826 match info.flat.as_flat_types() {
827 Some(types) => {
828 for (t32, t64) in types.memory32.iter().zip(types.memory64) {
829 if !self.flat.push(*t32, *t64) {
830 break;
831 }
832 }
833 }
834 None => {
835 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
836 }
837 }
838 }
839 }
840
841 fn build_variant<'a, I>(&mut self, cases: I)
853 where
854 I: IntoIterator<Item = Option<&'a TypeInformation>>,
855 {
856 let cases = cases.into_iter();
857 self.flat.push(FlatType::I32, FlatType::I32);
858 self.depth = 1;
859
860 for info in cases {
861 let info = match info {
862 Some(info) => info,
863 None => continue,
866 };
867 self.depth = self.depth.max(1 + info.depth);
868 self.has_borrow = self.has_borrow || info.has_borrow;
869
870 if usize::from(self.flat.len) > MAX_FLAT_TYPES {
873 continue;
874 }
875
876 let types = match info.flat.as_flat_types() {
877 Some(types) => types,
878 None => {
881 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
882 continue;
883 }
884 };
885 if types.memory32.len() >= MAX_FLAT_TYPES {
889 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
890 continue;
891 }
892 let dst = self
893 .flat
894 .memory32
895 .iter_mut()
896 .zip(&mut self.flat.memory64)
897 .skip(1);
898 for (i, ((t32, t64), (dst32, dst64))) in types
899 .memory32
900 .iter()
901 .zip(types.memory64)
902 .zip(dst)
903 .enumerate()
904 {
905 if i + 1 < usize::from(self.flat.len) {
906 dst32.join(*t32);
909 dst64.join(*t64);
910 } else {
911 self.flat.len += 1;
916 *dst32 = *t32;
917 *dst64 = *t64;
918 }
919 }
920 }
921 }
922
923 fn records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord) {
924 self.build_record(ty.fields.iter().map(|f| types.type_information(&f.ty)));
925 }
926
927 fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
928 self.build_record(ty.types.iter().map(|t| types.type_information(t)));
929 }
930
931 fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
932 self.depth = 1;
933 self.flat.push(FlatType::I32, FlatType::I32);
934 }
935
936 fn flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags) {
937 self.depth = 1;
938 match FlagsSize::from_count(ty.names.len()) {
939 FlagsSize::Size0 => {}
940 FlagsSize::Size1 | FlagsSize::Size2 => {
941 self.flat.push(FlatType::I32, FlatType::I32);
942 }
943 FlagsSize::Size4Plus(n) => {
944 for _ in 0..n {
945 self.flat.push(FlatType::I32, FlatType::I32);
946 }
947 }
948 }
949 }
950
951 fn variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant) {
952 self.build_variant(
953 ty.cases
954 .iter()
955 .map(|(_, c)| c.as_ref().map(|ty| types.type_information(ty))),
956 )
957 }
958
959 fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
960 self.build_variant([
961 ty.ok.as_ref().map(|ty| types.type_information(ty)),
962 ty.err.as_ref().map(|ty| types.type_information(ty)),
963 ])
964 }
965
966 fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
967 self.build_variant([None, Some(types.type_information(&ty.ty))]);
968 }
969
970 fn lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList) {
971 *self = TypeInformation::string();
972 let info = types.type_information(&ty.element);
973 self.depth += info.depth;
974 self.has_borrow = info.has_borrow;
975 }
976}