1use crate::component::*;
2use crate::error::{Result, bail};
3use crate::prelude::*;
4use crate::{
5 EngineOrModuleTypeIndex, EntityType, ModuleInternedTypeIndex, ModuleTypes, ModuleTypesBuilder,
6 PrimaryMap, TypeConvert, WasmHeapType, WasmValType,
7};
8use cranelift_entity::EntityRef;
9use std::collections::HashMap;
10use std::hash::Hash;
11use std::ops::Index;
12use wasmparser::component_types::{
13 ComponentAnyTypeId, ComponentCoreModuleTypeId, ComponentDefinedType, ComponentDefinedTypeId,
14 ComponentEntityType, ComponentFuncTypeId, ComponentInstanceTypeId, ComponentTypeId,
15 ComponentValType, RecordType, ResourceId, TupleType, VariantType,
16};
17use wasmparser::names::KebabString;
18use wasmparser::types::TypesRef;
19use wasmparser::{PrimitiveValType, Validator};
20use wasmtime_component_util::FlagsSize;
21
22mod resources;
23pub use resources::ResourcesBuilder;
24
25const MAX_TYPE_DEPTH: u32 = 100;
33
34pub struct ComponentTypesBuilder {
39 functions: HashMap<TypeFunc, TypeFuncIndex>,
40 lists: HashMap<TypeList, TypeListIndex>,
41 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);
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 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 pub fn module_types_builder(&self) -> &ModuleTypesBuilder {
190 &self.module_types
191 }
192
193 pub fn module_types_builder_mut(&mut self) -> &mut ModuleTypesBuilder {
195 &mut self.module_types
196 }
197
198 pub(super) fn component_types(&self) -> &ComponentTypes {
200 &self.component_types
201 }
202
203 pub fn num_resource_tables(&self) -> usize {
206 self.component_types.resource_tables.len()
207 }
208
209 pub fn num_future_tables(&self) -> usize {
212 self.component_types.future_tables.len()
213 }
214
215 pub fn num_stream_tables(&self) -> usize {
218 self.component_types.stream_tables.len()
219 }
220
221 pub fn num_error_context_tables(&self) -> usize {
224 self.component_types.error_context_tables.len()
225 }
226
227 pub fn resources_mut(&mut self) -> &mut ResourcesBuilder {
229 &mut self.resources
230 }
231
232 pub fn resources_mut_and_types(&mut self) -> (&mut ResourcesBuilder, &ComponentTypes) {
235 (&mut self.resources, &self.component_types)
236 }
237
238 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 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 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
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
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
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
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
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 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 pub fn error_context_type(&mut self) -> Result<TypeComponentLocalErrorContextTableIndex> {
479 self.error_context_table_type()
480 }
481
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
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
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
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
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
568 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
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
588 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 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
605 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
613 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
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
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
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
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 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
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
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 pub fn resource_id(&mut self, id: ResourceId) -> TypeResourceTableIndex {
728 self.resources.convert(id, &mut self.component_types)
729 }
730
731 pub fn add_func_type(&mut self, ty: TypeFunc) -> TypeFuncIndex {
733 intern(&mut self.functions, &mut self.component_types.functions, ty)
734 }
735
736 pub fn add_record_type(&mut self, ty: TypeRecord) -> TypeRecordIndex {
738 intern_and_fill_flat_types!(self, records, ty)
739 }
740
741 pub fn add_flags_type(&mut self, ty: TypeFlags) -> TypeFlagsIndex {
743 intern_and_fill_flat_types!(self, flags, ty)
744 }
745
746 pub fn add_tuple_type(&mut self, ty: TypeTuple) -> TypeTupleIndex {
748 intern_and_fill_flat_types!(self, tuples, ty)
749 }
750
751 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 pub fn add_variant_type(&mut self, ty: TypeVariant) -> TypeVariantIndex {
761 intern_and_fill_flat_types!(self, variants, ty)
762 }
763
764 pub fn add_enum_type(&mut self, ty: TypeEnum) -> TypeEnumIndex {
766 intern_and_fill_flat_types!(self, enums, ty)
767 }
768
769 pub fn add_option_type(&mut self, ty: TypeOption) -> TypeOptionIndex {
771 intern_and_fill_flat_types!(self, options, ty)
772 }
773
774 pub fn add_result_type(&mut self, ty: TypeResult) -> TypeResultIndex {
776 intern_and_fill_flat_types!(self, results, ty)
777 }
778
779 pub fn add_list_type(&mut self, ty: TypeList) -> TypeListIndex {
781 intern_and_fill_flat_types!(self, lists, ty)
782 }
783
784 pub fn add_map_type(&mut self, ty: TypeMap) -> TypeMapIndex {
786 intern_and_fill_flat_types!(self, maps, ty)
787 }
788
789 pub fn add_future_type(&mut self, ty: TypeFuture) -> TypeFutureIndex {
791 intern(&mut self.futures, &mut self.component_types.futures, ty)
792 }
793
794 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 pub fn add_stream_type(&mut self, ty: TypeStream) -> TypeStreamIndex {
805 intern(&mut self.streams, &mut self.component_types.streams, ty)
806 }
807
808 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 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 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
831 self.component_types.canonical_abi(ty)
832 }
833
834 pub fn flat_types(&self, ty: &InterfaceType) -> Option<FlatTypes<'_>> {
840 self.type_information(ty).flat.as_flat_types()
841 }
842
843 pub fn ty_contains_borrow_resource(&self, ty: &InterfaceType) -> bool {
846 self.type_information(ty).has_borrow
847 }
848
849 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
905impl TypeConvert for ComponentTypesBuilder {
906 fn lookup_heap_type(&self, _index: wasmparser::UnpackedIndex) -> WasmHeapType {
907 panic!("heap types are not supported yet")
908 }
909
910 fn lookup_type_index(&self, _index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
911 panic!("typed references are not supported yet")
912 }
913}
914
915fn intern<T, U>(map: &mut HashMap<T, U>, list: &mut PrimaryMap<U, T>, item: T) -> U
916where
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
928struct FlatTypesStorage {
929 memory32: [FlatType; MAX_FLAT_TYPES],
934 memory64: [FlatType; MAX_FLAT_TYPES],
935
936 len: u8,
940}
941
942impl FlatTypesStorage {
943 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
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 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 len == MAX_FLAT_TYPES {
981 self.len += 1;
982 }
983 false
984 }
985 }
986}
987
988impl 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)]
1001struct 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
1014struct TypeInformation {
1015 depth: u32,
1016 flat: FlatTypesStorage,
1017 has_borrow: bool,
1018}
1019
1020impl TypeInformation {
1021 const fn new() -> TypeInformation {
1022 TypeInformation {
1023 depth: 0,
1024 flat: FlatTypesStorage::new(),
1025 has_borrow: false,
1026 }
1027 }
1028
1029 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
1038 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 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 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 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 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 None => {
1111 self.flat.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap();
1112 continue;
1113 }
1114 };
1115 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 dst32.join(*t32);
1139 dst64.join(*t64);
1140 } else {
1141 self.flat.len += 1;
1146 *dst32 = *t32;
1147 *dst64 = *t64;
1148 }
1149 }
1150 }
1151 }
1152
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
1157 fn tuples(&mut self, types: &ComponentTypesBuilder, ty: &TypeTuple) {
1158 self.build_record(ty.types.iter().map(|t| types.type_information(t)));
1159 }
1160
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
1179 fn enums(&mut self, _types: &ComponentTypesBuilder, _ty: &TypeEnum) {
1180 self.depth = 1;
1181 self.flat.push(FlatType::I32, FlatType::I32);
1182 }
1183
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
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
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
1214 fn options(&mut self, types: &ComponentTypesBuilder, ty: &TypeOption) {
1215 self.build_variant([None, Some(types.type_information(&ty.ty))]);
1216 }
1217
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
1225 fn maps(&mut self, types: &ComponentTypesBuilder, ty: &TypeMap) {
1226 *self = TypeInformation::string();
1229 let key_info = types.type_information(&ty.key);
1230 let value_info = types.type_information(&ty.value);
1231 self.depth = key_info.depth.max(value_info.depth) + 1;
1233 self.has_borrow = key_info.has_borrow || value_info.has_borrow;
1234 }
1235}