wasmtime_environ/component/
types.rs

1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::{prelude::*, TypeTrace};
3use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PrimaryMap};
4use core::hash::{Hash, Hasher};
5use core::ops::Index;
6use serde_derive::{Deserialize, Serialize};
7use wasmparser::component_types::ComponentAnyTypeId;
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9
10pub use crate::StaticModuleIndex;
11
12macro_rules! indices {
13    ($(
14        $(#[$a:meta])*
15        pub struct $name:ident(u32);
16    )*) => ($(
17        $(#[$a])*
18        #[derive(
19            Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
20            Serialize, Deserialize,
21        )]
22        #[repr(transparent)]
23        pub struct $name(u32);
24        cranelift_entity::entity_impl!($name);
25    )*);
26}
27
28indices! {
29    // ========================================================================
30    // These indices are used during compile time only when we're translating a
31    // component at this time. The actual indices are not persisted beyond the
32    // compile phase to when we're actually working with the component at
33    // runtime.
34
35    /// Index within a component's component type index space.
36    pub struct ComponentTypeIndex(u32);
37
38    /// Index within a component's module index space.
39    pub struct ModuleIndex(u32);
40
41    /// Index within a component's component index space.
42    pub struct ComponentIndex(u32);
43
44    /// Index within a component's module instance index space.
45    pub struct ModuleInstanceIndex(u32);
46
47    /// Index within a component's component instance index space.
48    pub struct ComponentInstanceIndex(u32);
49
50    /// Index within a component's component function index space.
51    pub struct ComponentFuncIndex(u32);
52
53    // ========================================================================
54    // These indices are used to lookup type information within a `TypeTables`
55    // structure. These represent generally deduplicated type information across
56    // an entire component and are a form of RTTI in a sense.
57
58    /// Index pointing to a component's type (exports/imports with
59    /// component-model types)
60    pub struct TypeComponentIndex(u32);
61
62    /// Index pointing to a component instance's type (exports with
63    /// component-model types, no imports)
64    pub struct TypeComponentInstanceIndex(u32);
65
66    /// Index pointing to a core wasm module's type (exports/imports with
67    /// core wasm types)
68    pub struct TypeModuleIndex(u32);
69
70    /// Index pointing to a component model function type with arguments/result
71    /// as interface types.
72    pub struct TypeFuncIndex(u32);
73
74    /// Index pointing to a record type in the component model (aka a struct).
75    pub struct TypeRecordIndex(u32);
76    /// Index pointing to a variant type in the component model (aka an enum).
77    pub struct TypeVariantIndex(u32);
78    /// Index pointing to a tuple type in the component model.
79    pub struct TypeTupleIndex(u32);
80    /// Index pointing to a flags type in the component model.
81    pub struct TypeFlagsIndex(u32);
82    /// Index pointing to an enum type in the component model.
83    pub struct TypeEnumIndex(u32);
84    /// Index pointing to an option type in the component model (aka a
85    /// `Option<T, E>`)
86    pub struct TypeOptionIndex(u32);
87    /// Index pointing to an result type in the component model (aka a
88    /// `Result<T, E>`)
89    pub struct TypeResultIndex(u32);
90    /// Index pointing to a list type in the component model.
91    pub struct TypeListIndex(u32);
92    /// Index pointing to a future type in the component model.
93    pub struct TypeFutureIndex(u32);
94    /// Index pointing to a future table within a component.
95    ///
96    /// This is analogous to `TypeResourceTableIndex` in that it tracks
97    /// ownership of futures within each (sub)component instance.
98    pub struct TypeFutureTableIndex(u32);
99    /// Index pointing to a stream type in the component model.
100    pub struct TypeStreamIndex(u32);
101    /// Index pointing to a stream table within a component.
102    ///
103    /// This is analogous to `TypeResourceTableIndex` in that it tracks
104    /// ownership of stream within each (sub)component instance.
105    pub struct TypeStreamTableIndex(u32);
106
107    /// Index pointing to a error context table within a component.
108    ///
109    /// This is analogous to `TypeResourceTableIndex` in that it tracks
110    /// ownership of error contexts within each (sub)component instance.
111    pub struct TypeComponentLocalErrorContextTableIndex(u32);
112
113    /// Index pointing to a (component) globally tracked error context table entry
114    ///
115    /// Unlike [`TypeComponentLocalErrorContextTableIndex`], this index refers to
116    /// the global state table for error contexts at the level of the entire component,
117    /// not just a subcomponent.
118    pub struct TypeComponentGlobalErrorContextTableIndex(u32);
119
120    /// Index pointing to an interned `task.return` type within a component.
121    pub struct TypeTaskReturnIndex(u32);
122
123    /// Index pointing to a resource table within a component.
124    ///
125    /// This is a Wasmtime-specific type index which isn't part of the component
126    /// model per-se (or at least not the binary format). This index represents
127    /// a pointer to a table of runtime information tracking state for resources
128    /// within a component. Tables are generated per-resource-per-component
129    /// meaning that if the exact same resource is imported into 4 subcomponents
130    /// then that's 5 tables: one for the defining component and one for each
131    /// subcomponent.
132    ///
133    /// All resource-related intrinsics operate on table-local indices which
134    /// indicate which table the intrinsic is modifying. Each resource table has
135    /// an origin resource type (defined by `ResourceIndex`) along with a
136    /// component instance that it's recorded for.
137    pub struct TypeResourceTableIndex(u32);
138
139    /// Index pointing to a resource within a component.
140    ///
141    /// This index space covers all unique resource type definitions. For
142    /// example all unique imports come first and then all locally-defined
143    /// resources come next. Note that this does not count the number of runtime
144    /// tables required to track resources (that's `TypeResourceTableIndex`
145    /// instead). Instead this is a count of the number of unique
146    /// `(type (resource (rep ..)))` declarations within a component, plus
147    /// imports.
148    ///
149    /// This is then used for correlating various information such as
150    /// destructors, origin information, etc.
151    pub struct ResourceIndex(u32);
152
153    /// Index pointing to a local resource defined within a component.
154    ///
155    /// This is similar to `FooIndex` and `DefinedFooIndex` for core wasm and
156    /// the idea here is that this is guaranteed to be a wasm-defined resource
157    /// which is connected to a component instance for example.
158    pub struct DefinedResourceIndex(u32);
159
160    // ========================================================================
161    // Index types used to identify modules and components during compilation.
162
163    /// Index into a "closed over variables" list for components used to
164    /// implement outer aliases. For more information on this see the
165    /// documentation for the `LexicalScope` structure.
166    pub struct ModuleUpvarIndex(u32);
167
168    /// Same as `ModuleUpvarIndex` but for components.
169    pub struct ComponentUpvarIndex(u32);
170
171    /// Same as `StaticModuleIndex` but for components.
172    pub struct StaticComponentIndex(u32);
173
174    // ========================================================================
175    // These indices are actually used at runtime when managing a component at
176    // this time.
177
178    /// Index that represents a core wasm instance created at runtime.
179    ///
180    /// This is used to keep track of when instances are created and is able to
181    /// refer back to previously created instances for exports and such.
182    pub struct RuntimeInstanceIndex(u32);
183
184    /// Same as `RuntimeInstanceIndex` but tracks component instances instead.
185    pub struct RuntimeComponentInstanceIndex(u32);
186
187    /// Used to index imports into a `Component`
188    ///
189    /// This does not correspond to anything in the binary format for the
190    /// component model.
191    pub struct ImportIndex(u32);
192
193    /// Index that represents a leaf item imported into a component where a
194    /// "leaf" means "not an instance".
195    ///
196    /// This does not correspond to anything in the binary format for the
197    /// component model.
198    pub struct RuntimeImportIndex(u32);
199
200    /// Index that represents a lowered host function and is used to represent
201    /// host function lowerings with options and such.
202    ///
203    /// This does not correspond to anything in the binary format for the
204    /// component model.
205    pub struct LoweredIndex(u32);
206
207    /// Index representing a linear memory extracted from a wasm instance
208    /// which is stored in a `VMComponentContext`. This is used to deduplicate
209    /// references to the same linear memory where it's only stored once in a
210    /// `VMComponentContext`.
211    ///
212    /// This does not correspond to anything in the binary format for the
213    /// component model.
214    pub struct RuntimeMemoryIndex(u32);
215
216    /// Same as `RuntimeMemoryIndex` except for the `realloc` function.
217    pub struct RuntimeReallocIndex(u32);
218
219    /// Same as `RuntimeMemoryIndex` except for the `callback` function.
220    pub struct RuntimeCallbackIndex(u32);
221
222    /// Same as `RuntimeMemoryIndex` except for the `post-return` function.
223    pub struct RuntimePostReturnIndex(u32);
224
225    /// Index for all trampolines that are compiled in Cranelift for a
226    /// component.
227    ///
228    /// This is used to point to various bits of metadata within a compiled
229    /// component and is stored in the final compilation artifact. This does not
230    /// have a direct correspondence to any wasm definition.
231    pub struct TrampolineIndex(u32);
232
233    /// An index into `Component::export_items` at the end of compilation.
234    pub struct ExportIndex(u32);
235}
236
237// Reexport for convenience some core-wasm indices which are also used in the
238// component model, typically for when aliasing exports of core wasm modules.
239pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
240
241/// Equivalent of `EntityIndex` but for the component model instead of core
242/// wasm.
243#[derive(Debug, Clone, Copy)]
244#[allow(missing_docs, reason = "self-describing variants")]
245pub enum ComponentItem {
246    Func(ComponentFuncIndex),
247    Module(ModuleIndex),
248    Component(ComponentIndex),
249    ComponentInstance(ComponentInstanceIndex),
250    Type(ComponentAnyTypeId),
251}
252
253/// Runtime information about the type information contained within a component.
254///
255/// One of these is created per top-level component which describes all of the
256/// types contained within the top-level component itself. Each sub-component
257/// will have a pointer to this value as well.
258#[derive(Default, Serialize, Deserialize)]
259pub struct ComponentTypes {
260    pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
261    pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
262    pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
263    pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
264    pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
265    pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
266    pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
267    pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
268    pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
269    pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
270    pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
271    pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
272    pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
273    pub(super) module_types: Option<ModuleTypes>,
274    pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
275    pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
276    pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
277    pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
278    pub(super) error_context_tables:
279        PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
280    pub(super) task_returns: PrimaryMap<TypeTaskReturnIndex, TypeTaskReturn>,
281}
282
283impl TypeTrace for ComponentTypes {
284    fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
285    where
286        F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
287    {
288        for (_, m) in &self.modules {
289            m.trace(func)?;
290        }
291        if let Some(m) = self.module_types.as_ref() {
292            m.trace(func)?;
293        }
294        Ok(())
295    }
296
297    fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
298    where
299        F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
300    {
301        for (_, m) in &mut self.modules {
302            m.trace_mut(func)?;
303        }
304        if let Some(m) = self.module_types.as_mut() {
305            m.trace_mut(func)?;
306        }
307        Ok(())
308    }
309}
310
311impl ComponentTypes {
312    /// Returns the core wasm module types known within this component.
313    pub fn module_types(&self) -> &ModuleTypes {
314        self.module_types.as_ref().unwrap()
315    }
316
317    /// Returns the core wasm module types known within this component.
318    pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
319        self.module_types.as_mut().unwrap()
320    }
321
322    /// Returns the canonical ABI information about the specified type.
323    pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
324        match ty {
325            InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
326                &CanonicalAbiInfo::SCALAR1
327            }
328
329            InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
330
331            InterfaceType::U32
332            | InterfaceType::S32
333            | InterfaceType::Float32
334            | InterfaceType::Char
335            | InterfaceType::Own(_)
336            | InterfaceType::Borrow(_)
337            | InterfaceType::Future(_)
338            | InterfaceType::Stream(_)
339            | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
340
341            InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
342                &CanonicalAbiInfo::SCALAR8
343            }
344
345            InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
346
347            InterfaceType::Record(i) => &self[*i].abi,
348            InterfaceType::Variant(i) => &self[*i].abi,
349            InterfaceType::Tuple(i) => &self[*i].abi,
350            InterfaceType::Flags(i) => &self[*i].abi,
351            InterfaceType::Enum(i) => &self[*i].abi,
352            InterfaceType::Option(i) => &self[*i].abi,
353            InterfaceType::Result(i) => &self[*i].abi,
354        }
355    }
356
357    /// Adds a new `table` to the list of resource tables for this component.
358    pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
359        self.resource_tables.push(table)
360    }
361}
362
363macro_rules! impl_index {
364    ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
365        impl core::ops::Index<$ty> for ComponentTypes {
366            type Output = $output;
367            #[inline]
368            fn index(&self, idx: $ty) -> &$output {
369                &self.$field[idx]
370            }
371        }
372
373        #[cfg(feature = "compile")]
374        impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
375            type Output = $output;
376            #[inline]
377            fn index(&self, idx: $ty) -> &$output {
378                &self.component_types()[idx]
379            }
380        }
381    )*)
382}
383
384impl_index! {
385    impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
386    impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
387    impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
388    impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
389    impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
390    impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
391    impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
392    impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
393    impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
394    impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
395    impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
396    impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
397    impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
398    impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
399    impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
400    impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
401    impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
402    impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
403}
404
405// Additionally forward anything that can index `ModuleTypes` to `ModuleTypes`
406// (aka `SignatureIndex`)
407impl<T> Index<T> for ComponentTypes
408where
409    ModuleTypes: Index<T>,
410{
411    type Output = <ModuleTypes as Index<T>>::Output;
412    fn index(&self, idx: T) -> &Self::Output {
413        self.module_types.as_ref().unwrap().index(idx)
414    }
415}
416
417/// Types of imports and exports in the component model.
418///
419/// These types are what's available for import and export in components. Note
420/// that all indirect indices contained here are intended to be looked up
421/// through a sibling `ComponentTypes` structure.
422#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
423pub enum TypeDef {
424    /// A component and its type.
425    Component(TypeComponentIndex),
426    /// An instance of a component.
427    ComponentInstance(TypeComponentInstanceIndex),
428    /// A component function, not to be confused with a core wasm function.
429    ComponentFunc(TypeFuncIndex),
430    /// An type in an interface.
431    Interface(InterfaceType),
432    /// A core wasm module and its type.
433    Module(TypeModuleIndex),
434    /// A core wasm function using only core wasm types.
435    CoreFunc(ModuleInternedTypeIndex),
436    /// A resource type which operates on the specified resource table.
437    ///
438    /// Note that different resource tables may point to the same underlying
439    /// actual resource type, but that's a private detail.
440    Resource(TypeResourceTableIndex),
441}
442
443impl TypeDef {
444    /// A human readable description of what kind of type definition this is.
445    pub fn desc(&self) -> &str {
446        match self {
447            TypeDef::Component(_) => "component",
448            TypeDef::ComponentInstance(_) => "instance",
449            TypeDef::ComponentFunc(_) => "function",
450            TypeDef::Interface(_) => "type",
451            TypeDef::Module(_) => "core module",
452            TypeDef::CoreFunc(_) => "core function",
453            TypeDef::Resource(_) => "resource",
454        }
455    }
456}
457
458// NB: Note that maps below are stored as an `IndexMap` now but the order
459// typically does not matter. As a minor implementation detail we want the
460// serialization of this type to always be deterministic and using `IndexMap`
461// gets us that over using a `HashMap` for example.
462
463/// The type of a module in the component model.
464///
465/// Note that this is not to be confused with `TypeComponent` below. This is
466/// intended only for core wasm modules, not for components.
467#[derive(Serialize, Deserialize, Default)]
468pub struct TypeModule {
469    /// The values that this module imports.
470    ///
471    /// Note that the value of this map is a core wasm `EntityType`, not a
472    /// component model `TypeRef`. Additionally note that this reflects the
473    /// two-level namespace of core WebAssembly, but unlike core wasm all import
474    /// names are required to be unique to describe a module in the component
475    /// model.
476    pub imports: IndexMap<(String, String), EntityType>,
477
478    /// The values that this module exports.
479    ///
480    /// Note that the value of this map is the core wasm `EntityType` to
481    /// represent that core wasm items are being exported.
482    pub exports: IndexMap<String, EntityType>,
483}
484
485impl TypeTrace for TypeModule {
486    fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
487    where
488        F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
489    {
490        for ty in self.imports.values() {
491            ty.trace(func)?;
492        }
493        for ty in self.exports.values() {
494            ty.trace(func)?;
495        }
496        Ok(())
497    }
498
499    fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
500    where
501        F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
502    {
503        for ty in self.imports.values_mut() {
504            ty.trace_mut(func)?;
505        }
506        for ty in self.exports.values_mut() {
507            ty.trace_mut(func)?;
508        }
509        Ok(())
510    }
511}
512
513/// The type of a component in the component model.
514#[derive(Serialize, Deserialize, Default)]
515pub struct TypeComponent {
516    /// The named values that this component imports.
517    pub imports: IndexMap<String, TypeDef>,
518    /// The named values that this component exports.
519    pub exports: IndexMap<String, TypeDef>,
520}
521
522/// The type of a component instance in the component model, or an instantiated
523/// component.
524///
525/// Component instances only have exports of types in the component model.
526#[derive(Serialize, Deserialize, Default)]
527pub struct TypeComponentInstance {
528    /// The list of exports that this component has along with their types.
529    pub exports: IndexMap<String, TypeDef>,
530}
531
532/// A component function type in the component model.
533#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
534pub struct TypeFunc {
535    /// Names of parameters.
536    pub param_names: Vec<String>,
537    /// Parameters to the function represented as a tuple.
538    pub params: TypeTupleIndex,
539    /// Results of the function represented as a tuple.
540    pub results: TypeTupleIndex,
541    /// Expected core func type for memory32 `task.return` calls for this function.
542    pub task_return_type32: TypeTaskReturnIndex,
543    /// Expected core func type for memory64 `task.return` calls for this function.
544    pub task_return_type64: TypeTaskReturnIndex,
545}
546
547/// A core type representing the expected `task.return` signature for a
548/// component function.
549#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
550pub struct TypeTaskReturn {
551    /// Core type parameters for the signature.
552    ///
553    /// Note that `task.return` never returns results.
554    pub params: Vec<FlatType>,
555}
556
557/// All possible interface types that values can have.
558///
559/// This list represents an exhaustive listing of interface types and the
560/// shapes that they can take. Note that this enum is considered an "index" of
561/// forms where for non-primitive types a `ComponentTypes` structure is used to
562/// lookup further information based on the index found here.
563#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
564#[allow(missing_docs, reason = "self-describing variants")]
565pub enum InterfaceType {
566    Bool,
567    S8,
568    U8,
569    S16,
570    U16,
571    S32,
572    U32,
573    S64,
574    U64,
575    Float32,
576    Float64,
577    Char,
578    String,
579    Record(TypeRecordIndex),
580    Variant(TypeVariantIndex),
581    List(TypeListIndex),
582    Tuple(TypeTupleIndex),
583    Flags(TypeFlagsIndex),
584    Enum(TypeEnumIndex),
585    Option(TypeOptionIndex),
586    Result(TypeResultIndex),
587    Own(TypeResourceTableIndex),
588    Borrow(TypeResourceTableIndex),
589    Future(TypeFutureTableIndex),
590    Stream(TypeStreamTableIndex),
591    ErrorContext(TypeComponentLocalErrorContextTableIndex),
592}
593
594impl From<&wasmparser::PrimitiveValType> for InterfaceType {
595    fn from(ty: &wasmparser::PrimitiveValType) -> InterfaceType {
596        match ty {
597            wasmparser::PrimitiveValType::Bool => InterfaceType::Bool,
598            wasmparser::PrimitiveValType::S8 => InterfaceType::S8,
599            wasmparser::PrimitiveValType::U8 => InterfaceType::U8,
600            wasmparser::PrimitiveValType::S16 => InterfaceType::S16,
601            wasmparser::PrimitiveValType::U16 => InterfaceType::U16,
602            wasmparser::PrimitiveValType::S32 => InterfaceType::S32,
603            wasmparser::PrimitiveValType::U32 => InterfaceType::U32,
604            wasmparser::PrimitiveValType::S64 => InterfaceType::S64,
605            wasmparser::PrimitiveValType::U64 => InterfaceType::U64,
606            wasmparser::PrimitiveValType::F32 => InterfaceType::Float32,
607            wasmparser::PrimitiveValType::F64 => InterfaceType::Float64,
608            wasmparser::PrimitiveValType::Char => InterfaceType::Char,
609            wasmparser::PrimitiveValType::String => InterfaceType::String,
610        }
611    }
612}
613
614/// Bye information about a type in the canonical ABI, with metadata for both
615/// memory32 and memory64-based types.
616#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
617pub struct CanonicalAbiInfo {
618    /// The byte-size of this type in a 32-bit memory.
619    pub size32: u32,
620    /// The byte-alignment of this type in a 32-bit memory.
621    pub align32: u32,
622    /// The byte-size of this type in a 64-bit memory.
623    pub size64: u32,
624    /// The byte-alignment of this type in a 64-bit memory.
625    pub align64: u32,
626    /// The number of types it takes to represents this type in the "flat"
627    /// representation of the canonical abi where everything is passed as
628    /// immediate arguments or results.
629    ///
630    /// If this is `None` then this type is not representable in the flat ABI
631    /// because it is too large.
632    pub flat_count: Option<u8>,
633}
634
635impl Default for CanonicalAbiInfo {
636    fn default() -> CanonicalAbiInfo {
637        CanonicalAbiInfo {
638            size32: 0,
639            align32: 1,
640            size64: 0,
641            align64: 1,
642            flat_count: Some(0),
643        }
644    }
645}
646
647const fn align_to(a: u32, b: u32) -> u32 {
648    assert!(b.is_power_of_two());
649    (a + (b - 1)) & !(b - 1)
650}
651
652const fn max(a: u32, b: u32) -> u32 {
653    if a > b {
654        a
655    } else {
656        b
657    }
658}
659
660impl CanonicalAbiInfo {
661    /// ABI information for zero-sized types.
662    const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
663        size32: 0,
664        align32: 1,
665        size64: 0,
666        align64: 1,
667        flat_count: Some(0),
668    };
669
670    /// ABI information for one-byte scalars.
671    pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
672    /// ABI information for two-byte scalars.
673    pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
674    /// ABI information for four-byte scalars.
675    pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
676    /// ABI information for eight-byte scalars.
677    pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
678
679    const fn scalar(size: u32) -> CanonicalAbiInfo {
680        CanonicalAbiInfo {
681            size32: size,
682            align32: size,
683            size64: size,
684            align64: size,
685            flat_count: Some(1),
686        }
687    }
688
689    /// ABI information for lists/strings which are "pointer pairs"
690    pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
691        size32: 8,
692        align32: 4,
693        size64: 16,
694        align64: 8,
695        flat_count: Some(2),
696    };
697
698    /// Returns the abi for a record represented by the specified fields.
699    pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
700        // NB: this is basically a duplicate copy of
701        // `CanonicalAbiInfo::record_static` and the two should be kept in sync.
702
703        let mut ret = CanonicalAbiInfo::default();
704        for field in fields {
705            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
706            ret.align32 = ret.align32.max(field.align32);
707            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
708            ret.align64 = ret.align64.max(field.align64);
709            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
710        }
711        ret.size32 = align_to(ret.size32, ret.align32);
712        ret.size64 = align_to(ret.size64, ret.align64);
713        return ret;
714    }
715
716    /// Same as `CanonicalAbiInfo::record` but in a `const`-friendly context.
717    pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
718        // NB: this is basically a duplicate copy of `CanonicalAbiInfo::record`
719        // and the two should be kept in sync.
720
721        let mut ret = CanonicalAbiInfo::ZERO;
722        let mut i = 0;
723        while i < fields.len() {
724            let field = &fields[i];
725            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
726            ret.align32 = max(ret.align32, field.align32);
727            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
728            ret.align64 = max(ret.align64, field.align64);
729            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
730            i += 1;
731        }
732        ret.size32 = align_to(ret.size32, ret.align32);
733        ret.size64 = align_to(ret.size64, ret.align64);
734        return ret;
735    }
736
737    /// Returns the delta from the current value of `offset` to align properly
738    /// and read the next record field of type `abi` for 32-bit memories.
739    pub fn next_field32(&self, offset: &mut u32) -> u32 {
740        *offset = align_to(*offset, self.align32) + self.size32;
741        *offset - self.size32
742    }
743
744    /// Same as `next_field32`, but bumps a usize pointer
745    pub fn next_field32_size(&self, offset: &mut usize) -> usize {
746        let cur = u32::try_from(*offset).unwrap();
747        let cur = align_to(cur, self.align32) + self.size32;
748        *offset = usize::try_from(cur).unwrap();
749        usize::try_from(cur - self.size32).unwrap()
750    }
751
752    /// Returns the delta from the current value of `offset` to align properly
753    /// and read the next record field of type `abi` for 64-bit memories.
754    pub fn next_field64(&self, offset: &mut u32) -> u32 {
755        *offset = align_to(*offset, self.align64) + self.size64;
756        *offset - self.size64
757    }
758
759    /// Same as `next_field64`, but bumps a usize pointer
760    pub fn next_field64_size(&self, offset: &mut usize) -> usize {
761        let cur = u32::try_from(*offset).unwrap();
762        let cur = align_to(cur, self.align64) + self.size64;
763        *offset = usize::try_from(cur).unwrap();
764        usize::try_from(cur - self.size64).unwrap()
765    }
766
767    /// Returns ABI information for a structure which contains `count` flags.
768    pub const fn flags(count: usize) -> CanonicalAbiInfo {
769        let (size, align, flat_count) = match FlagsSize::from_count(count) {
770            FlagsSize::Size0 => (0, 1, 0),
771            FlagsSize::Size1 => (1, 1, 1),
772            FlagsSize::Size2 => (2, 2, 1),
773            FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
774        };
775        CanonicalAbiInfo {
776            size32: size,
777            align32: align,
778            size64: size,
779            align64: align,
780            flat_count: Some(flat_count),
781        }
782    }
783
784    fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
785    where
786        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
787        I::IntoIter: ExactSizeIterator,
788    {
789        // NB: this is basically a duplicate definition of
790        // `CanonicalAbiInfo::variant_static`, these should be kept in sync.
791
792        let cases = cases.into_iter();
793        let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
794        let mut max_size32 = 0;
795        let mut max_align32 = discrim_size;
796        let mut max_size64 = 0;
797        let mut max_align64 = discrim_size;
798        let mut max_case_count = Some(0);
799        for case in cases {
800            if let Some(case) = case {
801                max_size32 = max_size32.max(case.size32);
802                max_align32 = max_align32.max(case.align32);
803                max_size64 = max_size64.max(case.size64);
804                max_align64 = max_align64.max(case.align64);
805                max_case_count = max_flat(max_case_count, case.flat_count);
806            }
807        }
808        CanonicalAbiInfo {
809            size32: align_to(
810                align_to(discrim_size, max_align32) + max_size32,
811                max_align32,
812            ),
813            align32: max_align32,
814            size64: align_to(
815                align_to(discrim_size, max_align64) + max_size64,
816                max_align64,
817            ),
818            align64: max_align64,
819            flat_count: add_flat(max_case_count, Some(1)),
820        }
821    }
822
823    /// Same as `CanonicalAbiInfo::variant` but `const`-safe
824    pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
825        // NB: this is basically a duplicate definition of
826        // `CanonicalAbiInfo::variant`, these should be kept in sync.
827
828        let discrim_size = match DiscriminantSize::from_count(cases.len()) {
829            Some(size) => size.byte_size(),
830            None => unreachable!(),
831        };
832        let mut max_size32 = 0;
833        let mut max_align32 = discrim_size;
834        let mut max_size64 = 0;
835        let mut max_align64 = discrim_size;
836        let mut max_case_count = Some(0);
837        let mut i = 0;
838        while i < cases.len() {
839            let case = &cases[i];
840            if let Some(case) = case {
841                max_size32 = max(max_size32, case.size32);
842                max_align32 = max(max_align32, case.align32);
843                max_size64 = max(max_size64, case.size64);
844                max_align64 = max(max_align64, case.align64);
845                max_case_count = max_flat(max_case_count, case.flat_count);
846            }
847            i += 1;
848        }
849        CanonicalAbiInfo {
850            size32: align_to(
851                align_to(discrim_size, max_align32) + max_size32,
852                max_align32,
853            ),
854            align32: max_align32,
855            size64: align_to(
856                align_to(discrim_size, max_align64) + max_size64,
857                max_align64,
858            ),
859            align64: max_align64,
860            flat_count: add_flat(max_case_count, Some(1)),
861        }
862    }
863
864    /// Calculates ABI information for an enum with `cases` cases.
865    pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
866        // NB: this is basically a duplicate definition of
867        // `CanonicalAbiInfo::variant`, these should be kept in sync.
868
869        let discrim_size = match DiscriminantSize::from_count(cases) {
870            Some(size) => size.byte_size(),
871            None => unreachable!(),
872        };
873        CanonicalAbiInfo {
874            size32: discrim_size,
875            align32: discrim_size,
876            size64: discrim_size,
877            align64: discrim_size,
878            flat_count: Some(1),
879        }
880    }
881
882    /// Returns the flat count of this ABI information so long as the count
883    /// doesn't exceed the `max` specified.
884    pub fn flat_count(&self, max: usize) -> Option<usize> {
885        let flat = usize::from(self.flat_count?);
886        if flat > max {
887            None
888        } else {
889            Some(flat)
890        }
891    }
892}
893
894/// ABI information about the representation of a variant.
895#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
896pub struct VariantInfo {
897    /// The size of the discriminant used.
898    #[serde(with = "serde_discrim_size")]
899    pub size: DiscriminantSize,
900    /// The offset of the payload from the start of the variant in 32-bit
901    /// memories.
902    pub payload_offset32: u32,
903    /// The offset of the payload from the start of the variant in 64-bit
904    /// memories.
905    pub payload_offset64: u32,
906}
907
908impl VariantInfo {
909    /// Returns the abi information for a variant represented by the specified
910    /// cases.
911    pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
912    where
913        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
914        I::IntoIter: ExactSizeIterator,
915    {
916        let cases = cases.into_iter();
917        let size = DiscriminantSize::from_count(cases.len()).unwrap();
918        let abi = CanonicalAbiInfo::variant(cases);
919        (
920            VariantInfo {
921                size,
922                payload_offset32: align_to(u32::from(size), abi.align32),
923                payload_offset64: align_to(u32::from(size), abi.align64),
924            },
925            abi,
926        )
927    }
928    /// TODO
929    pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
930        let size = match DiscriminantSize::from_count(cases.len()) {
931            Some(size) => size,
932            None => unreachable!(),
933        };
934        let abi = CanonicalAbiInfo::variant_static(cases);
935        VariantInfo {
936            size,
937            payload_offset32: align_to(size.byte_size(), abi.align32),
938            payload_offset64: align_to(size.byte_size(), abi.align64),
939        }
940    }
941}
942
943mod serde_discrim_size {
944    use super::DiscriminantSize;
945    use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
946
947    pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
948    where
949        S: Serializer,
950    {
951        u32::from(*disc).serialize(ser)
952    }
953
954    pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
955    where
956        D: Deserializer<'de>,
957    {
958        match u32::deserialize(deser)? {
959            1 => Ok(DiscriminantSize::Size1),
960            2 => Ok(DiscriminantSize::Size2),
961            4 => Ok(DiscriminantSize::Size4),
962            _ => Err(D::Error::custom("invalid discriminant size")),
963        }
964    }
965}
966
967/// Shape of a "record" type in interface types.
968///
969/// This is equivalent to a `struct` in Rust.
970#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
971pub struct TypeRecord {
972    /// The fields that are contained within this struct type.
973    pub fields: Box<[RecordField]>,
974    /// Byte information about this type in the canonical ABI.
975    pub abi: CanonicalAbiInfo,
976}
977
978/// One field within a record.
979#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
980pub struct RecordField {
981    /// The name of the field, unique amongst all fields in a record.
982    pub name: String,
983    /// The type that this field contains.
984    pub ty: InterfaceType,
985}
986
987/// Shape of a "variant" type in interface types.
988///
989/// Variants are close to Rust `enum` declarations where a value is one of many
990/// cases and each case has a unique name and an optional payload associated
991/// with it.
992#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
993pub struct TypeVariant {
994    /// The list of cases that this variant can take.
995    pub cases: IndexMap<String, Option<InterfaceType>>,
996    /// Byte information about this type in the canonical ABI.
997    pub abi: CanonicalAbiInfo,
998    /// Byte information about this variant type.
999    pub info: VariantInfo,
1000}
1001
1002impl Hash for TypeVariant {
1003    fn hash<H: Hasher>(&self, h: &mut H) {
1004        let TypeVariant { cases, abi, info } = self;
1005        cases.len().hash(h);
1006        for pair in cases {
1007            pair.hash(h);
1008        }
1009        abi.hash(h);
1010        info.hash(h);
1011    }
1012}
1013
1014/// Shape of a "tuple" type in interface types.
1015///
1016/// This is largely the same as a tuple in Rust, basically a record with
1017/// unnamed fields.
1018#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1019pub struct TypeTuple {
1020    /// The types that are contained within this tuple.
1021    pub types: Box<[InterfaceType]>,
1022    /// Byte information about this type in the canonical ABI.
1023    pub abi: CanonicalAbiInfo,
1024}
1025
1026/// Shape of a "flags" type in interface types.
1027///
1028/// This can be thought of as a record-of-bools, although the representation is
1029/// more efficient as bitflags.
1030#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1031pub struct TypeFlags {
1032    /// The names of all flags, all of which are unique.
1033    pub names: IndexSet<String>,
1034    /// Byte information about this type in the canonical ABI.
1035    pub abi: CanonicalAbiInfo,
1036}
1037
1038impl Hash for TypeFlags {
1039    fn hash<H: Hasher>(&self, h: &mut H) {
1040        let TypeFlags { names, abi } = self;
1041        names.len().hash(h);
1042        for name in names {
1043            name.hash(h);
1044        }
1045        abi.hash(h);
1046    }
1047}
1048
1049/// Shape of an "enum" type in interface types, not to be confused with a Rust
1050/// `enum` type.
1051///
1052/// In interface types enums are simply a bag of names, and can be seen as a
1053/// variant where all payloads are `Unit`.
1054#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1055pub struct TypeEnum {
1056    /// The names of this enum, all of which are unique.
1057    pub names: IndexSet<String>,
1058    /// Byte information about this type in the canonical ABI.
1059    pub abi: CanonicalAbiInfo,
1060    /// Byte information about this variant type.
1061    pub info: VariantInfo,
1062}
1063
1064impl Hash for TypeEnum {
1065    fn hash<H: Hasher>(&self, h: &mut H) {
1066        let TypeEnum { names, abi, info } = self;
1067        names.len().hash(h);
1068        for name in names {
1069            name.hash(h);
1070        }
1071        abi.hash(h);
1072        info.hash(h);
1073    }
1074}
1075
1076/// Shape of an "option" interface type.
1077#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1078pub struct TypeOption {
1079    /// The `T` in `Result<T, E>`
1080    pub ty: InterfaceType,
1081    /// Byte information about this type in the canonical ABI.
1082    pub abi: CanonicalAbiInfo,
1083    /// Byte information about this variant type.
1084    pub info: VariantInfo,
1085}
1086
1087/// Shape of a "result" interface type.
1088#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1089pub struct TypeResult {
1090    /// The `T` in `Result<T, E>`
1091    pub ok: Option<InterfaceType>,
1092    /// The `E` in `Result<T, E>`
1093    pub err: Option<InterfaceType>,
1094    /// Byte information about this type in the canonical ABI.
1095    pub abi: CanonicalAbiInfo,
1096    /// Byte information about this variant type.
1097    pub info: VariantInfo,
1098}
1099
1100/// Shape of a "future" interface type.
1101#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1102pub struct TypeFuture {
1103    /// The `T` in `future<T>`
1104    pub payload: Option<InterfaceType>,
1105}
1106
1107/// Metadata about a future table added to a component.
1108#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1109pub struct TypeFutureTable {
1110    /// The specific future type this table is used for.
1111    pub ty: TypeFutureIndex,
1112    /// The specific component instance this table is used for.
1113    pub instance: RuntimeComponentInstanceIndex,
1114}
1115
1116/// Shape of a "stream" interface type.
1117#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1118pub struct TypeStream {
1119    /// The `T` in `stream<T>`
1120    pub payload: Option<InterfaceType>,
1121}
1122
1123/// Metadata about a stream table added to a component.
1124#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1125pub struct TypeStreamTable {
1126    /// The specific stream type this table is used for.
1127    pub ty: TypeStreamIndex,
1128    /// The specific component instance this table is used for.
1129    pub instance: RuntimeComponentInstanceIndex,
1130}
1131
1132/// Metadata about a error context table added to a component.
1133#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1134pub struct TypeErrorContextTable {
1135    /// The specific component instance this table is used for.
1136    pub instance: RuntimeComponentInstanceIndex,
1137}
1138
1139/// Metadata about a resource table added to a component.
1140#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1141pub struct TypeResourceTable {
1142    /// The original resource that this table contains.
1143    ///
1144    /// This is used when destroying resources within this table since this
1145    /// original definition will know how to execute destructors.
1146    pub ty: ResourceIndex,
1147
1148    /// The component instance that contains this resource table.
1149    pub instance: RuntimeComponentInstanceIndex,
1150}
1151
1152/// Shape of a "list" interface type.
1153#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1154pub struct TypeList {
1155    /// The element type of the list.
1156    pub element: InterfaceType,
1157}
1158
1159/// Maximum number of flat types, for either params or results.
1160pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1161    MAX_FLAT_PARAMS
1162} else {
1163    MAX_FLAT_RESULTS
1164};
1165
1166const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1167    const MAX: u8 = MAX_FLAT_TYPES as u8;
1168    let sum = match (a, b) {
1169        (Some(a), Some(b)) => match a.checked_add(b) {
1170            Some(c) => c,
1171            None => return None,
1172        },
1173        _ => return None,
1174    };
1175    if sum > MAX {
1176        None
1177    } else {
1178        Some(sum)
1179    }
1180}
1181
1182const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1183    match (a, b) {
1184        (Some(a), Some(b)) => {
1185            if a > b {
1186                Some(a)
1187            } else {
1188                Some(b)
1189            }
1190        }
1191        _ => None,
1192    }
1193}
1194
1195/// Flat representation of a type in just core wasm types.
1196pub struct FlatTypes<'a> {
1197    /// The flat representation of this type in 32-bit memories.
1198    pub memory32: &'a [FlatType],
1199    /// The flat representation of this type in 64-bit memories.
1200    pub memory64: &'a [FlatType],
1201}
1202
1203impl FlatTypes<'_> {
1204    /// Returns the number of flat types used to represent this type.
1205    ///
1206    /// Note that this length is the same regardless to the size of memory.
1207    pub fn len(&self) -> usize {
1208        assert_eq!(self.memory32.len(), self.memory64.len());
1209        self.memory32.len()
1210    }
1211}
1212
1213// Note that this is intentionally duplicated here to keep the size to 1 byte
1214// regardless to changes in the core wasm type system since this will only
1215// ever use integers/floats for the foreseeable future.
1216#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1217#[allow(missing_docs, reason = "self-describing variants")]
1218pub enum FlatType {
1219    I32,
1220    I64,
1221    F32,
1222    F64,
1223}