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