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