wasmtime_environ/component/
info.rs

1// General runtime type-information about a component.
2//
3// Compared to the `Module` structure for core wasm this type is pretty
4// significantly different. The core wasm `Module` corresponds roughly 1-to-1
5// with the structure of the wasm module itself, but instead a `Component` is
6// more of a "compiled" representation where the original structure is thrown
7// away in favor of a more optimized representation. The considerations for this
8// are:
9//
10// * This representation of a `Component` avoids the need to create a
11//   `PrimaryMap` of some form for each of the index spaces within a component.
12//   This is less so an issue about allocations and more so that this information
13//   generally just isn't needed any time after instantiation. Avoiding creating
14//   these altogether helps components be lighter weight at runtime and
15//   additionally accelerates instantiation.
16//
17// * Components can have arbitrary nesting and internally do instantiations via
18//   string-based matching. At instantiation-time, though, we want to do as few
19//   string-lookups in hash maps as much as we can since they're significantly
20//   slower than index-based lookups. Furthermore while the imports of a
21//   component are not statically known the rest of the structure of the
22//   component is statically known which enables the ability to track precisely
23//   what matches up where and do all the string lookups at compile time instead
24//   of instantiation time.
25//
26// * Finally by performing this sort of dataflow analysis we are capable of
27//   identifying what adapters need trampolines for compilation or fusion. For
28//   example this tracks when host functions are lowered which enables us to
29//   enumerate what trampolines are required to enter into a component.
30//   Additionally (eventually) this will track all of the "fused" adapter
31//   functions where a function from one component instance is lifted and then
32//   lowered into another component instance. Altogether this enables Wasmtime's
33//   AOT-compilation where the artifact from compilation is suitable for use in
34//   running the component without the support of a compiler at runtime.
35//
36// Note, however, that the current design of `Component` has fundamental
37// limitations which it was not designed for. For example there is no feasible
38// way to implement either importing or exporting a component itself from the
39// root component. Currently we rely on the ability to have static knowledge of
40// what's coming from the host which at this point can only be either functions
41// or core wasm modules. Additionally one flat list of initializers for a
42// component are produced instead of initializers-per-component which would
43// otherwise be required to export a component from a component.
44//
45// For now this tradeoff is made as it aligns well with the intended use case
46// for components in an embedding. This may need to be revisited though if the
47// requirements of embeddings change over time.
48
49use crate::component::*;
50use crate::prelude::*;
51use crate::{EntityIndex, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
52use cranelift_entity::packed_option::PackedOption;
53use serde_derive::{Deserialize, Serialize};
54
55/// Metadata as a result of compiling a component.
56pub struct ComponentTranslation {
57    /// Serializable information that will be emitted into the final artifact.
58    pub component: Component,
59
60    /// Metadata about required trampolines and what they're supposed to do.
61    pub trampolines: PrimaryMap<TrampolineIndex, Trampoline>,
62}
63
64/// Run-time-type-information about a `Component`, its structure, and how to
65/// instantiate it.
66///
67/// This type is intended to mirror the `Module` type in this crate which
68/// provides all the runtime information about the structure of a module and
69/// how it works.
70///
71/// NB: Lots of the component model is not yet implemented in the runtime so
72/// this is going to undergo a lot of churn.
73#[derive(Default, Debug, Serialize, Deserialize)]
74pub struct Component {
75    /// A list of typed values that this component imports.
76    ///
77    /// Note that each name is given an `ImportIndex` here for the next map to
78    /// refer back to.
79    pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
80
81    /// A list of "flattened" imports that are used by this instance.
82    ///
83    /// This import map represents extracting imports, as necessary, from the
84    /// general imported types by this component. The flattening here refers to
85    /// extracting items from instances. Currently the flat imports are either a
86    /// host function or a core wasm module.
87    ///
88    /// For example if `ImportIndex(0)` pointed to an instance then this import
89    /// map represent extracting names from that map, for example extracting an
90    /// exported module or an exported function.
91    ///
92    /// Each import item is keyed by a `RuntimeImportIndex` which is referred to
93    /// by types below whenever something refers to an import. The value for
94    /// each `RuntimeImportIndex` in this map is the `ImportIndex` for where
95    /// this items comes from (which can be associated with a name above in the
96    /// `import_types` array) as well as the list of export names if
97    /// `ImportIndex` refers to an instance. The export names array represents
98    /// recursively fetching names within an instance.
99    //
100    // TODO: this is probably a lot of `String` storage and may be something
101    // that needs optimization in the future. For example instead of lots of
102    // different `String` allocations this could instead be a pointer/length
103    // into one large string allocation for the entire component. Alternatively
104    // strings could otherwise be globally intern'd via some other mechanism to
105    // avoid `Linker`-specific intern-ing plus intern-ing here. Unsure what the
106    // best route is or whether such an optimization is even necessary here.
107    pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
108
109    /// This component's own root exports from the component itself.
110    pub exports: NameMap<String, ExportIndex>,
111
112    /// All exports of this component and exported instances of this component.
113    ///
114    /// This is indexed by `ExportIndex` for fast lookup and `Export::Instance`
115    /// will refer back into this list.
116    pub export_items: PrimaryMap<ExportIndex, Export>,
117
118    /// Initializers that must be processed when instantiating this component.
119    ///
120    /// This list of initializers does not correspond directly to the component
121    /// itself. The general goal with this is that the recursive nature of
122    /// components is "flattened" with an array like this which is a linear
123    /// sequence of instructions of how to instantiate a component. This will
124    /// have instantiations, for example, in addition to entries which
125    /// initialize `VMComponentContext` fields with previously instantiated
126    /// instances.
127    pub initializers: Vec<GlobalInitializer>,
128
129    /// The number of runtime instances (maximum `RuntimeInstanceIndex`) created
130    /// when instantiating this component.
131    pub num_runtime_instances: u32,
132
133    /// Same as `num_runtime_instances`, but for `RuntimeComponentInstanceIndex`
134    /// instead.
135    pub num_runtime_component_instances: u32,
136
137    /// The number of runtime memories (maximum `RuntimeMemoryIndex`) needed to
138    /// instantiate this component.
139    ///
140    /// Note that this many memories will be stored in the `VMComponentContext`
141    /// and each memory is intended to be unique (e.g. the same memory isn't
142    /// stored in two different locations).
143    pub num_runtime_memories: u32,
144
145    /// The number of runtime tables (maximum `RuntimeTableIndex`) needed to
146    /// instantiate this component. See notes on `num_runtime_memories`.
147    pub num_runtime_tables: u32,
148
149    /// The number of runtime reallocs (maximum `RuntimeReallocIndex`) needed to
150    /// instantiate this component.
151    ///
152    /// Note that this many function pointers will be stored in the
153    /// `VMComponentContext`.
154    pub num_runtime_reallocs: u32,
155
156    /// The number of runtime async callbacks (maximum `RuntimeCallbackIndex`)
157    /// needed to instantiate this component.
158    pub num_runtime_callbacks: u32,
159
160    /// Same as `num_runtime_reallocs`, but for post-return functions.
161    pub num_runtime_post_returns: u32,
162
163    /// WebAssembly type signature of all trampolines.
164    pub trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
165
166    /// A map from a `UnsafeIntrinsic::index()` to that intrinsic's
167    /// module-interned type.
168    pub unsafe_intrinsics: [PackedOption<ModuleInternedTypeIndex>; UnsafeIntrinsic::len() as usize],
169
170    /// The number of lowered host functions (maximum `LoweredIndex`) needed to
171    /// instantiate this component.
172    pub num_lowerings: u32,
173
174    /// Total number of resources both imported and defined within this
175    /// component.
176    pub num_resources: u32,
177
178    /// Maximal number of tables required at runtime for future-related
179    /// information in this component.
180    pub num_future_tables: usize,
181
182    /// Maximal number of tables required at runtime for stream-related
183    /// information in this component.
184    pub num_stream_tables: usize,
185
186    /// Maximal number of tables required at runtime for error-context-related
187    /// information in this component.
188    pub num_error_context_tables: usize,
189
190    /// Metadata about imported resources and where they are within the runtime
191    /// imports array.
192    ///
193    /// This map is only as large as the number of imported resources.
194    pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
195
196    /// Metadata about which component instances defined each resource within
197    /// this component.
198    ///
199    /// This is used to determine which set of instance flags are inspected when
200    /// testing reentrance.
201    pub defined_resource_instances: PrimaryMap<DefinedResourceIndex, RuntimeComponentInstanceIndex>,
202
203    /// All canonical options used by this component. Stored as a table here
204    /// from index-to-options so the options can be consulted at runtime.
205    pub options: PrimaryMap<OptionsIndex, CanonicalOptions>,
206}
207
208impl Component {
209    /// Attempts to convert a resource index into a defined index.
210    ///
211    /// Returns `None` if `idx` is for an imported resource in this component or
212    /// `Some` if it's a locally defined resource.
213    pub fn defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex> {
214        let idx = idx
215            .as_u32()
216            .checked_sub(self.imported_resources.len() as u32)?;
217        Some(DefinedResourceIndex::from_u32(idx))
218    }
219
220    /// Converts a defined resource index to a component-local resource index
221    /// which includes all imports.
222    pub fn resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex {
223        ResourceIndex::from_u32(self.imported_resources.len() as u32 + idx.as_u32())
224    }
225}
226
227/// GlobalInitializer instructions to get processed when instantiating a
228/// component.
229///
230/// The variants of this enum are processed during the instantiation phase of a
231/// component in-order from front-to-back. These are otherwise emitted as a
232/// component is parsed and read and translated.
233//
234// FIXME(#2639) if processing this list is ever a bottleneck we could
235// theoretically use cranelift to compile an initialization function which
236// performs all of these duties for us and skips the overhead of interpreting
237// all of these instructions.
238#[derive(Debug, Serialize, Deserialize)]
239pub enum GlobalInitializer {
240    /// A core wasm module is being instantiated.
241    ///
242    /// This will result in a new core wasm instance being created, which may
243    /// involve running the `start` function of the instance as well if it's
244    /// specified. This largely delegates to the same standard instantiation
245    /// process as the rest of the core wasm machinery already uses.
246    InstantiateModule(InstantiateModule),
247
248    /// A host function is being lowered, creating a core wasm function.
249    ///
250    /// This initializer entry is intended to be used to fill out the
251    /// `VMComponentContext` and information about this lowering such as the
252    /// cranelift-compiled trampoline function pointer, the host function
253    /// pointer the trampoline calls, and the canonical ABI options.
254    LowerImport {
255        /// The index of the lowered function that's being created.
256        ///
257        /// This is guaranteed to be the `n`th `LowerImport` instruction
258        /// if the index is `n`.
259        index: LoweredIndex,
260
261        /// The index of the imported host function that is being lowered.
262        ///
263        /// It's guaranteed that this `RuntimeImportIndex` points to a function.
264        import: RuntimeImportIndex,
265    },
266
267    /// A core wasm linear memory is going to be saved into the
268    /// `VMComponentContext`.
269    ///
270    /// This instruction indicates that a core wasm linear memory needs to be
271    /// extracted from the `export` and stored into the `VMComponentContext` at
272    /// the `index` specified. This lowering is then used in the future by
273    /// pointers from `CanonicalOptions`.
274    ExtractMemory(ExtractMemory),
275
276    /// Same as `ExtractMemory`, except it's extracting a function pointer to be
277    /// used as a `realloc` function.
278    ExtractRealloc(ExtractRealloc),
279
280    /// Same as `ExtractMemory`, except it's extracting a function pointer to be
281    /// used as an async `callback` function.
282    ExtractCallback(ExtractCallback),
283
284    /// Same as `ExtractMemory`, except it's extracting a function pointer to be
285    /// used as a `post-return` function.
286    ExtractPostReturn(ExtractPostReturn),
287
288    /// A core wasm table is going to be saved into the `VMComponentContext`.
289    ///
290    /// This instruction indicates that s core wasm table needs to be extracted
291    /// from its `export` and stored into the `VMComponentContext` at the
292    /// `index` specified. During this extraction, we will also capture the
293    /// table's containing instance pointer to access the table at runtime. This
294    /// extraction is useful for `thread.spawn-indirect`.
295    ExtractTable(ExtractTable),
296
297    /// Declares a new defined resource within this component.
298    ///
299    /// Contains information about the destructor, for example.
300    Resource(Resource),
301}
302
303/// Metadata for extraction of a memory; contains what's being extracted (the
304/// memory at `export`) and where it's going (the `index` within a
305/// `VMComponentContext`).
306#[derive(Debug, Serialize, Deserialize)]
307pub struct ExtractMemory {
308    /// The index of the memory being defined.
309    pub index: RuntimeMemoryIndex,
310    /// Where this memory is being extracted from.
311    pub export: CoreExport<MemoryIndex>,
312}
313
314/// Same as `ExtractMemory` but for the `realloc` canonical option.
315#[derive(Debug, Serialize, Deserialize)]
316pub struct ExtractRealloc {
317    /// The index of the realloc being defined.
318    pub index: RuntimeReallocIndex,
319    /// Where this realloc is being extracted from.
320    pub def: CoreDef,
321}
322
323/// Same as `ExtractMemory` but for the `callback` canonical option.
324#[derive(Debug, Serialize, Deserialize)]
325pub struct ExtractCallback {
326    /// The index of the callback being defined.
327    pub index: RuntimeCallbackIndex,
328    /// Where this callback is being extracted from.
329    pub def: CoreDef,
330}
331
332/// Same as `ExtractMemory` but for the `post-return` canonical option.
333#[derive(Debug, Serialize, Deserialize)]
334pub struct ExtractPostReturn {
335    /// The index of the post-return being defined.
336    pub index: RuntimePostReturnIndex,
337    /// Where this post-return is being extracted from.
338    pub def: CoreDef,
339}
340
341/// Metadata for extraction of a table.
342#[derive(Debug, Serialize, Deserialize)]
343pub struct ExtractTable {
344    /// The index of the table being defined in a `VMComponentContext`.
345    pub index: RuntimeTableIndex,
346    /// Where this table is being extracted from.
347    pub export: CoreExport<TableIndex>,
348}
349
350/// Different methods of instantiating a core wasm module.
351#[derive(Debug, Serialize, Deserialize)]
352pub enum InstantiateModule {
353    /// A module defined within this component is being instantiated.
354    ///
355    /// Note that this is distinct from the case of imported modules because the
356    /// order of imports required is statically known and can be pre-calculated
357    /// to avoid string lookups related to names at runtime, represented by the
358    /// flat list of arguments here.
359    Static(StaticModuleIndex, Box<[CoreDef]>),
360
361    /// An imported module is being instantiated.
362    ///
363    /// This is similar to `Upvar` but notably the imports are provided as a
364    /// two-level named map since import resolution order needs to happen at
365    /// runtime.
366    Import(
367        RuntimeImportIndex,
368        IndexMap<String, IndexMap<String, CoreDef>>,
369    ),
370}
371
372/// Definition of a core wasm item and where it can come from within a
373/// component.
374///
375/// Note that this is sort of a result of data-flow-like analysis on a component
376/// during compile time of the component itself. References to core wasm items
377/// are "compiled" to either referring to a previous instance or to some sort of
378/// lowered host import.
379#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
380pub enum CoreDef {
381    /// This item refers to an export of a previously instantiated core wasm
382    /// instance.
383    Export(CoreExport<EntityIndex>),
384    /// This is a reference to a wasm global which represents the
385    /// runtime-managed flags for a wasm instance.
386    InstanceFlags(RuntimeComponentInstanceIndex),
387    /// This is a reference to a Cranelift-generated trampoline which is
388    /// described in the `trampolines` array.
389    Trampoline(TrampolineIndex),
390    /// An intrinsic for compile-time builtins.
391    UnsafeIntrinsic(UnsafeIntrinsic),
392}
393
394impl<T> From<CoreExport<T>> for CoreDef
395where
396    EntityIndex: From<T>,
397{
398    fn from(export: CoreExport<T>) -> CoreDef {
399        CoreDef::Export(export.map_index(|i| i.into()))
400    }
401}
402
403/// Identifier of an exported item from a core WebAssembly module instance.
404///
405/// Note that the `T` here is the index type for exports which can be
406/// identified by index. The `T` is monomorphized with types like
407/// [`EntityIndex`] or [`FuncIndex`].
408#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
409pub struct CoreExport<T> {
410    /// The instance that this item is located within.
411    ///
412    /// Note that this is intended to index the `instances` map within a
413    /// component. It's validated ahead of time that all instance pointers
414    /// refer only to previously-created instances.
415    pub instance: RuntimeInstanceIndex,
416
417    /// The item that this export is referencing, either by name or by index.
418    pub item: ExportItem<T>,
419}
420
421impl<T> CoreExport<T> {
422    /// Maps the index type `T` to another type `U` if this export item indeed
423    /// refers to an index `T`.
424    pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
425        CoreExport {
426            instance: self.instance,
427            item: match self.item {
428                ExportItem::Index(i) => ExportItem::Index(f(i)),
429                ExportItem::Name(s) => ExportItem::Name(s),
430            },
431        }
432    }
433}
434
435/// An index at which to find an item within a runtime instance.
436#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
437pub enum ExportItem<T> {
438    /// An exact index that the target can be found at.
439    ///
440    /// This is used where possible to avoid name lookups at runtime during the
441    /// instantiation process. This can only be used on instances where the
442    /// module was statically known at compile time, however.
443    Index(T),
444
445    /// An item which is identified by a name, so at runtime we need to
446    /// perform a name lookup to determine the index that the item is located
447    /// at.
448    ///
449    /// This is used for instantiations of imported modules, for example, since
450    /// the precise shape of the module is not known.
451    Name(String),
452}
453
454/// Possible exports from a component.
455#[derive(Debug, Clone, Serialize, Deserialize)]
456pub enum Export {
457    /// A lifted function being exported which is an adaptation of a core wasm
458    /// function.
459    LiftedFunction {
460        /// The component function type of the function being created.
461        ty: TypeFuncIndex,
462        /// Which core WebAssembly export is being lifted.
463        func: CoreDef,
464        /// Any options, if present, associated with this lifting.
465        options: OptionsIndex,
466    },
467    /// A module defined within this component is exported.
468    ModuleStatic {
469        /// The type of this module
470        ty: TypeModuleIndex,
471        /// Which module this is referring to.
472        index: StaticModuleIndex,
473    },
474    /// A module imported into this component is exported.
475    ModuleImport {
476        /// Module type index
477        ty: TypeModuleIndex,
478        /// Module runtime import index
479        import: RuntimeImportIndex,
480    },
481    /// A nested instance is being exported which has recursively defined
482    /// `Export` items.
483    Instance {
484        /// Instance type index, if such is assigned
485        ty: TypeComponentInstanceIndex,
486        /// Instance export map
487        exports: NameMap<String, ExportIndex>,
488    },
489    /// An exported type from a component or instance, currently only
490    /// informational.
491    Type(TypeDef),
492}
493
494#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
495/// Data is stored in a linear memory.
496pub struct LinearMemoryOptions {
497    /// The memory used by these options, if specified.
498    pub memory: Option<RuntimeMemoryIndex>,
499    /// The realloc function used by these options, if specified.
500    pub realloc: Option<RuntimeReallocIndex>,
501}
502
503/// The data model for objects that are not unboxed in locals.
504#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
505pub enum CanonicalOptionsDataModel {
506    /// Data is stored in GC objects.
507    Gc {},
508
509    /// Data is stored in a linear memory.
510    LinearMemory(LinearMemoryOptions),
511}
512
513/// Canonical ABI options associated with a lifted or lowered function.
514#[derive(Debug, Clone, Serialize, Deserialize)]
515pub struct CanonicalOptions {
516    /// The component instance that this bundle was associated with.
517    pub instance: RuntimeComponentInstanceIndex,
518
519    /// The encoding used for strings.
520    pub string_encoding: StringEncoding,
521
522    /// The async callback function used by these options, if specified.
523    pub callback: Option<RuntimeCallbackIndex>,
524
525    /// The post-return function used by these options, if specified.
526    pub post_return: Option<RuntimePostReturnIndex>,
527
528    /// Whether to use the async ABI for lifting or lowering.
529    pub async_: bool,
530
531    /// Whether or not this function can consume a task cancellation
532    /// notification.
533    pub cancellable: bool,
534
535    /// The core function type that is being lifted from / lowered to.
536    pub core_type: ModuleInternedTypeIndex,
537
538    /// The data model (GC objects or linear memory) used with these canonical
539    /// options.
540    pub data_model: CanonicalOptionsDataModel,
541}
542
543impl CanonicalOptions {
544    /// Returns the memory referred to by these options, if any.
545    pub fn memory(&self) -> Option<RuntimeMemoryIndex> {
546        match self.data_model {
547            CanonicalOptionsDataModel::Gc {} => None,
548            CanonicalOptionsDataModel::LinearMemory(opts) => opts.memory,
549        }
550    }
551}
552
553/// Possible encodings of strings within the component model.
554#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
555#[expect(missing_docs, reason = "self-describing variants")]
556pub enum StringEncoding {
557    Utf8,
558    Utf16,
559    CompactUtf16,
560}
561
562impl StringEncoding {
563    /// Decodes the `u8` provided back into a `StringEncoding`, if it's valid.
564    pub fn from_u8(val: u8) -> Option<StringEncoding> {
565        if val == StringEncoding::Utf8 as u8 {
566            return Some(StringEncoding::Utf8);
567        }
568        if val == StringEncoding::Utf16 as u8 {
569            return Some(StringEncoding::Utf16);
570        }
571        if val == StringEncoding::CompactUtf16 as u8 {
572            return Some(StringEncoding::CompactUtf16);
573        }
574        None
575    }
576}
577
578/// Possible transcoding operations that must be provided by the host.
579///
580/// Note that each transcoding operation may have a unique signature depending
581/// on the precise operation.
582#[expect(missing_docs, reason = "self-describing variants")]
583#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
584pub enum Transcode {
585    Copy(FixedEncoding),
586    Latin1ToUtf16,
587    Latin1ToUtf8,
588    Utf16ToCompactProbablyUtf16,
589    Utf16ToCompactUtf16,
590    Utf16ToLatin1,
591    Utf16ToUtf8,
592    Utf8ToCompactUtf16,
593    Utf8ToLatin1,
594    Utf8ToUtf16,
595}
596
597impl Transcode {
598    /// Get this transcoding's symbol fragment.
599    pub fn symbol_fragment(&self) -> &'static str {
600        match self {
601            Transcode::Copy(x) => match x {
602                FixedEncoding::Utf8 => "copy_utf8",
603                FixedEncoding::Utf16 => "copy_utf16",
604                FixedEncoding::Latin1 => "copy_latin1",
605            },
606            Transcode::Latin1ToUtf16 => "latin1_to_utf16",
607            Transcode::Latin1ToUtf8 => "latin1_to_utf8",
608            Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",
609            Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",
610            Transcode::Utf16ToLatin1 => "utf16_to_latin1",
611            Transcode::Utf16ToUtf8 => "utf16_to_utf8",
612            Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",
613            Transcode::Utf8ToLatin1 => "utf8_to_latin1",
614            Transcode::Utf8ToUtf16 => "utf8_to_utf16",
615        }
616    }
617
618    /// Returns a human-readable description for this transcoding operation.
619    pub fn desc(&self) -> &'static str {
620        match self {
621            Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",
622            Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",
623            Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",
624            Transcode::Latin1ToUtf16 => "latin1-to-utf16",
625            Transcode::Latin1ToUtf8 => "latin1-to-utf8",
626            Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",
627            Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",
628            Transcode::Utf16ToLatin1 => "utf16-to-latin1",
629            Transcode::Utf16ToUtf8 => "utf16-to-utf8",
630            Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",
631            Transcode::Utf8ToLatin1 => "utf8-to-latin1",
632            Transcode::Utf8ToUtf16 => "utf8-to-utf16",
633        }
634    }
635}
636
637#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
638#[expect(missing_docs, reason = "self-describing variants")]
639pub enum FixedEncoding {
640    Utf8,
641    Utf16,
642    Latin1,
643}
644
645impl FixedEncoding {
646    /// Returns the byte width of unit loads/stores for this encoding, for
647    /// example the unit length is multiplied by this return value to get the
648    /// byte width of a string.
649    pub fn width(&self) -> u8 {
650        match self {
651            FixedEncoding::Utf8 => 1,
652            FixedEncoding::Utf16 => 2,
653            FixedEncoding::Latin1 => 1,
654        }
655    }
656}
657
658/// Description of a new resource declared in a `GlobalInitializer::Resource`
659/// variant.
660///
661/// This will have the effect of initializing runtime state for this resource,
662/// namely the destructor is fetched and stored.
663#[derive(Debug, Serialize, Deserialize)]
664pub struct Resource {
665    /// The local index of the resource being defined.
666    pub index: DefinedResourceIndex,
667    /// Core wasm representation of this resource.
668    pub rep: WasmValType,
669    /// Optionally-specified destructor and where it comes from.
670    pub dtor: Option<CoreDef>,
671    /// Which component instance this resource logically belongs to.
672    pub instance: RuntimeComponentInstanceIndex,
673}
674
675/// A list of all possible trampolines that may be required to compile a
676/// component completely.
677///
678/// These trampolines are used often as core wasm definitions and require
679/// Cranelift support to generate these functions. Each trampoline serves a
680/// different purpose for implementing bits and pieces of the component model.
681///
682/// All trampolines have a core wasm function signature associated with them
683/// which is stored in the `Component::trampolines` array.
684///
685/// Note that this type does not implement `Serialize` or `Deserialize` and
686/// that's intentional as this isn't stored in the final compilation artifact.
687#[derive(Debug)]
688pub enum Trampoline {
689    /// Description of a lowered import used in conjunction with
690    /// `GlobalInitializer::LowerImport`.
691    LowerImport {
692        /// The runtime lowering state that this trampoline will access.
693        index: LoweredIndex,
694
695        /// The type of the function that is being lowered, as perceived by the
696        /// component doing the lowering.
697        lower_ty: TypeFuncIndex,
698
699        /// The canonical ABI options used when lowering this function specified
700        /// in the original component.
701        options: OptionsIndex,
702    },
703
704    /// Information about a string transcoding function required by an adapter
705    /// module.
706    ///
707    /// A transcoder is used when strings are passed between adapter modules,
708    /// optionally changing string encodings at the same time. The transcoder is
709    /// implemented in a few different layers:
710    ///
711    /// * Each generated adapter module has some glue around invoking the
712    ///   transcoder represented by this item. This involves bounds-checks and
713    ///   handling `realloc` for example.
714    /// * Each transcoder gets a cranelift-generated trampoline which has the
715    ///   appropriate signature for the adapter module in question. Existence of
716    ///   this initializer indicates that this should be compiled by Cranelift.
717    /// * The cranelift-generated trampoline will invoke a "transcoder libcall"
718    ///   which is implemented natively in Rust that has a signature independent
719    ///   of memory64 configuration options for example.
720    Transcoder {
721        /// The transcoding operation being performed.
722        op: Transcode,
723        /// The linear memory that the string is being read from.
724        from: RuntimeMemoryIndex,
725        /// Whether or not the source linear memory is 64-bit or not.
726        from64: bool,
727        /// The linear memory that the string is being written to.
728        to: RuntimeMemoryIndex,
729        /// Whether or not the destination linear memory is 64-bit or not.
730        to64: bool,
731    },
732
733    /// A small adapter which simply traps, used for degenerate lift/lower
734    /// combinations.
735    AlwaysTrap,
736
737    /// A `resource.new` intrinsic which will inject a new resource into the
738    /// table specified.
739    ResourceNew {
740        /// The specific component instance which is calling the intrinsic.
741        instance: RuntimeComponentInstanceIndex,
742        /// The type of the resource.
743        ty: TypeResourceTableIndex,
744    },
745
746    /// Same as `ResourceNew`, but for the `resource.rep` intrinsic.
747    ResourceRep {
748        /// The specific component instance which is calling the intrinsic.
749        instance: RuntimeComponentInstanceIndex,
750        /// The type of the resource.
751        ty: TypeResourceTableIndex,
752    },
753
754    /// Same as `ResourceNew`, but for the `resource.drop` intrinsic.
755    ResourceDrop {
756        /// The specific component instance which is calling the intrinsic.
757        instance: RuntimeComponentInstanceIndex,
758        /// The type of the resource.
759        ty: TypeResourceTableIndex,
760    },
761
762    /// A `backpressure.inc` intrinsic.
763    BackpressureInc {
764        /// The specific component instance which is calling the intrinsic.
765        instance: RuntimeComponentInstanceIndex,
766    },
767
768    /// A `backpressure.dec` intrinsic.
769    BackpressureDec {
770        /// The specific component instance which is calling the intrinsic.
771        instance: RuntimeComponentInstanceIndex,
772    },
773
774    /// A `task.return` intrinsic, which returns a result to the caller of a
775    /// lifted export function.  This allows the callee to continue executing
776    /// after returning a result.
777    TaskReturn {
778        /// The specific component instance which is calling the intrinsic.
779        instance: RuntimeComponentInstanceIndex,
780        /// Tuple representing the result types this intrinsic accepts.
781        results: TypeTupleIndex,
782        /// The canonical ABI options specified for this intrinsic.
783        options: OptionsIndex,
784    },
785
786    /// A `task.cancel` intrinsic, which acknowledges a `CANCELLED` event
787    /// delivered to a guest task previously created by a call to an async
788    /// export.
789    TaskCancel {
790        /// The specific component instance which is calling the intrinsic.
791        instance: RuntimeComponentInstanceIndex,
792    },
793
794    /// A `waitable-set.new` intrinsic.
795    WaitableSetNew {
796        /// The specific component instance which is calling the intrinsic.
797        instance: RuntimeComponentInstanceIndex,
798    },
799
800    /// A `waitable-set.wait` intrinsic, which waits for at least one
801    /// outstanding async task/stream/future to make progress, returning the
802    /// first such event.
803    WaitableSetWait {
804        /// The specific component instance which is calling the intrinsic.
805        instance: RuntimeComponentInstanceIndex,
806        /// Configuration options for this intrinsic call.
807        options: OptionsIndex,
808    },
809
810    /// A `waitable-set.poll` intrinsic, which checks whether any outstanding
811    /// async task/stream/future has made progress.  Unlike `task.wait`, this
812    /// does not block and may return nothing if no such event has occurred.
813    WaitableSetPoll {
814        /// The specific component instance which is calling the intrinsic.
815        instance: RuntimeComponentInstanceIndex,
816        /// Configuration options for this intrinsic call.
817        options: OptionsIndex,
818    },
819
820    /// A `waitable-set.drop` intrinsic.
821    WaitableSetDrop {
822        /// The specific component instance which is calling the intrinsic.
823        instance: RuntimeComponentInstanceIndex,
824    },
825
826    /// A `waitable.join` intrinsic.
827    WaitableJoin {
828        /// The specific component instance which is calling the intrinsic.
829        instance: RuntimeComponentInstanceIndex,
830    },
831
832    /// A `thread.yield` intrinsic, which yields control to the host so that other
833    /// tasks are able to make progress, if any.
834    ThreadYield {
835        /// The specific component instance which is calling the intrinsic.
836        instance: RuntimeComponentInstanceIndex,
837        /// If `true`, indicates the caller instance may receive notification
838        /// of task cancellation.
839        cancellable: bool,
840    },
841
842    /// A `subtask.drop` intrinsic to drop a specified task which has completed.
843    SubtaskDrop {
844        /// The specific component instance which is calling the intrinsic.
845        instance: RuntimeComponentInstanceIndex,
846    },
847
848    /// A `subtask.cancel` intrinsic to drop an in-progress task.
849    SubtaskCancel {
850        /// The specific component instance which is calling the intrinsic.
851        instance: RuntimeComponentInstanceIndex,
852        /// If `false`, block until cancellation completes rather than return
853        /// `BLOCKED`.
854        async_: bool,
855    },
856
857    /// A `stream.new` intrinsic to create a new `stream` handle of the
858    /// specified type.
859    StreamNew {
860        /// The specific component instance which is calling the intrinsic.
861        instance: RuntimeComponentInstanceIndex,
862        /// The table index for the specific `stream` type and caller instance.
863        ty: TypeStreamTableIndex,
864    },
865
866    /// A `stream.read` intrinsic to read from a `stream` of the specified type.
867    StreamRead {
868        /// The specific component instance which is calling the intrinsic.
869        instance: RuntimeComponentInstanceIndex,
870        /// The table index for the specific `stream` type and caller instance.
871        ty: TypeStreamTableIndex,
872        /// Any options (e.g. string encoding) to use when storing values to
873        /// memory.
874        options: OptionsIndex,
875    },
876
877    /// A `stream.write` intrinsic to write to a `stream` of the specified type.
878    StreamWrite {
879        /// The specific component instance which is calling the intrinsic.
880        instance: RuntimeComponentInstanceIndex,
881        /// The table index for the specific `stream` type and caller instance.
882        ty: TypeStreamTableIndex,
883        /// Any options (e.g. string encoding) to use when storing values to
884        /// memory.
885        options: OptionsIndex,
886    },
887
888    /// A `stream.cancel-read` intrinsic to cancel an in-progress read from a
889    /// `stream` of the specified type.
890    StreamCancelRead {
891        /// The specific component instance which is calling the intrinsic.
892        instance: RuntimeComponentInstanceIndex,
893        /// The table index for the specific `stream` type and caller instance.
894        ty: TypeStreamTableIndex,
895        /// If `false`, block until cancellation completes rather than return
896        /// `BLOCKED`.
897        async_: bool,
898    },
899
900    /// A `stream.cancel-write` intrinsic to cancel an in-progress write from a
901    /// `stream` of the specified type.
902    StreamCancelWrite {
903        /// The specific component instance which is calling the intrinsic.
904        instance: RuntimeComponentInstanceIndex,
905        /// The table index for the specific `stream` type and caller instance.
906        ty: TypeStreamTableIndex,
907        /// If `false`, block until cancellation completes rather than return
908        /// `BLOCKED`.
909        async_: bool,
910    },
911
912    /// A `stream.drop-readable` intrinsic to drop the readable end of a
913    /// `stream` of the specified type.
914    StreamDropReadable {
915        /// The specific component instance which is calling the intrinsic.
916        instance: RuntimeComponentInstanceIndex,
917        /// The table index for the specific `stream` type and caller instance.
918        ty: TypeStreamTableIndex,
919    },
920
921    /// A `stream.drop-writable` intrinsic to drop the writable end of a
922    /// `stream` of the specified type.
923    StreamDropWritable {
924        /// The specific component instance which is calling the intrinsic.
925        instance: RuntimeComponentInstanceIndex,
926        /// The table index for the specific `stream` type and caller instance.
927        ty: TypeStreamTableIndex,
928    },
929
930    /// A `future.new` intrinsic to create a new `future` handle of the
931    /// specified type.
932    FutureNew {
933        /// The specific component instance which is calling the intrinsic.
934        instance: RuntimeComponentInstanceIndex,
935        /// The table index for the specific `future` type and caller instance.
936        ty: TypeFutureTableIndex,
937    },
938
939    /// A `future.read` intrinsic to read from a `future` of the specified type.
940    FutureRead {
941        /// The specific component instance which is calling the intrinsic.
942        instance: RuntimeComponentInstanceIndex,
943        /// The table index for the specific `future` type and caller instance.
944        ty: TypeFutureTableIndex,
945        /// Any options (e.g. string encoding) to use when storing values to
946        /// memory.
947        options: OptionsIndex,
948    },
949
950    /// A `future.write` intrinsic to write to a `future` of the specified type.
951    FutureWrite {
952        /// The specific component instance which is calling the intrinsic.
953        instance: RuntimeComponentInstanceIndex,
954        /// The table index for the specific `future` type and caller instance.
955        ty: TypeFutureTableIndex,
956        /// Any options (e.g. string encoding) to use when storing values to
957        /// memory.
958        options: OptionsIndex,
959    },
960
961    /// A `future.cancel-read` intrinsic to cancel an in-progress read from a
962    /// `future` of the specified type.
963    FutureCancelRead {
964        /// The specific component instance which is calling the intrinsic.
965        instance: RuntimeComponentInstanceIndex,
966        /// The table index for the specific `future` type and caller instance.
967        ty: TypeFutureTableIndex,
968        /// If `false`, block until cancellation completes rather than return
969        /// `BLOCKED`.
970        async_: bool,
971    },
972
973    /// A `future.cancel-write` intrinsic to cancel an in-progress write from a
974    /// `future` of the specified type.
975    FutureCancelWrite {
976        /// The specific component instance which is calling the intrinsic.
977        instance: RuntimeComponentInstanceIndex,
978        /// The table index for the specific `future` type and caller instance.
979        ty: TypeFutureTableIndex,
980        /// If `false`, block until cancellation completes rather than return
981        /// `BLOCKED`.
982        async_: bool,
983    },
984
985    /// A `future.drop-readable` intrinsic to drop the readable end of a
986    /// `future` of the specified type.
987    FutureDropReadable {
988        /// The specific component instance which is calling the intrinsic.
989        instance: RuntimeComponentInstanceIndex,
990        /// The table index for the specific `future` type and caller instance.
991        ty: TypeFutureTableIndex,
992    },
993
994    /// A `future.drop-writable` intrinsic to drop the writable end of a
995    /// `future` of the specified type.
996    FutureDropWritable {
997        /// The specific component instance which is calling the intrinsic.
998        instance: RuntimeComponentInstanceIndex,
999        /// The table index for the specific `future` type and caller instance.
1000        ty: TypeFutureTableIndex,
1001    },
1002
1003    /// A `error-context.new` intrinsic to create a new `error-context` with a
1004    /// specified debug message.
1005    ErrorContextNew {
1006        /// The specific component instance which is calling the intrinsic.
1007        instance: RuntimeComponentInstanceIndex,
1008        /// The table index for the `error-context` type in the caller instance.
1009        ty: TypeComponentLocalErrorContextTableIndex,
1010        /// String encoding, memory, etc. to use when loading debug message.
1011        options: OptionsIndex,
1012    },
1013
1014    /// A `error-context.debug-message` intrinsic to get the debug message for a
1015    /// specified `error-context`.
1016    ///
1017    /// Note that the debug message might not necessarily match what was passed
1018    /// to `error.new`.
1019    ErrorContextDebugMessage {
1020        /// The specific component instance which is calling the intrinsic.
1021        instance: RuntimeComponentInstanceIndex,
1022        /// The table index for the `error-context` type in the caller instance.
1023        ty: TypeComponentLocalErrorContextTableIndex,
1024        /// String encoding, memory, etc. to use when storing debug message.
1025        options: OptionsIndex,
1026    },
1027
1028    /// A `error-context.drop` intrinsic to drop a specified `error-context`.
1029    ErrorContextDrop {
1030        /// The specific component instance which is calling the intrinsic.
1031        instance: RuntimeComponentInstanceIndex,
1032        /// The table index for the `error-context` type in the caller instance.
1033        ty: TypeComponentLocalErrorContextTableIndex,
1034    },
1035
1036    /// An intrinsic used by FACT-generated modules which will transfer an owned
1037    /// resource from one table to another. Used in component-to-component
1038    /// adapter trampolines.
1039    ResourceTransferOwn,
1040
1041    /// Same as `ResourceTransferOwn` but for borrows.
1042    ResourceTransferBorrow,
1043
1044    /// An intrinsic used by FACT-generated modules which indicates that a call
1045    /// is being entered and resource-related metadata needs to be configured.
1046    ///
1047    /// Note that this is currently only invoked when borrowed resources are
1048    /// detected, otherwise this is "optimized out".
1049    ResourceEnterCall,
1050
1051    /// Same as `ResourceEnterCall` except for when exiting a call.
1052    ResourceExitCall,
1053
1054    /// An intrinsic used by FACT-generated modules to prepare a call involving
1055    /// an async-lowered import and/or an async-lifted export.
1056    PrepareCall {
1057        /// The memory used to verify that the memory specified for the
1058        /// `task.return` that is called at runtime matches the one specified in
1059        /// the lifted export.
1060        memory: Option<RuntimeMemoryIndex>,
1061    },
1062
1063    /// An intrinsic used by FACT-generated modules to start a call involving a
1064    /// sync-lowered import and async-lifted export.
1065    SyncStartCall {
1066        /// The callee's callback function, if any.
1067        callback: Option<RuntimeCallbackIndex>,
1068    },
1069
1070    /// An intrinsic used by FACT-generated modules to start a call involving
1071    /// an async-lowered import function.
1072    ///
1073    /// Note that `AsyncPrepareCall` and `AsyncStartCall` could theoretically be
1074    /// combined into a single `AsyncCall` intrinsic, but we separate them to
1075    /// allow the FACT-generated module to optionally call the callee directly
1076    /// without an intermediate host stack frame.
1077    AsyncStartCall {
1078        /// The callee's callback, if any.
1079        callback: Option<RuntimeCallbackIndex>,
1080        /// The callee's post-return function, if any.
1081        post_return: Option<RuntimePostReturnIndex>,
1082    },
1083
1084    /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1085    /// ownership of a `future`.
1086    ///
1087    /// Transferring a `future` can either mean giving away the readable end
1088    /// while retaining the writable end or only the former, depending on the
1089    /// ownership status of the `future`.
1090    FutureTransfer,
1091
1092    /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1093    /// ownership of a `stream`.
1094    ///
1095    /// Transferring a `stream` can either mean giving away the readable end
1096    /// while retaining the writable end or only the former, depending on the
1097    /// ownership status of the `stream`.
1098    StreamTransfer,
1099
1100    /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1101    /// ownership of an `error-context`.
1102    ///
1103    /// Unlike futures, streams, and resource handles, `error-context` handles
1104    /// are reference counted, meaning that sharing the handle with another
1105    /// component does not invalidate the handle in the original component.
1106    ErrorContextTransfer,
1107
1108    /// An intrinsic used by FACT-generated modules to check whether an
1109    /// async-typed function may be called via a sync lower.
1110    CheckBlocking,
1111
1112    /// Intrinsic used to implement the `context.get` component model builtin.
1113    ///
1114    /// The payload here represents that this is accessing the Nth slot of local
1115    /// storage.
1116    ContextGet {
1117        /// The specific component instance which is calling the intrinsic.
1118        instance: RuntimeComponentInstanceIndex,
1119        /// Which slot to access.
1120        slot: u32,
1121    },
1122
1123    /// Intrinsic used to implement the `context.set` component model builtin.
1124    ///
1125    /// The payload here represents that this is accessing the Nth slot of local
1126    /// storage.
1127    ContextSet {
1128        /// The specific component instance which is calling the intrinsic.
1129        instance: RuntimeComponentInstanceIndex,
1130        /// Which slot to update.
1131        slot: u32,
1132    },
1133
1134    /// Intrinsic used to implement the `thread.index` component model builtin.
1135    ThreadIndex,
1136
1137    /// Intrinsic used to implement the `thread.new-indirect` component model builtin.
1138    ThreadNewIndirect {
1139        /// The specific component instance which is calling the intrinsic.
1140        instance: RuntimeComponentInstanceIndex,
1141        /// The type index for the start function of the thread.
1142        start_func_ty_idx: ComponentTypeIndex,
1143        /// The index of the table that stores the start function.
1144        start_func_table_idx: RuntimeTableIndex,
1145    },
1146
1147    /// Intrinsic used to implement the `thread.switch-to` component model builtin.
1148    ThreadSwitchTo {
1149        /// The specific component instance which is calling the intrinsic.
1150        instance: RuntimeComponentInstanceIndex,
1151        /// If `true`, indicates the caller instance may receive notification
1152        /// of task cancellation.
1153        cancellable: bool,
1154    },
1155
1156    /// Intrinsic used to implement the `thread.suspend` component model builtin.
1157    ThreadSuspend {
1158        /// The specific component instance which is calling the intrinsic.
1159        instance: RuntimeComponentInstanceIndex,
1160        /// If `true`, indicates the caller instance may receive notification
1161        /// of task cancellation.
1162        cancellable: bool,
1163    },
1164
1165    /// Intrinsic used to implement the `thread.resume-later` component model builtin.
1166    ThreadResumeLater {
1167        /// The specific component instance which is calling the intrinsic.
1168        instance: RuntimeComponentInstanceIndex,
1169    },
1170
1171    /// Intrinsic used to implement the `thread.yield-to` component model builtin.
1172    ThreadYieldTo {
1173        /// The specific component instance which is calling the intrinsic.
1174        instance: RuntimeComponentInstanceIndex,
1175        /// If `true`, indicates the caller instance may receive notification
1176        /// of task cancellation.
1177        cancellable: bool,
1178    },
1179}
1180
1181impl Trampoline {
1182    /// Returns the name to use for the symbol of this trampoline in the final
1183    /// compiled artifact
1184    pub fn symbol_name(&self) -> String {
1185        use Trampoline::*;
1186        match self {
1187            LowerImport { index, .. } => {
1188                format!("component-lower-import[{}]", index.as_u32())
1189            }
1190            Transcoder {
1191                op, from64, to64, ..
1192            } => {
1193                let op = op.symbol_fragment();
1194                let from = if *from64 { "64" } else { "32" };
1195                let to = if *to64 { "64" } else { "32" };
1196                format!("component-transcode-{op}-m{from}-m{to}")
1197            }
1198            AlwaysTrap => format!("component-always-trap"),
1199            ResourceNew { ty, .. } => format!("component-resource-new[{}]", ty.as_u32()),
1200            ResourceRep { ty, .. } => format!("component-resource-rep[{}]", ty.as_u32()),
1201            ResourceDrop { ty, .. } => format!("component-resource-drop[{}]", ty.as_u32()),
1202            BackpressureInc { .. } => format!("backpressure-inc"),
1203            BackpressureDec { .. } => format!("backpressure-dec"),
1204            TaskReturn { .. } => format!("task-return"),
1205            TaskCancel { .. } => format!("task-cancel"),
1206            WaitableSetNew { .. } => format!("waitable-set-new"),
1207            WaitableSetWait { .. } => format!("waitable-set-wait"),
1208            WaitableSetPoll { .. } => format!("waitable-set-poll"),
1209            WaitableSetDrop { .. } => format!("waitable-set-drop"),
1210            WaitableJoin { .. } => format!("waitable-join"),
1211            ThreadYield { .. } => format!("thread-yield"),
1212            SubtaskDrop { .. } => format!("subtask-drop"),
1213            SubtaskCancel { .. } => format!("subtask-cancel"),
1214            StreamNew { .. } => format!("stream-new"),
1215            StreamRead { .. } => format!("stream-read"),
1216            StreamWrite { .. } => format!("stream-write"),
1217            StreamCancelRead { .. } => format!("stream-cancel-read"),
1218            StreamCancelWrite { .. } => format!("stream-cancel-write"),
1219            StreamDropReadable { .. } => format!("stream-drop-readable"),
1220            StreamDropWritable { .. } => format!("stream-drop-writable"),
1221            FutureNew { .. } => format!("future-new"),
1222            FutureRead { .. } => format!("future-read"),
1223            FutureWrite { .. } => format!("future-write"),
1224            FutureCancelRead { .. } => format!("future-cancel-read"),
1225            FutureCancelWrite { .. } => format!("future-cancel-write"),
1226            FutureDropReadable { .. } => format!("future-drop-readable"),
1227            FutureDropWritable { .. } => format!("future-drop-writable"),
1228            ErrorContextNew { .. } => format!("error-context-new"),
1229            ErrorContextDebugMessage { .. } => format!("error-context-debug-message"),
1230            ErrorContextDrop { .. } => format!("error-context-drop"),
1231            ResourceTransferOwn => format!("component-resource-transfer-own"),
1232            ResourceTransferBorrow => format!("component-resource-transfer-borrow"),
1233            ResourceEnterCall => format!("component-resource-enter-call"),
1234            ResourceExitCall => format!("component-resource-exit-call"),
1235            PrepareCall { .. } => format!("component-prepare-call"),
1236            SyncStartCall { .. } => format!("component-sync-start-call"),
1237            AsyncStartCall { .. } => format!("component-async-start-call"),
1238            FutureTransfer => format!("future-transfer"),
1239            StreamTransfer => format!("stream-transfer"),
1240            ErrorContextTransfer => format!("error-context-transfer"),
1241            CheckBlocking => format!("check-blocking"),
1242            ContextGet { .. } => format!("context-get"),
1243            ContextSet { .. } => format!("context-set"),
1244            ThreadIndex => format!("thread-index"),
1245            ThreadNewIndirect { .. } => format!("thread-new-indirect"),
1246            ThreadSwitchTo { .. } => format!("thread-switch-to"),
1247            ThreadSuspend { .. } => format!("thread-suspend"),
1248            ThreadResumeLater { .. } => format!("thread-resume-later"),
1249            ThreadYieldTo { .. } => format!("thread-yield-to"),
1250        }
1251    }
1252}