wasmtime_environ/component/
types.rs

1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::prelude::*;
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 ComponentTypes {
284    /// Returns the core wasm module types known within this component.
285    pub fn module_types(&self) -> &ModuleTypes {
286        self.module_types.as_ref().unwrap()
287    }
288
289    /// Returns the canonical ABI information about the specified type.
290    pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
291        match ty {
292            InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
293                &CanonicalAbiInfo::SCALAR1
294            }
295
296            InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
297
298            InterfaceType::U32
299            | InterfaceType::S32
300            | InterfaceType::Float32
301            | InterfaceType::Char
302            | InterfaceType::Own(_)
303            | InterfaceType::Borrow(_)
304            | InterfaceType::Future(_)
305            | InterfaceType::Stream(_)
306            | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
307
308            InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
309                &CanonicalAbiInfo::SCALAR8
310            }
311
312            InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
313
314            InterfaceType::Record(i) => &self[*i].abi,
315            InterfaceType::Variant(i) => &self[*i].abi,
316            InterfaceType::Tuple(i) => &self[*i].abi,
317            InterfaceType::Flags(i) => &self[*i].abi,
318            InterfaceType::Enum(i) => &self[*i].abi,
319            InterfaceType::Option(i) => &self[*i].abi,
320            InterfaceType::Result(i) => &self[*i].abi,
321        }
322    }
323
324    /// Adds a new `table` to the list of resource tables for this component.
325    pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
326        self.resource_tables.push(table)
327    }
328}
329
330macro_rules! impl_index {
331    ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
332        impl core::ops::Index<$ty> for ComponentTypes {
333            type Output = $output;
334            #[inline]
335            fn index(&self, idx: $ty) -> &$output {
336                &self.$field[idx]
337            }
338        }
339
340        #[cfg(feature = "compile")]
341        impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
342            type Output = $output;
343            #[inline]
344            fn index(&self, idx: $ty) -> &$output {
345                &self.component_types()[idx]
346            }
347        }
348    )*)
349}
350
351impl_index! {
352    impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
353    impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
354    impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
355    impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
356    impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
357    impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
358    impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
359    impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
360    impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
361    impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
362    impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
363    impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
364    impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
365    impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
366    impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
367    impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
368    impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
369    impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
370}
371
372// Additionally forward anything that can index `ModuleTypes` to `ModuleTypes`
373// (aka `SignatureIndex`)
374impl<T> Index<T> for ComponentTypes
375where
376    ModuleTypes: Index<T>,
377{
378    type Output = <ModuleTypes as Index<T>>::Output;
379    fn index(&self, idx: T) -> &Self::Output {
380        self.module_types.as_ref().unwrap().index(idx)
381    }
382}
383
384/// Types of imports and exports in the component model.
385///
386/// These types are what's available for import and export in components. Note
387/// that all indirect indices contained here are intended to be looked up
388/// through a sibling `ComponentTypes` structure.
389#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
390pub enum TypeDef {
391    /// A component and its type.
392    Component(TypeComponentIndex),
393    /// An instance of a component.
394    ComponentInstance(TypeComponentInstanceIndex),
395    /// A component function, not to be confused with a core wasm function.
396    ComponentFunc(TypeFuncIndex),
397    /// An type in an interface.
398    Interface(InterfaceType),
399    /// A core wasm module and its type.
400    Module(TypeModuleIndex),
401    /// A core wasm function using only core wasm types.
402    CoreFunc(ModuleInternedTypeIndex),
403    /// A resource type which operates on the specified resource table.
404    ///
405    /// Note that different resource tables may point to the same underlying
406    /// actual resource type, but that's a private detail.
407    Resource(TypeResourceTableIndex),
408}
409
410impl TypeDef {
411    /// A human readable description of what kind of type definition this is.
412    pub fn desc(&self) -> &str {
413        match self {
414            TypeDef::Component(_) => "component",
415            TypeDef::ComponentInstance(_) => "instance",
416            TypeDef::ComponentFunc(_) => "function",
417            TypeDef::Interface(_) => "type",
418            TypeDef::Module(_) => "core module",
419            TypeDef::CoreFunc(_) => "core function",
420            TypeDef::Resource(_) => "resource",
421        }
422    }
423}
424
425// NB: Note that maps below are stored as an `IndexMap` now but the order
426// typically does not matter. As a minor implementation detail we want the
427// serialization of this type to always be deterministic and using `IndexMap`
428// gets us that over using a `HashMap` for example.
429
430/// The type of a module in the component model.
431///
432/// Note that this is not to be confused with `TypeComponent` below. This is
433/// intended only for core wasm modules, not for components.
434#[derive(Serialize, Deserialize, Default)]
435pub struct TypeModule {
436    /// The values that this module imports.
437    ///
438    /// Note that the value of this map is a core wasm `EntityType`, not a
439    /// component model `TypeRef`. Additionally note that this reflects the
440    /// two-level namespace of core WebAssembly, but unlike core wasm all import
441    /// names are required to be unique to describe a module in the component
442    /// model.
443    pub imports: IndexMap<(String, String), EntityType>,
444
445    /// The values that this module exports.
446    ///
447    /// Note that the value of this map is the core wasm `EntityType` to
448    /// represent that core wasm items are being exported.
449    pub exports: IndexMap<String, EntityType>,
450}
451
452/// The type of a component in the component model.
453#[derive(Serialize, Deserialize, Default)]
454pub struct TypeComponent {
455    /// The named values that this component imports.
456    pub imports: IndexMap<String, TypeDef>,
457    /// The named values that this component exports.
458    pub exports: IndexMap<String, TypeDef>,
459}
460
461/// The type of a component instance in the component model, or an instantiated
462/// component.
463///
464/// Component instances only have exports of types in the component model.
465#[derive(Serialize, Deserialize, Default)]
466pub struct TypeComponentInstance {
467    /// The list of exports that this component has along with their types.
468    pub exports: IndexMap<String, TypeDef>,
469}
470
471/// A component function type in the component model.
472#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
473pub struct TypeFunc {
474    /// Names of parameters.
475    pub param_names: Vec<String>,
476    /// Parameters to the function represented as a tuple.
477    pub params: TypeTupleIndex,
478    /// Results of the function represented as a tuple.
479    pub results: TypeTupleIndex,
480    /// Expected core func type for memory32 `task.return` calls for this function.
481    pub task_return_type32: TypeTaskReturnIndex,
482    /// Expected core func type for memory64 `task.return` calls for this function.
483    pub task_return_type64: TypeTaskReturnIndex,
484}
485
486/// A core type representing the expected `task.return` signature for a
487/// component function.
488#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
489pub struct TypeTaskReturn {
490    /// Core type parameters for the signature.
491    ///
492    /// Note that `task.return` never returns results.
493    pub params: Vec<FlatType>,
494}
495
496/// All possible interface types that values can have.
497///
498/// This list represents an exhaustive listing of interface types and the
499/// shapes that they can take. Note that this enum is considered an "index" of
500/// forms where for non-primitive types a `ComponentTypes` structure is used to
501/// lookup further information based on the index found here.
502#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
503#[allow(missing_docs, reason = "self-describing variants")]
504pub enum InterfaceType {
505    Bool,
506    S8,
507    U8,
508    S16,
509    U16,
510    S32,
511    U32,
512    S64,
513    U64,
514    Float32,
515    Float64,
516    Char,
517    String,
518    Record(TypeRecordIndex),
519    Variant(TypeVariantIndex),
520    List(TypeListIndex),
521    Tuple(TypeTupleIndex),
522    Flags(TypeFlagsIndex),
523    Enum(TypeEnumIndex),
524    Option(TypeOptionIndex),
525    Result(TypeResultIndex),
526    Own(TypeResourceTableIndex),
527    Borrow(TypeResourceTableIndex),
528    Future(TypeFutureTableIndex),
529    Stream(TypeStreamTableIndex),
530    ErrorContext(TypeComponentLocalErrorContextTableIndex),
531}
532
533impl From<&wasmparser::PrimitiveValType> for InterfaceType {
534    fn from(ty: &wasmparser::PrimitiveValType) -> InterfaceType {
535        match ty {
536            wasmparser::PrimitiveValType::Bool => InterfaceType::Bool,
537            wasmparser::PrimitiveValType::S8 => InterfaceType::S8,
538            wasmparser::PrimitiveValType::U8 => InterfaceType::U8,
539            wasmparser::PrimitiveValType::S16 => InterfaceType::S16,
540            wasmparser::PrimitiveValType::U16 => InterfaceType::U16,
541            wasmparser::PrimitiveValType::S32 => InterfaceType::S32,
542            wasmparser::PrimitiveValType::U32 => InterfaceType::U32,
543            wasmparser::PrimitiveValType::S64 => InterfaceType::S64,
544            wasmparser::PrimitiveValType::U64 => InterfaceType::U64,
545            wasmparser::PrimitiveValType::F32 => InterfaceType::Float32,
546            wasmparser::PrimitiveValType::F64 => InterfaceType::Float64,
547            wasmparser::PrimitiveValType::Char => InterfaceType::Char,
548            wasmparser::PrimitiveValType::String => InterfaceType::String,
549        }
550    }
551}
552
553/// Bye information about a type in the canonical ABI, with metadata for both
554/// memory32 and memory64-based types.
555#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
556pub struct CanonicalAbiInfo {
557    /// The byte-size of this type in a 32-bit memory.
558    pub size32: u32,
559    /// The byte-alignment of this type in a 32-bit memory.
560    pub align32: u32,
561    /// The byte-size of this type in a 64-bit memory.
562    pub size64: u32,
563    /// The byte-alignment of this type in a 64-bit memory.
564    pub align64: u32,
565    /// The number of types it takes to represents this type in the "flat"
566    /// representation of the canonical abi where everything is passed as
567    /// immediate arguments or results.
568    ///
569    /// If this is `None` then this type is not representable in the flat ABI
570    /// because it is too large.
571    pub flat_count: Option<u8>,
572}
573
574impl Default for CanonicalAbiInfo {
575    fn default() -> CanonicalAbiInfo {
576        CanonicalAbiInfo {
577            size32: 0,
578            align32: 1,
579            size64: 0,
580            align64: 1,
581            flat_count: Some(0),
582        }
583    }
584}
585
586const fn align_to(a: u32, b: u32) -> u32 {
587    assert!(b.is_power_of_two());
588    (a + (b - 1)) & !(b - 1)
589}
590
591const fn max(a: u32, b: u32) -> u32 {
592    if a > b {
593        a
594    } else {
595        b
596    }
597}
598
599impl CanonicalAbiInfo {
600    /// ABI information for zero-sized types.
601    const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
602        size32: 0,
603        align32: 1,
604        size64: 0,
605        align64: 1,
606        flat_count: Some(0),
607    };
608
609    /// ABI information for one-byte scalars.
610    pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
611    /// ABI information for two-byte scalars.
612    pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
613    /// ABI information for four-byte scalars.
614    pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
615    /// ABI information for eight-byte scalars.
616    pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
617
618    const fn scalar(size: u32) -> CanonicalAbiInfo {
619        CanonicalAbiInfo {
620            size32: size,
621            align32: size,
622            size64: size,
623            align64: size,
624            flat_count: Some(1),
625        }
626    }
627
628    /// ABI information for lists/strings which are "pointer pairs"
629    pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
630        size32: 8,
631        align32: 4,
632        size64: 16,
633        align64: 8,
634        flat_count: Some(2),
635    };
636
637    /// Returns the abi for a record represented by the specified fields.
638    pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
639        // NB: this is basically a duplicate copy of
640        // `CanonicalAbiInfo::record_static` and the two should be kept in sync.
641
642        let mut ret = CanonicalAbiInfo::default();
643        for field in fields {
644            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
645            ret.align32 = ret.align32.max(field.align32);
646            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
647            ret.align64 = ret.align64.max(field.align64);
648            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
649        }
650        ret.size32 = align_to(ret.size32, ret.align32);
651        ret.size64 = align_to(ret.size64, ret.align64);
652        return ret;
653    }
654
655    /// Same as `CanonicalAbiInfo::record` but in a `const`-friendly context.
656    pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
657        // NB: this is basically a duplicate copy of `CanonicalAbiInfo::record`
658        // and the two should be kept in sync.
659
660        let mut ret = CanonicalAbiInfo::ZERO;
661        let mut i = 0;
662        while i < fields.len() {
663            let field = &fields[i];
664            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
665            ret.align32 = max(ret.align32, field.align32);
666            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
667            ret.align64 = max(ret.align64, field.align64);
668            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
669            i += 1;
670        }
671        ret.size32 = align_to(ret.size32, ret.align32);
672        ret.size64 = align_to(ret.size64, ret.align64);
673        return ret;
674    }
675
676    /// Returns the delta from the current value of `offset` to align properly
677    /// and read the next record field of type `abi` for 32-bit memories.
678    pub fn next_field32(&self, offset: &mut u32) -> u32 {
679        *offset = align_to(*offset, self.align32) + self.size32;
680        *offset - self.size32
681    }
682
683    /// Same as `next_field32`, but bumps a usize pointer
684    pub fn next_field32_size(&self, offset: &mut usize) -> usize {
685        let cur = u32::try_from(*offset).unwrap();
686        let cur = align_to(cur, self.align32) + self.size32;
687        *offset = usize::try_from(cur).unwrap();
688        usize::try_from(cur - self.size32).unwrap()
689    }
690
691    /// Returns the delta from the current value of `offset` to align properly
692    /// and read the next record field of type `abi` for 64-bit memories.
693    pub fn next_field64(&self, offset: &mut u32) -> u32 {
694        *offset = align_to(*offset, self.align64) + self.size64;
695        *offset - self.size64
696    }
697
698    /// Same as `next_field64`, but bumps a usize pointer
699    pub fn next_field64_size(&self, offset: &mut usize) -> usize {
700        let cur = u32::try_from(*offset).unwrap();
701        let cur = align_to(cur, self.align64) + self.size64;
702        *offset = usize::try_from(cur).unwrap();
703        usize::try_from(cur - self.size64).unwrap()
704    }
705
706    /// Returns ABI information for a structure which contains `count` flags.
707    pub const fn flags(count: usize) -> CanonicalAbiInfo {
708        let (size, align, flat_count) = match FlagsSize::from_count(count) {
709            FlagsSize::Size0 => (0, 1, 0),
710            FlagsSize::Size1 => (1, 1, 1),
711            FlagsSize::Size2 => (2, 2, 1),
712            FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
713        };
714        CanonicalAbiInfo {
715            size32: size,
716            align32: align,
717            size64: size,
718            align64: align,
719            flat_count: Some(flat_count),
720        }
721    }
722
723    fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
724    where
725        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
726        I::IntoIter: ExactSizeIterator,
727    {
728        // NB: this is basically a duplicate definition of
729        // `CanonicalAbiInfo::variant_static`, these should be kept in sync.
730
731        let cases = cases.into_iter();
732        let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
733        let mut max_size32 = 0;
734        let mut max_align32 = discrim_size;
735        let mut max_size64 = 0;
736        let mut max_align64 = discrim_size;
737        let mut max_case_count = Some(0);
738        for case in cases {
739            if let Some(case) = case {
740                max_size32 = max_size32.max(case.size32);
741                max_align32 = max_align32.max(case.align32);
742                max_size64 = max_size64.max(case.size64);
743                max_align64 = max_align64.max(case.align64);
744                max_case_count = max_flat(max_case_count, case.flat_count);
745            }
746        }
747        CanonicalAbiInfo {
748            size32: align_to(
749                align_to(discrim_size, max_align32) + max_size32,
750                max_align32,
751            ),
752            align32: max_align32,
753            size64: align_to(
754                align_to(discrim_size, max_align64) + max_size64,
755                max_align64,
756            ),
757            align64: max_align64,
758            flat_count: add_flat(max_case_count, Some(1)),
759        }
760    }
761
762    /// Same as `CanonicalAbiInfo::variant` but `const`-safe
763    pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
764        // NB: this is basically a duplicate definition of
765        // `CanonicalAbiInfo::variant`, these should be kept in sync.
766
767        let discrim_size = match DiscriminantSize::from_count(cases.len()) {
768            Some(size) => size.byte_size(),
769            None => unreachable!(),
770        };
771        let mut max_size32 = 0;
772        let mut max_align32 = discrim_size;
773        let mut max_size64 = 0;
774        let mut max_align64 = discrim_size;
775        let mut max_case_count = Some(0);
776        let mut i = 0;
777        while i < cases.len() {
778            let case = &cases[i];
779            if let Some(case) = case {
780                max_size32 = max(max_size32, case.size32);
781                max_align32 = max(max_align32, case.align32);
782                max_size64 = max(max_size64, case.size64);
783                max_align64 = max(max_align64, case.align64);
784                max_case_count = max_flat(max_case_count, case.flat_count);
785            }
786            i += 1;
787        }
788        CanonicalAbiInfo {
789            size32: align_to(
790                align_to(discrim_size, max_align32) + max_size32,
791                max_align32,
792            ),
793            align32: max_align32,
794            size64: align_to(
795                align_to(discrim_size, max_align64) + max_size64,
796                max_align64,
797            ),
798            align64: max_align64,
799            flat_count: add_flat(max_case_count, Some(1)),
800        }
801    }
802
803    /// Calculates ABI information for an enum with `cases` cases.
804    pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
805        // NB: this is basically a duplicate definition of
806        // `CanonicalAbiInfo::variant`, these should be kept in sync.
807
808        let discrim_size = match DiscriminantSize::from_count(cases) {
809            Some(size) => size.byte_size(),
810            None => unreachable!(),
811        };
812        CanonicalAbiInfo {
813            size32: discrim_size,
814            align32: discrim_size,
815            size64: discrim_size,
816            align64: discrim_size,
817            flat_count: Some(1),
818        }
819    }
820
821    /// Returns the flat count of this ABI information so long as the count
822    /// doesn't exceed the `max` specified.
823    pub fn flat_count(&self, max: usize) -> Option<usize> {
824        let flat = usize::from(self.flat_count?);
825        if flat > max {
826            None
827        } else {
828            Some(flat)
829        }
830    }
831}
832
833/// ABI information about the representation of a variant.
834#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
835pub struct VariantInfo {
836    /// The size of the discriminant used.
837    #[serde(with = "serde_discrim_size")]
838    pub size: DiscriminantSize,
839    /// The offset of the payload from the start of the variant in 32-bit
840    /// memories.
841    pub payload_offset32: u32,
842    /// The offset of the payload from the start of the variant in 64-bit
843    /// memories.
844    pub payload_offset64: u32,
845}
846
847impl VariantInfo {
848    /// Returns the abi information for a variant represented by the specified
849    /// cases.
850    pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
851    where
852        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
853        I::IntoIter: ExactSizeIterator,
854    {
855        let cases = cases.into_iter();
856        let size = DiscriminantSize::from_count(cases.len()).unwrap();
857        let abi = CanonicalAbiInfo::variant(cases);
858        (
859            VariantInfo {
860                size,
861                payload_offset32: align_to(u32::from(size), abi.align32),
862                payload_offset64: align_to(u32::from(size), abi.align64),
863            },
864            abi,
865        )
866    }
867    /// TODO
868    pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
869        let size = match DiscriminantSize::from_count(cases.len()) {
870            Some(size) => size,
871            None => unreachable!(),
872        };
873        let abi = CanonicalAbiInfo::variant_static(cases);
874        VariantInfo {
875            size,
876            payload_offset32: align_to(size.byte_size(), abi.align32),
877            payload_offset64: align_to(size.byte_size(), abi.align64),
878        }
879    }
880}
881
882mod serde_discrim_size {
883    use super::DiscriminantSize;
884    use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
885
886    pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
887    where
888        S: Serializer,
889    {
890        u32::from(*disc).serialize(ser)
891    }
892
893    pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
894    where
895        D: Deserializer<'de>,
896    {
897        match u32::deserialize(deser)? {
898            1 => Ok(DiscriminantSize::Size1),
899            2 => Ok(DiscriminantSize::Size2),
900            4 => Ok(DiscriminantSize::Size4),
901            _ => Err(D::Error::custom("invalid discriminant size")),
902        }
903    }
904}
905
906/// Shape of a "record" type in interface types.
907///
908/// This is equivalent to a `struct` in Rust.
909#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
910pub struct TypeRecord {
911    /// The fields that are contained within this struct type.
912    pub fields: Box<[RecordField]>,
913    /// Byte information about this type in the canonical ABI.
914    pub abi: CanonicalAbiInfo,
915}
916
917/// One field within a record.
918#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
919pub struct RecordField {
920    /// The name of the field, unique amongst all fields in a record.
921    pub name: String,
922    /// The type that this field contains.
923    pub ty: InterfaceType,
924}
925
926/// Shape of a "variant" type in interface types.
927///
928/// Variants are close to Rust `enum` declarations where a value is one of many
929/// cases and each case has a unique name and an optional payload associated
930/// with it.
931#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
932pub struct TypeVariant {
933    /// The list of cases that this variant can take.
934    pub cases: IndexMap<String, Option<InterfaceType>>,
935    /// Byte information about this type in the canonical ABI.
936    pub abi: CanonicalAbiInfo,
937    /// Byte information about this variant type.
938    pub info: VariantInfo,
939}
940
941impl Hash for TypeVariant {
942    fn hash<H: Hasher>(&self, h: &mut H) {
943        let TypeVariant { cases, abi, info } = self;
944        cases.len().hash(h);
945        for pair in cases {
946            pair.hash(h);
947        }
948        abi.hash(h);
949        info.hash(h);
950    }
951}
952
953/// Shape of a "tuple" type in interface types.
954///
955/// This is largely the same as a tuple in Rust, basically a record with
956/// unnamed fields.
957#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
958pub struct TypeTuple {
959    /// The types that are contained within this tuple.
960    pub types: Box<[InterfaceType]>,
961    /// Byte information about this type in the canonical ABI.
962    pub abi: CanonicalAbiInfo,
963}
964
965/// Shape of a "flags" type in interface types.
966///
967/// This can be thought of as a record-of-bools, although the representation is
968/// more efficient as bitflags.
969#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
970pub struct TypeFlags {
971    /// The names of all flags, all of which are unique.
972    pub names: IndexSet<String>,
973    /// Byte information about this type in the canonical ABI.
974    pub abi: CanonicalAbiInfo,
975}
976
977impl Hash for TypeFlags {
978    fn hash<H: Hasher>(&self, h: &mut H) {
979        let TypeFlags { names, abi } = self;
980        names.len().hash(h);
981        for name in names {
982            name.hash(h);
983        }
984        abi.hash(h);
985    }
986}
987
988/// Shape of an "enum" type in interface types, not to be confused with a Rust
989/// `enum` type.
990///
991/// In interface types enums are simply a bag of names, and can be seen as a
992/// variant where all payloads are `Unit`.
993#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
994pub struct TypeEnum {
995    /// The names of this enum, all of which are unique.
996    pub names: IndexSet<String>,
997    /// Byte information about this type in the canonical ABI.
998    pub abi: CanonicalAbiInfo,
999    /// Byte information about this variant type.
1000    pub info: VariantInfo,
1001}
1002
1003impl Hash for TypeEnum {
1004    fn hash<H: Hasher>(&self, h: &mut H) {
1005        let TypeEnum { names, abi, info } = self;
1006        names.len().hash(h);
1007        for name in names {
1008            name.hash(h);
1009        }
1010        abi.hash(h);
1011        info.hash(h);
1012    }
1013}
1014
1015/// Shape of an "option" interface type.
1016#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1017pub struct TypeOption {
1018    /// The `T` in `Result<T, E>`
1019    pub ty: InterfaceType,
1020    /// Byte information about this type in the canonical ABI.
1021    pub abi: CanonicalAbiInfo,
1022    /// Byte information about this variant type.
1023    pub info: VariantInfo,
1024}
1025
1026/// Shape of a "result" interface type.
1027#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1028pub struct TypeResult {
1029    /// The `T` in `Result<T, E>`
1030    pub ok: Option<InterfaceType>,
1031    /// The `E` in `Result<T, E>`
1032    pub err: Option<InterfaceType>,
1033    /// Byte information about this type in the canonical ABI.
1034    pub abi: CanonicalAbiInfo,
1035    /// Byte information about this variant type.
1036    pub info: VariantInfo,
1037}
1038
1039/// Shape of a "future" interface type.
1040#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1041pub struct TypeFuture {
1042    /// The `T` in `future<T>`
1043    pub payload: Option<InterfaceType>,
1044}
1045
1046/// Metadata about a future table added to a component.
1047#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1048pub struct TypeFutureTable {
1049    /// The specific future type this table is used for.
1050    pub ty: TypeFutureIndex,
1051    /// The specific component instance this table is used for.
1052    pub instance: RuntimeComponentInstanceIndex,
1053}
1054
1055/// Shape of a "stream" interface type.
1056#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1057pub struct TypeStream {
1058    /// The `T` in `stream<T>`
1059    pub payload: Option<InterfaceType>,
1060}
1061
1062/// Metadata about a stream table added to a component.
1063#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1064pub struct TypeStreamTable {
1065    /// The specific stream type this table is used for.
1066    pub ty: TypeStreamIndex,
1067    /// The specific component instance this table is used for.
1068    pub instance: RuntimeComponentInstanceIndex,
1069}
1070
1071/// Metadata about a error context table added to a component.
1072#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1073pub struct TypeErrorContextTable {
1074    /// The specific component instance this table is used for.
1075    pub instance: RuntimeComponentInstanceIndex,
1076}
1077
1078/// Metadata about a resource table added to a component.
1079#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1080pub struct TypeResourceTable {
1081    /// The original resource that this table contains.
1082    ///
1083    /// This is used when destroying resources within this table since this
1084    /// original definition will know how to execute destructors.
1085    pub ty: ResourceIndex,
1086
1087    /// The component instance that contains this resource table.
1088    pub instance: RuntimeComponentInstanceIndex,
1089}
1090
1091/// Shape of a "list" interface type.
1092#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1093pub struct TypeList {
1094    /// The element type of the list.
1095    pub element: InterfaceType,
1096}
1097
1098/// Maximum number of flat types, for either params or results.
1099pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1100    MAX_FLAT_PARAMS
1101} else {
1102    MAX_FLAT_RESULTS
1103};
1104
1105const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1106    const MAX: u8 = MAX_FLAT_TYPES as u8;
1107    let sum = match (a, b) {
1108        (Some(a), Some(b)) => match a.checked_add(b) {
1109            Some(c) => c,
1110            None => return None,
1111        },
1112        _ => return None,
1113    };
1114    if sum > MAX {
1115        None
1116    } else {
1117        Some(sum)
1118    }
1119}
1120
1121const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1122    match (a, b) {
1123        (Some(a), Some(b)) => {
1124            if a > b {
1125                Some(a)
1126            } else {
1127                Some(b)
1128            }
1129        }
1130        _ => None,
1131    }
1132}
1133
1134/// Flat representation of a type in just core wasm types.
1135pub struct FlatTypes<'a> {
1136    /// The flat representation of this type in 32-bit memories.
1137    pub memory32: &'a [FlatType],
1138    /// The flat representation of this type in 64-bit memories.
1139    pub memory64: &'a [FlatType],
1140}
1141
1142impl FlatTypes<'_> {
1143    /// Returns the number of flat types used to represent this type.
1144    ///
1145    /// Note that this length is the same regardless to the size of memory.
1146    pub fn len(&self) -> usize {
1147        assert_eq!(self.memory32.len(), self.memory64.len());
1148        self.memory32.len()
1149    }
1150}
1151
1152// Note that this is intentionally duplicated here to keep the size to 1 byte
1153// regardless to changes in the core wasm type system since this will only
1154// ever use integers/floats for the foreseeable future.
1155#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1156#[allow(missing_docs, reason = "self-describing variants")]
1157pub enum FlatType {
1158    I32,
1159    I64,
1160    F32,
1161    F64,
1162}