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