1 use crate::component::*;
2 use crate::error::{Result, bail};
3 use crate::prelude::*;
4 use crate::{
5     EngineOrModuleTypeIndex, EntityType, ModuleInternedTypeIndex, ModuleTypes, ModuleTypesBuilder,
6     PrimaryMap, TypeConvert, WasmHeapType, WasmValType,
7 };
8 use cranelift_entity::EntityRef;
9 use std::collections::HashMap;
10 use std::hash::Hash;
11 use std::ops::Index;
12 use wasmparser::component_types::{
13     ComponentAnyTypeId, ComponentCoreModuleTypeId, ComponentDefinedType, ComponentDefinedTypeId,
14     ComponentEntityType, ComponentFuncTypeId, ComponentInstanceTypeId, ComponentTypeId,
15     ComponentValType, RecordType, ResourceId, TupleType, VariantType,
16 };
17 use wasmparser::names::KebabString;
18 use wasmparser::types::TypesRef;
19 use wasmparser::{PrimitiveValType, Validator};
20 use wasmtime_component_util::FlagsSize;
21 
22 mod resources;
23 pub use resources::ResourcesBuilder;
24 
25 /// Maximum nesting depth of a type allowed in Wasmtime.
26 ///
27 /// This constant isn't chosen via any scientific means and its main purpose is
28 /// to enable most of Wasmtime to handle types via recursion without worrying
29 /// about stack overflow.
30 ///
31 /// Some more information about this can be found in #4814
32 const MAX_TYPE_DEPTH: u32 = 100;
33 
34 /// Structure used to build a [`ComponentTypes`] during translation.
35 ///
36 /// This contains tables to intern any component types found as well as
37 /// managing building up core wasm [`ModuleTypes`] as well.
38 pub struct ComponentTypesBuilder {
39     functions: HashMap<TypeFunc, TypeFuncIndex>,
40     lists: HashMap<TypeList, TypeListIndex>,
41     maps: HashMap<TypeMap, TypeMapIndex>,
42     records: HashMap<TypeRecord, TypeRecordIndex>,
43     variants: HashMap<TypeVariant, TypeVariantIndex>,
44     tuples: HashMap<TypeTuple, TypeTupleIndex>,
45     enums: HashMap<TypeEnum, TypeEnumIndex>,
46     flags: HashMap<TypeFlags, TypeFlagsIndex>,
47     options: HashMap<TypeOption, TypeOptionIndex>,
48     results: HashMap<TypeResult, TypeResultIndex>,
49     futures: HashMap<TypeFuture, TypeFutureIndex>,
50     streams: HashMap<TypeStream, TypeStreamIndex>,
51     future_tables: HashMap<TypeFutureTable, TypeFutureTableIndex>,
52     stream_tables: HashMap<TypeStreamTable, TypeStreamTableIndex>,
53     error_context_tables: HashMap<TypeErrorContextTable, TypeComponentLocalErrorContextTableIndex>,
54     fixed_length_lists: HashMap<TypeFixedLengthList, TypeFixedLengthListIndex>,
55 
56     component_types: ComponentTypes,
57     module_types: ModuleTypesBuilder,
58 
59     // Cache of what the "flat" representation of all types are which is only
60     // used at compile-time and not used at runtime, hence the location here
61     // as opposed to `ComponentTypes`.
62     type_info: TypeInformationCache,
63 
64     resources: ResourcesBuilder,
65 
66     // Total number of abstract resources allocated.
67     //
68     // These are only allocated within component and instance types when
69     // translating them.
70     abstract_resources: u32,
71 }
72 
73 impl<T> Index<T> for ComponentTypesBuilder
74 where
75     ModuleTypes: Index<T>,
76 {
77     type Output = <ModuleTypes as Index<T>>::Output;
index(&self, idx: T) -> &Self::Output78     fn index(&self, idx: T) -> &Self::Output {
79         self.module_types.index(idx)
80     }
81 }
82 
83 macro_rules! intern_and_fill_flat_types {
84     ($me:ident, $name:ident, $val:ident) => {{
85         if let Some(idx) = $me.$name.get(&$val) {
86             *idx
87         } else {
88             let idx = $me.component_types.$name.push($val.clone());
89             let mut info = TypeInformation::new();
90             info.$name($me, &$val);
91             let idx2 = $me.type_info.$name.push(info);
92             assert_eq!(idx, idx2);
93             $me.$name.insert($val, idx);
94             idx
95         }
96     }};
97 }
98 
99 impl ComponentTypesBuilder {
100     /// Construct a new `ComponentTypesBuilder` for use with the given validator.
new(validator: &Validator) -> Self101     pub fn new(validator: &Validator) -> Self {
102         Self {
103             module_types: ModuleTypesBuilder::new(validator),
104 
105             functions: HashMap::default(),
106             lists: HashMap::default(),
107             maps: HashMap::default(),
108             records: HashMap::default(),
109             variants: HashMap::default(),
110             tuples: HashMap::default(),
111             enums: HashMap::default(),
112             flags: HashMap::default(),
113             options: HashMap::default(),
114             results: HashMap::default(),
115             futures: HashMap::default(),
116             streams: HashMap::default(),
117             future_tables: HashMap::default(),
118             stream_tables: HashMap::default(),
119             error_context_tables: HashMap::default(),
120             component_types: ComponentTypes::default(),
121             type_info: TypeInformationCache::default(),
122             resources: ResourcesBuilder::default(),
123             abstract_resources: 0,
124             fixed_length_lists: HashMap::default(),
125         }
126     }
127 
export_type_def( &mut self, export_items: &PrimaryMap<ExportIndex, Export>, idx: ExportIndex, ) -> TypeDef128     fn export_type_def(
129         &mut self,
130         export_items: &PrimaryMap<ExportIndex, Export>,
131         idx: ExportIndex,
132     ) -> TypeDef {
133         match &export_items[idx] {
134             Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(*ty),
135             Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
136                 TypeDef::Module(*ty)
137             }
138             Export::Instance { ty, .. } => TypeDef::ComponentInstance(*ty),
139             Export::Type(ty) => *ty,
140         }
141     }
142 
143     /// Finishes this list of component types and returns the finished
144     /// structure and the [`TypeComponentIndex`] corresponding to top-level component
145     /// with `imports` and `exports` specified.
finish(mut self, component: &Component) -> (ComponentTypes, TypeComponentIndex)146     pub fn finish(mut self, component: &Component) -> (ComponentTypes, TypeComponentIndex) {
147         let mut component_ty = TypeComponent::default();
148         for (_, (name, ty)) in component.import_types.iter() {
149             component_ty.imports.insert(name.clone(), *ty);
150         }
151         for (name, ty) in component.exports.raw_iter() {
152             component_ty.exports.insert(
153                 name.clone(),
154                 self.export_type_def(&component.export_items, *ty),
155             );
156         }
157         let ty = self.component_types.components.push(component_ty);
158 
159         self.component_types.module_types = Some(self.module_types.finish());
160         (self.component_types, ty)
161     }
162 
163     /// Smaller helper method to find a `ModuleInternedTypeIndex` which
164     /// corresponds to the `resource.drop` intrinsic in components, namely a
165     /// core wasm function type which takes one `i32` argument and has no
166     /// results.
167     ///
168     /// This is a bit of a hack right now as ideally this find operation
169     /// wouldn't be needed and instead the `ModuleInternedTypeIndex` itself
170     /// would be threaded through appropriately, but that's left for a future
171     /// refactoring. Try not to lean too hard on this method though.
find_resource_drop_signature(&self) -> Option<ModuleInternedTypeIndex>172     pub fn find_resource_drop_signature(&self) -> Option<ModuleInternedTypeIndex> {
173         self.module_types
174             .wasm_types()
175             .find(|(_, ty)| {
176                 ty.as_func().map_or(false, |sig| {
177                     sig.params().len() == 1
178                         && sig.results().len() == 0
179                         && sig.params()[0] == WasmValType::I32
180                 })
181             })
182             .map(|(i, _)| i)
183     }
184 
185     /// Returns the underlying builder used to build up core wasm module types.
186     ///
187     /// Note that this is shared across all modules found within a component to
188     /// improve the wins from deduplicating function signatures.
module_types_builder(&self) -> &ModuleTypesBuilder189     pub fn module_types_builder(&self) -> &ModuleTypesBuilder {
190         &self.module_types
191     }
192 
193     /// Same as `module_types_builder`, but `mut`.
module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder194     pub fn module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder {
195         &mut self.module_types
196     }
197 
198     /// Returns the internal reference to the in-progress `&ComponentTypes`.
component_types(&self) -> &ComponentTypes199     pub(super) fn component_types(&self) -> &ComponentTypes {
200         &self.component_types
201     }
202 
203     /// Returns the number of resource tables allocated so far, or the maximum
204     /// `TypeResourceTableIndex`.
num_resource_tables(&self) -> usize205     pub fn num_resource_tables(&self) -> usize {
206         self.component_types.resource_tables.len()
207     }
208 
209     /// Returns the number of future tables allocated so far, or the maximum
210     /// `TypeFutureTableIndex`.
num_future_tables(&self) -> usize211     pub fn num_future_tables(&self) -> usize {
212         self.component_types.future_tables.len()
213     }
214 
215     /// Returns the number of stream tables allocated so far, or the maximum
216     /// `TypeStreamTableIndex`.
num_stream_tables(&self) -> usize217     pub fn num_stream_tables(&self) -> usize {
218         self.component_types.stream_tables.len()
219     }
220 
221     /// Returns the number of error-context tables allocated so far, or the maximum
222     /// `TypeComponentLocalErrorContextTableIndex`.
num_error_context_tables(&self) -> usize223     pub fn num_error_context_tables(&self) -> usize {
224         self.component_types.error_context_tables.len()
225     }
226 
227     /// Returns a mutable reference to the underlying `ResourcesBuilder`.
resources_mut(&mut self) -> &mut ResourcesBuilder228     pub fn resources_mut(&mut self) -> &mut ResourcesBuilder {
229         &mut self.resources
230     }
231 
232     /// Work around the borrow checker to borrow two sub-fields simultaneously
233     /// externally.
resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes)234     pub fn resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes) {
235         (&mut self.resources, &self.component_types)
236     }
237 
238     /// Converts a wasmparser `ComponentFuncType` into Wasmtime's type
239     /// representation.
convert_component_func_type( &mut self, types: TypesRef<'_>, id: ComponentFuncTypeId, ) -> Result<TypeFuncIndex>240     pub fn convert_component_func_type(
241         &mut self,
242         types: TypesRef<'_>,
243         id: ComponentFuncTypeId,
244     ) -> Result<TypeFuncIndex> {
245         assert_eq!(types.id(), self.module_types.validator_id());
246         let ty = &types[id];
247         let param_names = ty.params.iter().map(|(name, _)| name.to_string()).collect();
248         let params = ty
249             .params
250             .iter()
251             .map(|(_name, ty)| self.valtype(types, ty))
252             .collect::<Result<_>>()?;
253         let results = ty
254             .result
255             .iter()
256             .map(|ty| self.valtype(types, ty))
257             .collect::<Result<_>>()?;
258         let params = self.new_tuple_type(params);
259         let results = self.new_tuple_type(results);
260         let ty = TypeFunc {
261             async_: ty.async_,
262             param_names,
263             params,
264             results,
265         };
266         Ok(self.add_func_type(ty))
267     }
268 
269     /// Converts a wasmparser `ComponentEntityType` into Wasmtime's type
270     /// representation.
convert_component_entity_type( &mut self, types: TypesRef<'_>, ty: ComponentEntityType, ) -> Result<TypeDef>271     pub fn convert_component_entity_type(
272         &mut self,
273         types: TypesRef<'_>,
274         ty: ComponentEntityType,
275     ) -> Result<TypeDef> {
276         assert_eq!(types.id(), self.module_types.validator_id());
277         Ok(match ty {
278             ComponentEntityType::Module(id) => TypeDef::Module(self.convert_module(types, id)?),
279             ComponentEntityType::Component(id) => {
280                 TypeDef::Component(self.convert_component(types, id)?)
281             }
282             ComponentEntityType::Instance(id) => {
283                 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
284             }
285             ComponentEntityType::Func(id) => {
286                 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
287             }
288             ComponentEntityType::Type { created, .. } => match created {
289                 ComponentAnyTypeId::Defined(id) => {
290                     TypeDef::Interface(self.defined_type(types, id)?)
291                 }
292                 ComponentAnyTypeId::Resource(id) => {
293                     TypeDef::Resource(self.resource_id(id.resource()))
294                 }
295                 _ => bail!("unsupported type export"),
296             },
297             ComponentEntityType::Value(_) => bail!("values not supported"),
298         })
299     }
300 
301     /// Converts a wasmparser `Type` into Wasmtime's type representation.
convert_type(&mut self, types: TypesRef<'_>, id: ComponentAnyTypeId) -> Result<TypeDef>302     pub fn convert_type(&mut self, types: TypesRef<'_>, id: ComponentAnyTypeId) -> Result<TypeDef> {
303         assert_eq!(types.id(), self.module_types.validator_id());
304         Ok(match id {
305             ComponentAnyTypeId::Defined(id) => TypeDef::Interface(self.defined_type(types, id)?),
306             ComponentAnyTypeId::Component(id) => {
307                 TypeDef::Component(self.convert_component(types, id)?)
308             }
309             ComponentAnyTypeId::Instance(id) => {
310                 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
311             }
312             ComponentAnyTypeId::Func(id) => {
313                 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
314             }
315             ComponentAnyTypeId::Resource(id) => TypeDef::Resource(self.resource_id(id.resource())),
316         })
317     }
318 
convert_component( &mut self, types: TypesRef<'_>, id: ComponentTypeId, ) -> Result<TypeComponentIndex>319     fn convert_component(
320         &mut self,
321         types: TypesRef<'_>,
322         id: ComponentTypeId,
323     ) -> Result<TypeComponentIndex> {
324         assert_eq!(types.id(), self.module_types.validator_id());
325         let ty = &types[id];
326         let mut result = TypeComponent::default();
327         for (name, ty) in ty.imports.iter() {
328             self.register_abstract_component_entity_type(types, *ty);
329             result.imports.insert(
330                 name.clone(),
331                 self.convert_component_entity_type(types, *ty)?,
332             );
333         }
334         for (name, ty) in ty.exports.iter() {
335             self.register_abstract_component_entity_type(types, *ty);
336             result.exports.insert(
337                 name.clone(),
338                 self.convert_component_entity_type(types, *ty)?,
339             );
340         }
341         Ok(self.component_types.components.push(result))
342     }
343 
convert_instance( &mut self, types: TypesRef<'_>, id: ComponentInstanceTypeId, ) -> Result<TypeComponentInstanceIndex>344     pub(crate) fn convert_instance(
345         &mut self,
346         types: TypesRef<'_>,
347         id: ComponentInstanceTypeId,
348     ) -> Result<TypeComponentInstanceIndex> {
349         assert_eq!(types.id(), self.module_types.validator_id());
350         let ty = &types[id];
351         let mut result = TypeComponentInstance::default();
352         for (name, ty) in ty.exports.iter() {
353             self.register_abstract_component_entity_type(types, *ty);
354             result.exports.insert(
355                 name.clone(),
356                 self.convert_component_entity_type(types, *ty)?,
357             );
358         }
359         Ok(self.component_types.component_instances.push(result))
360     }
361 
register_abstract_component_entity_type( &mut self, types: TypesRef<'_>, ty: ComponentEntityType, )362     fn register_abstract_component_entity_type(
363         &mut self,
364         types: TypesRef<'_>,
365         ty: ComponentEntityType,
366     ) {
367         let mut path = Vec::new();
368         self.resources.register_abstract_component_entity_type(
369             &types,
370             ty,
371             &mut path,
372             &mut |_path| {
373                 self.abstract_resources += 1;
374                 AbstractResourceIndex::from_u32(self.abstract_resources)
375             },
376         );
377     }
378 
convert_module( &mut self, types: TypesRef<'_>, id: ComponentCoreModuleTypeId, ) -> Result<TypeModuleIndex>379     pub(crate) fn convert_module(
380         &mut self,
381         types: TypesRef<'_>,
382         id: ComponentCoreModuleTypeId,
383     ) -> Result<TypeModuleIndex> {
384         assert_eq!(types.id(), self.module_types.validator_id());
385         let ty = &types[id];
386         let mut result = TypeModule::default();
387         for ((module, field), ty) in ty.imports.iter() {
388             result.imports.insert(
389                 (module.clone(), field.clone()),
390                 self.entity_type(types, ty)?,
391             );
392         }
393         for (name, ty) in ty.exports.iter() {
394             result
395                 .exports
396                 .insert(name.clone(), self.entity_type(types, ty)?);
397         }
398         Ok(self.component_types.modules.push(result))
399     }
400 
entity_type( &mut self, types: TypesRef<'_>, ty: &wasmparser::types::EntityType, ) -> Result<EntityType>401     fn entity_type(
402         &mut self,
403         types: TypesRef<'_>,
404         ty: &wasmparser::types::EntityType,
405     ) -> Result<EntityType> {
406         use wasmparser::types::EntityType::*;
407 
408         assert_eq!(types.id(), self.module_types.validator_id());
409         Ok(match ty {
410             Func(id) => EntityType::Function({
411                 self.module_types_builder_mut()
412                     .intern_type(types, *id)?
413                     .into()
414             }),
415             Table(ty) => EntityType::Table(self.convert_table_type(ty)?),
416             Memory(ty) => EntityType::Memory((*ty).into()),
417             Global(ty) => EntityType::Global(self.convert_global_type(ty)?),
418             Tag(id) => {
419                 let func = self.module_types_builder_mut().intern_type(types, *id)?;
420                 let exc = self
421                     .module_types_builder_mut()
422                     .define_exception_type_for_tag(func);
423                 EntityType::Tag(crate::types::Tag {
424                     signature: func.into(),
425                     exception: exc.into(),
426                 })
427             }
428             FuncExact(_) => bail!("custom-descriptors proposal not implemented"),
429         })
430     }
431 
432     /// Convert a wasmparser `ComponentDefinedTypeId` into Wasmtime's type representation.
defined_type( &mut self, types: TypesRef<'_>, id: ComponentDefinedTypeId, ) -> Result<InterfaceType>433     pub fn defined_type(
434         &mut self,
435         types: TypesRef<'_>,
436         id: ComponentDefinedTypeId,
437     ) -> Result<InterfaceType> {
438         assert_eq!(types.id(), self.module_types.validator_id());
439         let ret = match &types[id] {
440             ComponentDefinedType::Primitive(ty) => self.primitive_type(ty)?,
441             ComponentDefinedType::Record(e) => InterfaceType::Record(self.record_type(types, e)?),
442             ComponentDefinedType::Variant(e) => {
443                 InterfaceType::Variant(self.variant_type(types, e)?)
444             }
445             ComponentDefinedType::List(e) => InterfaceType::List(self.list_type(types, e)?),
446             ComponentDefinedType::Map(key, value) => {
447                 InterfaceType::Map(self.map_type(types, key, value)?)
448             }
449             ComponentDefinedType::Tuple(e) => InterfaceType::Tuple(self.tuple_type(types, e)?),
450             ComponentDefinedType::Flags(e) => InterfaceType::Flags(self.flags_type(e)),
451             ComponentDefinedType::Enum(e) => InterfaceType::Enum(self.enum_type(e)),
452             ComponentDefinedType::Option(e) => InterfaceType::Option(self.option_type(types, e)?),
453             ComponentDefinedType::Result { ok, err } => {
454                 InterfaceType::Result(self.result_type(types, ok, err)?)
455             }
456             ComponentDefinedType::Own(r) => InterfaceType::Own(self.resource_id(r.resource())),
457             ComponentDefinedType::Borrow(r) => {
458                 InterfaceType::Borrow(self.resource_id(r.resource()))
459             }
460             ComponentDefinedType::Future(ty) => {
461                 InterfaceType::Future(self.future_table_type(types, ty)?)
462             }
463             ComponentDefinedType::Stream(ty) => {
464                 InterfaceType::Stream(self.stream_table_type(types, ty)?)
465             }
466             ComponentDefinedType::FixedLengthList(ty, size) => {
467                 InterfaceType::FixedLengthList(self.fixed_length_list_type(types, ty, *size)?)
468             }
469         };
470         let info = self.type_information(&ret);
471         if info.depth > MAX_TYPE_DEPTH {
472             bail!("type nesting is too deep");
473         }
474         Ok(ret)
475     }
476 
477     /// Retrieve Wasmtime's type representation of the `error-context` type.
error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex>478     pub fn error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
479         self.error_context_table_type()
480     }
481 
valtype( &mut self, types: TypesRef<'_>, ty: &ComponentValType, ) -> Result<InterfaceType>482     pub(crate) fn valtype(
483         &mut self,
484         types: TypesRef<'_>,
485         ty: &ComponentValType,
486     ) -> Result<InterfaceType> {
487         assert_eq!(types.id(), self.module_types.validator_id());
488         match ty {
489             ComponentValType::Primitive(p) => self.primitive_type(p),
490             ComponentValType::Type(id) => self.defined_type(types, *id),
491         }
492     }
493 
primitive_type(&mut self, ty: &PrimitiveValType) -> Result<InterfaceType>494     fn primitive_type(&mut self, ty: &PrimitiveValType) -> Result<InterfaceType> {
495         match ty {
496             wasmparser::PrimitiveValType::Bool => Ok(InterfaceType::Bool),
497             wasmparser::PrimitiveValType::S8 => Ok(InterfaceType::S8),
498             wasmparser::PrimitiveValType::U8 => Ok(InterfaceType::U8),
499             wasmparser::PrimitiveValType::S16 => Ok(InterfaceType::S16),
500             wasmparser::PrimitiveValType::U16 => Ok(InterfaceType::U16),
501             wasmparser::PrimitiveValType::S32 => Ok(InterfaceType::S32),
502             wasmparser::PrimitiveValType::U32 => Ok(InterfaceType::U32),
503             wasmparser::PrimitiveValType::S64 => Ok(InterfaceType::S64),
504             wasmparser::PrimitiveValType::U64 => Ok(InterfaceType::U64),
505             wasmparser::PrimitiveValType::F32 => Ok(InterfaceType::Float32),
506             wasmparser::PrimitiveValType::F64 => Ok(InterfaceType::Float64),
507             wasmparser::PrimitiveValType::Char => Ok(InterfaceType::Char),
508             wasmparser::PrimitiveValType::String => Ok(InterfaceType::String),
509             wasmparser::PrimitiveValType::ErrorContext => Ok(InterfaceType::ErrorContext(
510                 self.error_context_table_type()?,
511             )),
512         }
513     }
514 
record_type(&mut self, types: TypesRef<'_>, ty: &RecordType) -> Result<TypeRecordIndex>515     fn record_type(&mut self, types: TypesRef<'_>, ty: &RecordType) -> Result<TypeRecordIndex> {
516         assert_eq!(types.id(), self.module_types.validator_id());
517         let fields = ty
518             .fields
519             .iter()
520             .map(|(name, ty)| {
521                 Ok(RecordField {
522                     name: name.to_string(),
523                     ty: self.valtype(types, ty)?,
524                 })
525             })
526             .collect::<Result<Box<[_]>>>()?;
527         let abi = CanonicalAbiInfo::record(
528             fields
529                 .iter()
530                 .map(|field| self.component_types.canonical_abi(&field.ty)),
531         );
532         Ok(self.add_record_type(TypeRecord { fields, abi }))
533     }
534 
variant_type(&mut self, types: TypesRef<'_>, ty: &VariantType) -> Result<TypeVariantIndex>535     fn variant_type(&mut self, types: TypesRef<'_>, ty: &VariantType) -> Result<TypeVariantIndex> {
536         assert_eq!(types.id(), self.module_types.validator_id());
537         let cases = ty
538             .cases
539             .iter()
540             .map(|(name, case)| {
541                 Ok((
542                     name.to_string(),
543                     match &case.ty.as_ref() {
544                         Some(ty) => Some(self.valtype(types, ty)?),
545                         None => None,
546                     },
547                 ))
548             })
549             .collect::<Result<IndexMap<_, _>>>()?;
550         let (info, abi) = VariantInfo::new(
551             cases
552                 .iter()
553                 .map(|(_, c)| c.as_ref().map(|ty| self.component_types.canonical_abi(ty))),
554         );
555         Ok(self.add_variant_type(TypeVariant { cases, abi, info }))
556     }
557 
tuple_type(&mut self, types: TypesRef<'_>, ty: &TupleType) -> Result<TypeTupleIndex>558     fn tuple_type(&mut self, types: TypesRef<'_>, ty: &TupleType) -> Result<TypeTupleIndex> {
559         assert_eq!(types.id(), self.module_types.validator_id());
560         let types = ty
561             .types
562             .iter()
563             .map(|ty| self.valtype(types, ty))
564             .collect::<Result<Box<[_]>>>()?;
565         Ok(self.new_tuple_type(types))
566     }
567 
new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex568     pub(crate) fn new_tuple_type(&mut self, types: Box<[InterfaceType]>) -> TypeTupleIndex {
569         let abi = CanonicalAbiInfo::record(
570             types
571                 .iter()
572                 .map(|ty| self.component_types.canonical_abi(ty)),
573         );
574         self.add_tuple_type(TypeTuple { types, abi })
575     }
576 
fixed_length_list_type( &mut self, types: TypesRef<'_>, ty: &ComponentValType, size: u32, ) -> Result<TypeFixedLengthListIndex>577     fn fixed_length_list_type(
578         &mut self,
579         types: TypesRef<'_>,
580         ty: &ComponentValType,
581         size: u32,
582     ) -> Result<TypeFixedLengthListIndex> {
583         assert_eq!(types.id(), self.module_types.validator_id());
584         let element = self.valtype(types, ty)?;
585         Ok(self.new_fixed_length_list_type(element, size))
586     }
587 
new_fixed_length_list_type( &mut self, element: InterfaceType, size: u32, ) -> TypeFixedLengthListIndex588     pub(crate) fn new_fixed_length_list_type(
589         &mut self,
590         element: InterfaceType,
591         size: u32,
592     ) -> TypeFixedLengthListIndex {
593         let element_abi = self.component_types.canonical_abi(&element);
594         let mut abi = element_abi.clone();
595         // this assumes that size32 is already rounded up to alignment
596         abi.size32 = element_abi.size32.saturating_mul(size);
597         abi.size64 = element_abi.size64.saturating_mul(size);
598         abi.flat_count = element_abi
599             .flat_count
600             .zip(u8::try_from(size).ok())
601             .and_then(|(flat_count, size)| flat_count.checked_mul(size));
602         self.add_fixed_length_list_type(TypeFixedLengthList { element, size, abi })
603     }
604 
flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex605     fn flags_type(&mut self, flags: &IndexSet<KebabString>) -> TypeFlagsIndex {
606         let flags = TypeFlags {
607             names: flags.iter().map(|s| s.to_string()).collect(),
608             abi: CanonicalAbiInfo::flags(flags.len()),
609         };
610         self.add_flags_type(flags)
611     }
612 
enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex613     fn enum_type(&mut self, variants: &IndexSet<KebabString>) -> TypeEnumIndex {
614         let names = variants
615             .iter()
616             .map(|s| s.to_string())
617             .collect::<IndexSet<_>>();
618         let (info, abi) = VariantInfo::new(names.iter().map(|_| None));
619         self.add_enum_type(TypeEnum { names, abi, info })
620     }
621 
option_type( &mut self, types: TypesRef<'_>, ty: &ComponentValType, ) -> Result<TypeOptionIndex>622     fn option_type(
623         &mut self,
624         types: TypesRef<'_>,
625         ty: &ComponentValType,
626     ) -> Result<TypeOptionIndex> {
627         assert_eq!(types.id(), self.module_types.validator_id());
628         let ty = self.valtype(types, ty)?;
629         let (info, abi) = VariantInfo::new([None, Some(self.component_types.canonical_abi(&ty))]);
630         Ok(self.add_option_type(TypeOption { ty, abi, info }))
631     }
632 
result_type( &mut self, types: TypesRef<'_>, ok: &Option<ComponentValType>, err: &Option<ComponentValType>, ) -> Result<TypeResultIndex>633     fn result_type(
634         &mut self,
635         types: TypesRef<'_>,
636         ok: &Option<ComponentValType>,
637         err: &Option<ComponentValType>,
638     ) -> Result<TypeResultIndex> {
639         assert_eq!(types.id(), self.module_types.validator_id());
640         let ok = match ok {
641             Some(ty) => Some(self.valtype(types, ty)?),
642             None => None,
643         };
644         let err = match err {
645             Some(ty) => Some(self.valtype(types, ty)?),
646             None => None,
647         };
648         let (info, abi) = VariantInfo::new([
649             ok.as_ref().map(|t| self.component_types.canonical_abi(t)),
650             err.as_ref().map(|t| self.component_types.canonical_abi(t)),
651         ]);
652         Ok(self.add_result_type(TypeResult { ok, err, abi, info }))
653     }
654 
future_table_type( &mut self, types: TypesRef<'_>, ty: &Option<ComponentValType>, ) -> Result<TypeFutureTableIndex>655     fn future_table_type(
656         &mut self,
657         types: TypesRef<'_>,
658         ty: &Option<ComponentValType>,
659     ) -> Result<TypeFutureTableIndex> {
660         let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
661         let ty = self.add_future_type(TypeFuture { payload });
662         Ok(self.add_future_table_type(TypeFutureTable {
663             ty,
664             instance: self.resources.get_current_instance().unwrap(),
665         }))
666     }
667 
stream_table_type( &mut self, types: TypesRef<'_>, ty: &Option<ComponentValType>, ) -> Result<TypeStreamTableIndex>668     fn stream_table_type(
669         &mut self,
670         types: TypesRef<'_>,
671         ty: &Option<ComponentValType>,
672     ) -> Result<TypeStreamTableIndex> {
673         let payload = ty.as_ref().map(|ty| self.valtype(types, ty)).transpose()?;
674         let ty = self.add_stream_type(TypeStream { payload });
675         Ok(self.add_stream_table_type(TypeStreamTable {
676             ty,
677             instance: self.resources.get_current_instance().unwrap(),
678         }))
679     }
680 
681     /// Retrieve Wasmtime's type representation of the `error-context` type from
682     /// the point of view of the current component instance.
error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex>683     pub fn error_context_table_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
684         Ok(self.add_error_context_table_type(TypeErrorContextTable {
685             instance: self.resources.get_current_instance().unwrap(),
686         }))
687     }
688 
list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<TypeListIndex>689     fn list_type(&mut self, types: TypesRef<'_>, ty: &ComponentValType) -> Result<TypeListIndex> {
690         assert_eq!(types.id(), self.module_types.validator_id());
691         let element = self.valtype(types, ty)?;
692         Ok(self.add_list_type(TypeList { element }))
693     }
694 
map_type( &mut self, types: TypesRef<'_>, key: &ComponentValType, value: &ComponentValType, ) -> Result<TypeMapIndex>695     fn map_type(
696         &mut self,
697         types: TypesRef<'_>,
698         key: &ComponentValType,
699         value: &ComponentValType,
700     ) -> Result<TypeMapIndex> {
701         assert_eq!(types.id(), self.module_types.validator_id());
702         let key_ty = self.valtype(types, key)?;
703         let value_ty = self.valtype(types, value)?;
704         let key_abi = self.component_types.canonical_abi(&key_ty);
705         let value_abi = self.component_types.canonical_abi(&value_ty);
706         let entry_abi = CanonicalAbiInfo::record([key_abi, value_abi].into_iter());
707 
708         let mut offset32 = 0;
709         key_abi.next_field32(&mut offset32);
710         let value_offset32 = value_abi.next_field32(&mut offset32);
711 
712         let mut offset64 = 0;
713         key_abi.next_field64(&mut offset64);
714         let value_offset64 = value_abi.next_field64(&mut offset64);
715 
716         Ok(self.add_map_type(TypeMap {
717             key: key_ty,
718             value: value_ty,
719             entry_abi,
720             value_offset32,
721             value_offset64,
722         }))
723     }
724 
725     /// Converts a wasmparser `id`, which must point to a resource, to its
726     /// corresponding `TypeResourceTableIndex`.
resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex727     pub fn resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex {
728         self.resources.convert(id, &mut self.component_types)
729     }
730 
731     /// Interns a new function type within this type information.
add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex732     pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
733         intern(&mut self.functions, &mut self.component_types.functions, ty)
734     }
735 
736     /// Interns a new record type within this type information.
add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex737     pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
738         intern_and_fill_flat_types!(self, records, ty)
739     }
740 
741     /// Interns a new flags type within this type information.
add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex742     pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
743         intern_and_fill_flat_types!(self, flags, ty)
744     }
745 
746     /// Interns a new tuple type within this type information.
add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex747     pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
748         intern_and_fill_flat_types!(self, tuples, ty)
749     }
750 
751     /// Interns a new tuple type within this type information.
add_fixed_length_list_type( &mut self, ty: TypeFixedLengthList, ) -> TypeFixedLengthListIndex752     pub fn add_fixed_length_list_type(
753         &mut self,
754         ty: TypeFixedLengthList,
755     ) -> TypeFixedLengthListIndex {
756         intern_and_fill_flat_types!(self, fixed_length_lists, ty)
757     }
758 
759     /// Interns a new variant type within this type information.
add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex760     pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
761         intern_and_fill_flat_types!(self, variants, ty)
762     }
763 
764     /// Interns a new enum type within this type information.
add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex765     pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
766         intern_and_fill_flat_types!(self, enums, ty)
767     }
768 
769     /// Interns a new option type within this type information.
add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex770     pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
771         intern_and_fill_flat_types!(self, options, ty)
772     }
773 
774     /// Interns a new result type within this type information.
add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex775     pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
776         intern_and_fill_flat_types!(self, results, ty)
777     }
778 
779     /// Interns a new list type within this type information.
add_list_type(&mut self, ty: TypeList) -> TypeListIndex780     pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
781         intern_and_fill_flat_types!(self, lists, ty)
782     }
783 
784     /// Interns a new map type within this type information.
add_map_type(&mut self, ty: TypeMap) -> TypeMapIndex785     pub fn add_map_type(&mut self, ty: TypeMap) -> TypeMapIndex {
786         intern_and_fill_flat_types!(self, maps, ty)
787     }
788 
789     /// Interns a new future type within this type information.
add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex790     pub fn add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex {
791         intern(&mut self.futures, &mut self.component_types.futures, ty)
792     }
793 
794     /// Interns a new future table type within this type information.
add_future_table_type(&mut self, ty: TypeFutureTable) -> TypeFutureTableIndex795     pub fn add_future_table_type(&mut self, ty: TypeFutureTable) -> TypeFutureTableIndex {
796         intern(
797             &mut self.future_tables,
798             &mut self.component_types.future_tables,
799             ty,
800         )
801     }
802 
803     /// Interns a new stream type within this type information.
add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex804     pub fn add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex {
805         intern(&mut self.streams, &mut self.component_types.streams, ty)
806     }
807 
808     /// Interns a new stream table type within this type information.
add_stream_table_type(&mut self, ty: TypeStreamTable) -> TypeStreamTableIndex809     pub fn add_stream_table_type(&mut self, ty: TypeStreamTable) -> TypeStreamTableIndex {
810         intern(
811             &mut self.stream_tables,
812             &mut self.component_types.stream_tables,
813             ty,
814         )
815     }
816 
817     /// Interns a new error context table type within this type information.
add_error_context_table_type( &mut self, ty: TypeErrorContextTable, ) -> TypeComponentLocalErrorContextTableIndex818     pub fn add_error_context_table_type(
819         &mut self,
820         ty: TypeErrorContextTable,
821     ) -> TypeComponentLocalErrorContextTableIndex {
822         intern(
823             &mut self.error_context_tables,
824             &mut self.component_types.error_context_tables,
825             ty,
826         )
827     }
828 
829     /// Returns the canonical ABI information about the specified type.
canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo830     pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
831         self.component_types.canonical_abi(ty)
832     }
833 
834     /// Returns the "flat types" for the given interface type used in the
835     /// canonical ABI.
836     ///
837     /// Returns `None` if the type is too large to be represented via flat types
838     /// in the canonical abi.
flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>>839     pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
840         self.type_information(ty).flat.as_flat_types()
841     }
842 
843     /// Returns whether the type specified contains any borrowed resources
844     /// within it.
ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool845     pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
846         self.type_information(ty).has_borrow
847     }
848 
type_information(&self, ty: &InterfaceType) -> &TypeInformation849     fn type_information(&self, ty: &InterfaceType) -> &TypeInformation {
850         match ty {
851             InterfaceType::U8
852             | InterfaceType::S8
853             | InterfaceType::Bool
854             | InterfaceType::U16
855             | InterfaceType::S16
856             | InterfaceType::U32
857             | InterfaceType::S32
858             | InterfaceType::Char
859             | InterfaceType::Own(_)
860             | InterfaceType::Future(_)
861             | InterfaceType::Stream(_)
862             | InterfaceType::ErrorContext(_) => {
863                 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I32);
864                 &INFO
865             }
866             InterfaceType::Borrow(_) => {
867                 static INFO: TypeInformation = {
868                     let mut info = TypeInformation::primitive(FlatType::I32);
869                     info.has_borrow = true;
870                     info
871                 };
872                 &INFO
873             }
874             InterfaceType::U64 | InterfaceType::S64 => {
875                 static INFO: TypeInformation = TypeInformation::primitive(FlatType::I64);
876                 &INFO
877             }
878             InterfaceType::Float32 => {
879                 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F32);
880                 &INFO
881             }
882             InterfaceType::Float64 => {
883                 static INFO: TypeInformation = TypeInformation::primitive(FlatType::F64);
884                 &INFO
885             }
886             InterfaceType::String => {
887                 static INFO: TypeInformation = TypeInformation::string();
888                 &INFO
889             }
890 
891             InterfaceType::List(i) => &self.type_info.lists[*i],
892             InterfaceType::Map(i) => &self.type_info.maps[*i],
893             InterfaceType::Record(i) => &self.type_info.records[*i],
894             InterfaceType::Variant(i) => &self.type_info.variants[*i],
895             InterfaceType::Tuple(i) => &self.type_info.tuples[*i],
896             InterfaceType::Flags(i) => &self.type_info.flags[*i],
897             InterfaceType::Enum(i) => &self.type_info.enums[*i],
898             InterfaceType::Option(i) => &self.type_info.options[*i],
899             InterfaceType::Result(i) => &self.type_info.results[*i],
900             InterfaceType::FixedLengthList(i) => &self.type_info.fixed_length_lists[*i],
901         }
902     }
903 }
904 
905 impl TypeConvert for ComponentTypesBuilder {
lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType906     fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType {
907         panic!("heap types are not supported yet")
908     }
909 
lookup_type_index(&self, _index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex910     fn lookup_type_index(&self, _index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
911         panic!("typed references are not supported yet")
912     }
913 }
914 
intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U where T: Hash + Clone + Eq, U: Copy + EntityRef,915 fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U
916 where
917     T: Hash + Clone + Eq,
918     U: Copy + EntityRef,
919 {
920     if let Some(idx) = map.get(&item) {
921         return *idx;
922     }
923     let idx = list.push(item.clone());
924     map.insert(item, idx);
925     return idx;
926 }
927 
928 struct FlatTypesStorage {
929     // This could be represented as `Vec<FlatType>` but on 64-bit architectures
930     // that's 24 bytes. Otherwise `FlatType` is 1 byte large and
931     // `MAX_FLAT_TYPES` is 16, so it should ideally be more space-efficient to
932     // use a flat array instead of a heap-based vector.
933     memory32: [FlatType; MAX_FLAT_TYPES],
934     memory64: [FlatType; MAX_FLAT_TYPES],
935 
936     // Tracks the number of flat types pushed into this storage. If this is
937     // `MAX_FLAT_TYPES + 1` then this storage represents an un-reprsentable
938     // type in flat types.
939     len: u8,
940 }
941 
942 impl FlatTypesStorage {
new() -> FlatTypesStorage943     const fn new() -> FlatTypesStorage {
944         FlatTypesStorage {
945             memory32: [FlatType::I32; MAX_FLAT_TYPES],
946             memory64: [FlatType::I32; MAX_FLAT_TYPES],
947             len: 0,
948         }
949     }
950 
as_flat_types(&self) -> Option<FlatTypes<'_>>951     fn as_flat_types(&self) -> Option<FlatTypes<'_>> {
952         let len = usize::from(self.len);
953         if len > MAX_FLAT_TYPES {
954             assert_eq!(len, MAX_FLAT_TYPES + 1);
955             None
956         } else {
957             Some(FlatTypes {
958                 memory32: &self.memory32[..len],
959                 memory64: &self.memory64[..len],
960             })
961         }
962     }
963 
964     /// Pushes a new flat type into this list using `t32` for 32-bit memories
965     /// and `t64` for 64-bit memories.
966     ///
967     /// Returns whether the type was actually pushed or whether this list of
968     /// flat types just exceeded the maximum meaning that it is now
969     /// unrepresentable with a flat list of types.
push(&mut self, t32: FlatType, t64: FlatType) -> bool970     fn push(&mut self, t32: FlatType, t64: FlatType) -> bool {
971         let len = usize::from(self.len);
972         if len < MAX_FLAT_TYPES {
973             self.memory32[len] = t32;
974             self.memory64[len] = t64;
975             self.len += 1;
976             true
977         } else {
978             // If this was the first one to go over then flag the length as
979             // being incompatible with a flat representation.
980             if len == MAX_FLAT_TYPES {
981                 self.len += 1;
982             }
983             false
984         }
985     }
986 }
987 
988 impl FlatType {
join(&mut self, other: FlatType)989     fn join(&mut self, other: FlatType) {
990         if *self == other {
991             return;
992         }
993         *self = match (*self, other) {
994             (FlatType::I32, FlatType::F32) | (FlatType::F32, FlatType::I32) => FlatType::I32,
995             _ => FlatType::I64,
996         };
997     }
998 }
999 
1000 #[derive(Default)]
1001 struct TypeInformationCache {
1002     records: PrimaryMap<TypeRecordIndex, TypeInformation>,
1003     variants: PrimaryMap<TypeVariantIndex, TypeInformation>,
1004     tuples: PrimaryMap<TypeTupleIndex, TypeInformation>,
1005     enums: PrimaryMap<TypeEnumIndex, TypeInformation>,
1006     flags: PrimaryMap<TypeFlagsIndex, TypeInformation>,
1007     options: PrimaryMap<TypeOptionIndex, TypeInformation>,
1008     results: PrimaryMap<TypeResultIndex, TypeInformation>,
1009     lists: PrimaryMap<TypeListIndex, TypeInformation>,
1010     maps: PrimaryMap<TypeMapIndex, TypeInformation>,
1011     fixed_length_lists: PrimaryMap<TypeFixedLengthListIndex, TypeInformation>,
1012 }
1013 
1014 struct TypeInformation {
1015     depth: u32,
1016     flat: FlatTypesStorage,
1017     has_borrow: bool,
1018 }
1019 
1020 impl TypeInformation {
new() -> TypeInformation1021     const fn new() -> TypeInformation {
1022         TypeInformation {
1023             depth: 0,
1024             flat: FlatTypesStorage::new(),
1025             has_borrow: false,
1026         }
1027     }
1028 
primitive(flat: FlatType) -> TypeInformation1029     const fn primitive(flat: FlatType) -> TypeInformation {
1030         let mut info = TypeInformation::new();
1031         info.depth = 1;
1032         info.flat.memory32[0] = flat;
1033         info.flat.memory64[0] = flat;
1034         info.flat.len = 1;
1035         info
1036     }
1037 
string() -> TypeInformation1038     const fn string() -> TypeInformation {
1039         let mut info = TypeInformation::new();
1040         info.depth = 1;
1041         info.flat.memory32[0] = FlatType::I32;
1042         info.flat.memory32[1] = FlatType::I32;
1043         info.flat.memory64[0] = FlatType::I64;
1044         info.flat.memory64[1] = FlatType::I64;
1045         info.flat.len = 2;
1046         info
1047     }
1048 
1049     /// Builds up all flat types internally using the specified representation
1050     /// for all of the component fields of the record.
build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>)1051     fn build_record<'a>(&mut self, types: impl Iterator<Item = &'a TypeInformation>) {
1052         self.depth = 1;
1053         for info in types {
1054             self.depth = self.depth.max(1 + info.depth);
1055             self.has_borrow = self.has_borrow || info.has_borrow;
1056             match info.flat.as_flat_types() {
1057                 Some(types) => {
1058                     for (t32, t64) in types.memory32.iter().zip(types.memory64) {
1059                         if !self.flat.push(*t32, *t64) {
1060                             break;
1061                         }
1062                     }
1063                 }
1064                 None => {
1065                     self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1066                 }
1067             }
1068         }
1069     }
1070 
1071     /// Builds up the flat types used to represent a `variant` which notably
1072     /// handles "join"ing types together so each case is representable as a
1073     /// single flat list of types.
1074     ///
1075     /// The iterator item is:
1076     ///
1077     /// * `None` - no payload for this case
1078     /// * `Some(None)` - this case has a payload but can't be represented with
1079     ///   flat types
1080     /// * `Some(Some(types))` - this case has a payload and is represented with
1081     ///   the types specified in the flat representation.
build_variant<'a, I>(&mut self, cases: I) where I: IntoIterator<Item = Option<&'a TypeInformation>>,1082     fn build_variant<'a, I>(&mut self, cases: I)
1083     where
1084         I: IntoIterator<Item = Option<&'a TypeInformation>>,
1085     {
1086         let cases = cases.into_iter();
1087         self.flat.push(FlatType::I32, FlatType::I32);
1088         self.depth = 1;
1089 
1090         for info in cases {
1091             let info = match info {
1092                 Some(info) => info,
1093                 // If this case doesn't have a payload then it doesn't change
1094                 // the depth/flat representation
1095                 None => continue,
1096             };
1097             self.depth = self.depth.max(1 + info.depth);
1098             self.has_borrow = self.has_borrow || info.has_borrow;
1099 
1100             // If this variant is already unrepresentable in a flat
1101             // representation then this can be skipped.
1102             if usize::from(self.flat.len) > MAX_FLAT_TYPES {
1103                 continue;
1104             }
1105 
1106             let types = match info.flat.as_flat_types() {
1107                 Some(types) => types,
1108                 // If this case isn't representable with a flat list of types
1109                 // then this variant also isn't representable.
1110                 None => {
1111                     self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1112                     continue;
1113                 }
1114             };
1115             // If the case used all of the flat types then the discriminant
1116             // added for this variant means that this variant is no longer
1117             // representable.
1118             if types.memory32.len() >= MAX_FLAT_TYPES {
1119                 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1120                 continue;
1121             }
1122             let dst = self
1123                 .flat
1124                 .memory32
1125                 .iter_mut()
1126                 .zip(&mut self.flat.memory64)
1127                 .skip(1);
1128             for (i, ((t32, t64), (dst32, dst64))) in types
1129                 .memory32
1130                 .iter()
1131                 .zip(types.memory64)
1132                 .zip(dst)
1133                 .enumerate()
1134             {
1135                 if i + 1 < usize::from(self.flat.len) {
1136                     // If this index hs already been set by some previous case
1137                     // then the types are joined together.
1138                     dst32.join(*t32);
1139                     dst64.join(*t64);
1140                 } else {
1141                     // Otherwise if this is the first time that the
1142                     // representation has gotten this large then the destination
1143                     // is simply whatever the type is. The length is also
1144                     // increased here to indicate this.
1145                     self.flat.len += 1;
1146                     *dst32 = *t32;
1147                     *dst64 = *t64;
1148                 }
1149             }
1150         }
1151     }
1152 
records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord)1153     fn records(&mut self, types: &ComponentTypesBuilder, ty: &TypeRecord) {
1154         self.build_record(ty.fields.iter().map(|f| types.type_information(&f.ty)));
1155     }
1156 
tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple)1157     fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
1158         self.build_record(ty.types.iter().map(|t| types.type_information(t)));
1159     }
1160 
fixed_length_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedLengthList)1161     fn fixed_length_lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeFixedLengthList) {
1162         let element_info = types.type_information(&ty.element);
1163         self.depth = 1 + element_info.depth;
1164         self.has_borrow = element_info.has_borrow;
1165         match element_info.flat.as_flat_types() {
1166             Some(types) => {
1167                 'outer: for _ in 0..ty.size {
1168                     for (t32, t64) in types.memory32.iter().zip(types.memory64) {
1169                         if !self.flat.push(*t32, *t64) {
1170                             break 'outer;
1171                         }
1172                     }
1173                 }
1174             }
1175             None => self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap(),
1176         }
1177     }
1178 
enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum)1179     fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
1180         self.depth = 1;
1181         self.flat.push(FlatType::I32, FlatType::I32);
1182     }
1183 
flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags)1184     fn flags(&mut self, _types: &ComponentTypesBuilder, ty: &TypeFlags) {
1185         self.depth = 1;
1186         match FlagsSize::from_count(ty.names.len()) {
1187             FlagsSize::Size0 => {}
1188             FlagsSize::Size1 | FlagsSize::Size2 => {
1189                 self.flat.push(FlatType::I32, FlatType::I32);
1190             }
1191             FlagsSize::Size4Plus(n) => {
1192                 for _ in 0..n {
1193                     self.flat.push(FlatType::I32, FlatType::I32);
1194                 }
1195             }
1196         }
1197     }
1198 
variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant)1199     fn variants(&mut self, types: &ComponentTypesBuilder, ty: &TypeVariant) {
1200         self.build_variant(
1201             ty.cases
1202                 .iter()
1203                 .map(|(_, c)| c.as_ref().map(|ty| types.type_information(ty))),
1204         )
1205     }
1206 
results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult)1207     fn results(&mut self, types: &ComponentTypesBuilder, ty: &TypeResult) {
1208         self.build_variant([
1209             ty.ok.as_ref().map(|ty| types.type_information(ty)),
1210             ty.err.as_ref().map(|ty| types.type_information(ty)),
1211         ])
1212     }
1213 
options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption)1214     fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
1215         self.build_variant([None, Some(types.type_information(&ty.ty))]);
1216     }
1217 
lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList)1218     fn lists(&mut self, types: &ComponentTypesBuilder, ty: &TypeList) {
1219         *self = TypeInformation::string();
1220         let info = types.type_information(&ty.element);
1221         self.depth += info.depth;
1222         self.has_borrow = info.has_borrow;
1223     }
1224 
maps(&mut self, types: &ComponentTypesBuilder, ty: &TypeMap)1225     fn maps(&mut self, types: &ComponentTypesBuilder, ty: &TypeMap) {
1226         // Maps are represented as list<tuple<k, v>> in canonical ABI
1227         // So we use POINTER_PAIR like lists, and calculate depth/borrow from key and value
1228         *self = TypeInformation::string();
1229         let key_info = types.type_information(&ty.key);
1230         let value_info = types.type_information(&ty.value);
1231         // Depth is max of key/value depths, plus 1 for the extra map layer.
1232         self.depth = key_info.depth.max(value_info.depth) + 1;
1233         self.has_borrow = key_info.has_borrow || value_info.has_borrow;
1234     }
1235 }
1236