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 
49 use crate::component::*;
50 use crate::prelude::*;
51 use crate::{EntityIndex, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
52 use cranelift_entity::packed_option::PackedOption;
53 use serde_derive::{Deserialize, Serialize};
54 
55 /// Metadata as a result of compiling a component.
56 pub 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)]
74 pub 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 
208 impl 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.
defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex>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.
resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex222     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)]
239 pub 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     ///
247     /// The second field represents the component instance to which the module
248     /// belongs, if applicable.  This will be `None` for adapter modules.
249     InstantiateModule(InstantiateModule, Option<RuntimeComponentInstanceIndex>),
250 
251     /// A host function is being lowered, creating a core wasm function.
252     ///
253     /// This initializer entry is intended to be used to fill out the
254     /// `VMComponentContext` and information about this lowering such as the
255     /// cranelift-compiled trampoline function pointer, the host function
256     /// pointer the trampoline calls, and the canonical ABI options.
257     LowerImport {
258         /// The index of the lowered function that's being created.
259         ///
260         /// This is guaranteed to be the `n`th `LowerImport` instruction
261         /// if the index is `n`.
262         index: LoweredIndex,
263 
264         /// The index of the imported host function that is being lowered.
265         ///
266         /// It's guaranteed that this `RuntimeImportIndex` points to a function.
267         import: RuntimeImportIndex,
268     },
269 
270     /// A core wasm linear memory is going to be saved into the
271     /// `VMComponentContext`.
272     ///
273     /// This instruction indicates that a core wasm linear memory needs to be
274     /// extracted from the `export` and stored into the `VMComponentContext` at
275     /// the `index` specified. This lowering is then used in the future by
276     /// pointers from `CanonicalOptions`.
277     ExtractMemory(ExtractMemory),
278 
279     /// Same as `ExtractMemory`, except it's extracting a function pointer to be
280     /// used as a `realloc` function.
281     ExtractRealloc(ExtractRealloc),
282 
283     /// Same as `ExtractMemory`, except it's extracting a function pointer to be
284     /// used as an async `callback` function.
285     ExtractCallback(ExtractCallback),
286 
287     /// Same as `ExtractMemory`, except it's extracting a function pointer to be
288     /// used as a `post-return` function.
289     ExtractPostReturn(ExtractPostReturn),
290 
291     /// A core wasm table is going to be saved into the `VMComponentContext`.
292     ///
293     /// This instruction indicates that s core wasm table needs to be extracted
294     /// from its `export` and stored into the `VMComponentContext` at the
295     /// `index` specified. During this extraction, we will also capture the
296     /// table's containing instance pointer to access the table at runtime. This
297     /// extraction is useful for `thread.spawn-indirect`.
298     ExtractTable(ExtractTable),
299 
300     /// Declares a new defined resource within this component.
301     ///
302     /// Contains information about the destructor, for example.
303     Resource(Resource),
304 }
305 
306 /// Metadata for extraction of a memory; contains what's being extracted (the
307 /// memory at `export`) and where it's going (the `index` within a
308 /// `VMComponentContext`).
309 #[derive(Debug, Serialize, Deserialize)]
310 pub struct ExtractMemory {
311     /// The index of the memory being defined.
312     pub index: RuntimeMemoryIndex,
313     /// Where this memory is being extracted from.
314     pub export: CoreExport<MemoryIndex>,
315 }
316 
317 /// Same as `ExtractMemory` but for the `realloc` canonical option.
318 #[derive(Debug, Serialize, Deserialize)]
319 pub struct ExtractRealloc {
320     /// The index of the realloc being defined.
321     pub index: RuntimeReallocIndex,
322     /// Where this realloc is being extracted from.
323     pub def: CoreDef,
324 }
325 
326 /// Same as `ExtractMemory` but for the `callback` canonical option.
327 #[derive(Debug, Serialize, Deserialize)]
328 pub struct ExtractCallback {
329     /// The index of the callback being defined.
330     pub index: RuntimeCallbackIndex,
331     /// Where this callback is being extracted from.
332     pub def: CoreDef,
333 }
334 
335 /// Same as `ExtractMemory` but for the `post-return` canonical option.
336 #[derive(Debug, Serialize, Deserialize)]
337 pub struct ExtractPostReturn {
338     /// The index of the post-return being defined.
339     pub index: RuntimePostReturnIndex,
340     /// Where this post-return is being extracted from.
341     pub def: CoreDef,
342 }
343 
344 /// Metadata for extraction of a table.
345 #[derive(Debug, Serialize, Deserialize)]
346 pub struct ExtractTable {
347     /// The index of the table being defined in a `VMComponentContext`.
348     pub index: RuntimeTableIndex,
349     /// Where this table is being extracted from.
350     pub export: CoreExport<TableIndex>,
351 }
352 
353 /// Different methods of instantiating a core wasm module.
354 #[derive(Debug, Serialize, Deserialize)]
355 pub enum InstantiateModule {
356     /// A module defined within this component is being instantiated.
357     ///
358     /// Note that this is distinct from the case of imported modules because the
359     /// order of imports required is statically known and can be pre-calculated
360     /// to avoid string lookups related to names at runtime, represented by the
361     /// flat list of arguments here.
362     Static(StaticModuleIndex, Box<[CoreDef]>),
363 
364     /// An imported module is being instantiated.
365     ///
366     /// This is similar to `Upvar` but notably the imports are provided as a
367     /// two-level named map since import resolution order needs to happen at
368     /// runtime.
369     Import(
370         RuntimeImportIndex,
371         IndexMap<String, IndexMap<String, CoreDef>>,
372     ),
373 }
374 
375 /// Definition of a core wasm item and where it can come from within a
376 /// component.
377 ///
378 /// Note that this is sort of a result of data-flow-like analysis on a component
379 /// during compile time of the component itself. References to core wasm items
380 /// are "compiled" to either referring to a previous instance or to some sort of
381 /// lowered host import.
382 #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
383 pub enum CoreDef {
384     /// This item refers to an export of a previously instantiated core wasm
385     /// instance.
386     Export(CoreExport<EntityIndex>),
387     /// This is a reference to a wasm global which represents the
388     /// runtime-managed flags for a wasm instance.
389     InstanceFlags(RuntimeComponentInstanceIndex),
390     /// This is a reference to a Cranelift-generated trampoline which is
391     /// described in the `trampolines` array.
392     Trampoline(TrampolineIndex),
393     /// An intrinsic for compile-time builtins.
394     UnsafeIntrinsic(UnsafeIntrinsic),
395     /// Reference to a wasm global which represents a runtime-managed boolean
396     /// indicating whether the currently-running task may perform a blocking
397     /// operation.
398     TaskMayBlock,
399 }
400 
401 impl<T> From<CoreExport<T>> for CoreDef
402 where
403     EntityIndex: From<T>,
404 {
from(export: CoreExport<T>) -> CoreDef405     fn from(export: CoreExport<T>) -> CoreDef {
406         CoreDef::Export(export.map_index(|i| i.into()))
407     }
408 }
409 
410 /// Identifier of an exported item from a core WebAssembly module instance.
411 ///
412 /// Note that the `T` here is the index type for exports which can be
413 /// identified by index. The `T` is monomorphized with types like
414 /// [`EntityIndex`] or [`FuncIndex`].
415 #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
416 pub struct CoreExport<T> {
417     /// The instance that this item is located within.
418     ///
419     /// Note that this is intended to index the `instances` map within a
420     /// component. It's validated ahead of time that all instance pointers
421     /// refer only to previously-created instances.
422     pub instance: RuntimeInstanceIndex,
423 
424     /// The item that this export is referencing, either by name or by index.
425     pub item: ExportItem<T>,
426 }
427 
428 impl<T> CoreExport<T> {
429     /// Maps the index type `T` to another type `U` if this export item indeed
430     /// refers to an index `T`.
map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U>431     pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
432         CoreExport {
433             instance: self.instance,
434             item: match self.item {
435                 ExportItem::Index(i) => ExportItem::Index(f(i)),
436                 ExportItem::Name(s) => ExportItem::Name(s),
437             },
438         }
439     }
440 }
441 
442 /// An index at which to find an item within a runtime instance.
443 #[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
444 pub enum ExportItem<T> {
445     /// An exact index that the target can be found at.
446     ///
447     /// This is used where possible to avoid name lookups at runtime during the
448     /// instantiation process. This can only be used on instances where the
449     /// module was statically known at compile time, however.
450     Index(T),
451 
452     /// An item which is identified by a name, so at runtime we need to
453     /// perform a name lookup to determine the index that the item is located
454     /// at.
455     ///
456     /// This is used for instantiations of imported modules, for example, since
457     /// the precise shape of the module is not known.
458     Name(String),
459 }
460 
461 /// Possible exports from a component.
462 #[derive(Debug, Clone, Serialize, Deserialize)]
463 pub enum Export {
464     /// A lifted function being exported which is an adaptation of a core wasm
465     /// function.
466     LiftedFunction {
467         /// The component function type of the function being created.
468         ty: TypeFuncIndex,
469         /// Which core WebAssembly export is being lifted.
470         func: CoreDef,
471         /// Any options, if present, associated with this lifting.
472         options: OptionsIndex,
473     },
474     /// A module defined within this component is exported.
475     ModuleStatic {
476         /// The type of this module
477         ty: TypeModuleIndex,
478         /// Which module this is referring to.
479         index: StaticModuleIndex,
480     },
481     /// A module imported into this component is exported.
482     ModuleImport {
483         /// Module type index
484         ty: TypeModuleIndex,
485         /// Module runtime import index
486         import: RuntimeImportIndex,
487     },
488     /// A nested instance is being exported which has recursively defined
489     /// `Export` items.
490     Instance {
491         /// Instance type index, if such is assigned
492         ty: TypeComponentInstanceIndex,
493         /// Instance export map
494         exports: NameMap<String, ExportIndex>,
495     },
496     /// An exported type from a component or instance, currently only
497     /// informational.
498     Type(TypeDef),
499 }
500 
501 #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
502 /// Data is stored in a linear memory.
503 pub struct LinearMemoryOptions {
504     /// The memory used by these options, if specified.
505     pub memory: Option<RuntimeMemoryIndex>,
506     /// The realloc function used by these options, if specified.
507     pub realloc: Option<RuntimeReallocIndex>,
508 }
509 
510 /// The data model for objects that are not unboxed in locals.
511 #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
512 pub enum CanonicalOptionsDataModel {
513     /// Data is stored in GC objects.
514     Gc {},
515 
516     /// Data is stored in a linear memory.
517     LinearMemory(LinearMemoryOptions),
518 }
519 
520 /// Canonical ABI options associated with a lifted or lowered function.
521 #[derive(Debug, Clone, Serialize, Deserialize)]
522 pub struct CanonicalOptions {
523     /// The component instance that this bundle was associated with.
524     pub instance: RuntimeComponentInstanceIndex,
525 
526     /// The encoding used for strings.
527     pub string_encoding: StringEncoding,
528 
529     /// The async callback function used by these options, if specified.
530     pub callback: Option<RuntimeCallbackIndex>,
531 
532     /// The post-return function used by these options, if specified.
533     pub post_return: Option<RuntimePostReturnIndex>,
534 
535     /// Whether to use the async ABI for lifting or lowering.
536     pub async_: bool,
537 
538     /// Whether or not this function can consume a task cancellation
539     /// notification.
540     pub cancellable: bool,
541 
542     /// The core function type that is being lifted from / lowered to.
543     pub core_type: ModuleInternedTypeIndex,
544 
545     /// The data model (GC objects or linear memory) used with these canonical
546     /// options.
547     pub data_model: CanonicalOptionsDataModel,
548 }
549 
550 impl CanonicalOptions {
551     /// Returns the memory referred to by these options, if any.
memory(&self) -> Option<RuntimeMemoryIndex>552     pub fn memory(&self) -> Option<RuntimeMemoryIndex> {
553         match self.data_model {
554             CanonicalOptionsDataModel::Gc {} => None,
555             CanonicalOptionsDataModel::LinearMemory(opts) => opts.memory,
556         }
557     }
558 }
559 
560 /// Possible encodings of strings within the component model.
561 #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
562 #[expect(missing_docs, reason = "self-describing variants")]
563 pub enum StringEncoding {
564     Utf8,
565     Utf16,
566     CompactUtf16,
567 }
568 
569 impl StringEncoding {
570     /// Decodes the `u8` provided back into a `StringEncoding`, if it's valid.
from_u8(val: u8) -> Option<StringEncoding>571     pub fn from_u8(val: u8) -> Option<StringEncoding> {
572         if val == StringEncoding::Utf8 as u8 {
573             return Some(StringEncoding::Utf8);
574         }
575         if val == StringEncoding::Utf16 as u8 {
576             return Some(StringEncoding::Utf16);
577         }
578         if val == StringEncoding::CompactUtf16 as u8 {
579             return Some(StringEncoding::CompactUtf16);
580         }
581         None
582     }
583 }
584 
585 /// Possible transcoding operations that must be provided by the host.
586 ///
587 /// Note that each transcoding operation may have a unique signature depending
588 /// on the precise operation.
589 #[expect(missing_docs, reason = "self-describing variants")]
590 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
591 pub enum Transcode {
592     Copy(FixedEncoding),
593     Latin1ToUtf16,
594     Latin1ToUtf8,
595     Utf16ToCompactProbablyUtf16,
596     Utf16ToCompactUtf16,
597     Utf16ToLatin1,
598     Utf16ToUtf8,
599     Utf8ToCompactUtf16,
600     Utf8ToLatin1,
601     Utf8ToUtf16,
602 }
603 
604 impl Transcode {
605     /// Get this transcoding's symbol fragment.
symbol_fragment(&self) -> &'static str606     pub fn symbol_fragment(&self) -> &'static str {
607         match self {
608             Transcode::Copy(x) => match x {
609                 FixedEncoding::Utf8 => "copy_utf8",
610                 FixedEncoding::Utf16 => "copy_utf16",
611                 FixedEncoding::Latin1 => "copy_latin1",
612             },
613             Transcode::Latin1ToUtf16 => "latin1_to_utf16",
614             Transcode::Latin1ToUtf8 => "latin1_to_utf8",
615             Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",
616             Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",
617             Transcode::Utf16ToLatin1 => "utf16_to_latin1",
618             Transcode::Utf16ToUtf8 => "utf16_to_utf8",
619             Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",
620             Transcode::Utf8ToLatin1 => "utf8_to_latin1",
621             Transcode::Utf8ToUtf16 => "utf8_to_utf16",
622         }
623     }
624 
625     /// Returns a human-readable description for this transcoding operation.
desc(&self) -> &'static str626     pub fn desc(&self) -> &'static str {
627         match self {
628             Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",
629             Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",
630             Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",
631             Transcode::Latin1ToUtf16 => "latin1-to-utf16",
632             Transcode::Latin1ToUtf8 => "latin1-to-utf8",
633             Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",
634             Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",
635             Transcode::Utf16ToLatin1 => "utf16-to-latin1",
636             Transcode::Utf16ToUtf8 => "utf16-to-utf8",
637             Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",
638             Transcode::Utf8ToLatin1 => "utf8-to-latin1",
639             Transcode::Utf8ToUtf16 => "utf8-to-utf16",
640         }
641     }
642 }
643 
644 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
645 #[expect(missing_docs, reason = "self-describing variants")]
646 pub enum FixedEncoding {
647     Utf8,
648     Utf16,
649     Latin1,
650 }
651 
652 impl FixedEncoding {
653     /// Returns the byte width of unit loads/stores for this encoding, for
654     /// example the unit length is multiplied by this return value to get the
655     /// byte width of a string.
width(&self) -> u8656     pub fn width(&self) -> u8 {
657         match self {
658             FixedEncoding::Utf8 => 1,
659             FixedEncoding::Utf16 => 2,
660             FixedEncoding::Latin1 => 1,
661         }
662     }
663 
664     /// Returns the alignment of strings using this encoding.
align(&self) -> u8665     pub fn align(&self) -> u8 {
666         match self {
667             FixedEncoding::Utf8 => 1,
668             FixedEncoding::Utf16 => 2,
669             FixedEncoding::Latin1 => 2,
670         }
671     }
672 }
673 
674 /// Description of a new resource declared in a `GlobalInitializer::Resource`
675 /// variant.
676 ///
677 /// This will have the effect of initializing runtime state for this resource,
678 /// namely the destructor is fetched and stored.
679 #[derive(Debug, Serialize, Deserialize)]
680 pub struct Resource {
681     /// The local index of the resource being defined.
682     pub index: DefinedResourceIndex,
683     /// Core wasm representation of this resource.
684     pub rep: WasmValType,
685     /// Optionally-specified destructor and where it comes from.
686     pub dtor: Option<CoreDef>,
687     /// Which component instance this resource logically belongs to.
688     pub instance: RuntimeComponentInstanceIndex,
689 }
690 
691 /// A list of all possible trampolines that may be required to compile a
692 /// component completely.
693 ///
694 /// These trampolines are used often as core wasm definitions and require
695 /// Cranelift support to generate these functions. Each trampoline serves a
696 /// different purpose for implementing bits and pieces of the component model.
697 ///
698 /// All trampolines have a core wasm function signature associated with them
699 /// which is stored in the `Component::trampolines` array.
700 ///
701 /// Note that this type does not implement `Serialize` or `Deserialize` and
702 /// that's intentional as this isn't stored in the final compilation artifact.
703 #[derive(Debug)]
704 pub enum Trampoline {
705     /// Description of a lowered import used in conjunction with
706     /// `GlobalInitializer::LowerImport`.
707     LowerImport {
708         /// The runtime lowering state that this trampoline will access.
709         index: LoweredIndex,
710 
711         /// The type of the function that is being lowered, as perceived by the
712         /// component doing the lowering.
713         lower_ty: TypeFuncIndex,
714 
715         /// The canonical ABI options used when lowering this function specified
716         /// in the original component.
717         options: OptionsIndex,
718     },
719 
720     /// Information about a string transcoding function required by an adapter
721     /// module.
722     ///
723     /// A transcoder is used when strings are passed between adapter modules,
724     /// optionally changing string encodings at the same time. The transcoder is
725     /// implemented in a few different layers:
726     ///
727     /// * Each generated adapter module has some glue around invoking the
728     ///   transcoder represented by this item. This involves bounds-checks and
729     ///   handling `realloc` for example.
730     /// * Each transcoder gets a cranelift-generated trampoline which has the
731     ///   appropriate signature for the adapter module in question. Existence of
732     ///   this initializer indicates that this should be compiled by Cranelift.
733     /// * The cranelift-generated trampoline will invoke a "transcoder libcall"
734     ///   which is implemented natively in Rust that has a signature independent
735     ///   of memory64 configuration options for example.
736     Transcoder {
737         /// The transcoding operation being performed.
738         op: Transcode,
739         /// The linear memory that the string is being read from.
740         from: RuntimeMemoryIndex,
741         /// Whether or not the source linear memory is 64-bit or not.
742         from64: bool,
743         /// The linear memory that the string is being written to.
744         to: RuntimeMemoryIndex,
745         /// Whether or not the destination linear memory is 64-bit or not.
746         to64: bool,
747     },
748 
749     /// A `resource.new` intrinsic which will inject a new resource into the
750     /// table specified.
751     ResourceNew {
752         /// The specific component instance which is calling the intrinsic.
753         instance: RuntimeComponentInstanceIndex,
754         /// The type of the resource.
755         ty: TypeResourceTableIndex,
756     },
757 
758     /// Same as `ResourceNew`, but for the `resource.rep` intrinsic.
759     ResourceRep {
760         /// The specific component instance which is calling the intrinsic.
761         instance: RuntimeComponentInstanceIndex,
762         /// The type of the resource.
763         ty: TypeResourceTableIndex,
764     },
765 
766     /// Same as `ResourceNew`, but for the `resource.drop` intrinsic.
767     ResourceDrop {
768         /// The specific component instance which is calling the intrinsic.
769         instance: RuntimeComponentInstanceIndex,
770         /// The type of the resource.
771         ty: TypeResourceTableIndex,
772     },
773 
774     /// A `backpressure.inc` intrinsic.
775     BackpressureInc {
776         /// The specific component instance which is calling the intrinsic.
777         instance: RuntimeComponentInstanceIndex,
778     },
779 
780     /// A `backpressure.dec` intrinsic.
781     BackpressureDec {
782         /// The specific component instance which is calling the intrinsic.
783         instance: RuntimeComponentInstanceIndex,
784     },
785 
786     /// A `task.return` intrinsic, which returns a result to the caller of a
787     /// lifted export function.  This allows the callee to continue executing
788     /// after returning a result.
789     TaskReturn {
790         /// The specific component instance which is calling the intrinsic.
791         instance: RuntimeComponentInstanceIndex,
792         /// Tuple representing the result types this intrinsic accepts.
793         results: TypeTupleIndex,
794         /// The canonical ABI options specified for this intrinsic.
795         options: OptionsIndex,
796     },
797 
798     /// A `task.cancel` intrinsic, which acknowledges a `CANCELLED` event
799     /// delivered to a guest task previously created by a call to an async
800     /// export.
801     TaskCancel {
802         /// The specific component instance which is calling the intrinsic.
803         instance: RuntimeComponentInstanceIndex,
804     },
805 
806     /// A `waitable-set.new` intrinsic.
807     WaitableSetNew {
808         /// The specific component instance which is calling the intrinsic.
809         instance: RuntimeComponentInstanceIndex,
810     },
811 
812     /// A `waitable-set.wait` intrinsic, which waits for at least one
813     /// outstanding async task/stream/future to make progress, returning the
814     /// first such event.
815     WaitableSetWait {
816         /// The specific component instance which is calling the intrinsic.
817         instance: RuntimeComponentInstanceIndex,
818         /// Configuration options for this intrinsic call.
819         options: OptionsIndex,
820     },
821 
822     /// A `waitable-set.poll` intrinsic, which checks whether any outstanding
823     /// async task/stream/future has made progress.  Unlike `task.wait`, this
824     /// does not block and may return nothing if no such event has occurred.
825     WaitableSetPoll {
826         /// The specific component instance which is calling the intrinsic.
827         instance: RuntimeComponentInstanceIndex,
828         /// Configuration options for this intrinsic call.
829         options: OptionsIndex,
830     },
831 
832     /// A `waitable-set.drop` intrinsic.
833     WaitableSetDrop {
834         /// The specific component instance which is calling the intrinsic.
835         instance: RuntimeComponentInstanceIndex,
836     },
837 
838     /// A `waitable.join` intrinsic.
839     WaitableJoin {
840         /// The specific component instance which is calling the intrinsic.
841         instance: RuntimeComponentInstanceIndex,
842     },
843 
844     /// A `thread.yield` intrinsic, which yields control to the host so that other
845     /// tasks are able to make progress, if any.
846     ThreadYield {
847         /// The specific component instance which is calling the intrinsic.
848         instance: RuntimeComponentInstanceIndex,
849         /// If `true`, indicates the caller instance may receive notification
850         /// of task cancellation.
851         cancellable: bool,
852     },
853 
854     /// A `subtask.drop` intrinsic to drop a specified task which has completed.
855     SubtaskDrop {
856         /// The specific component instance which is calling the intrinsic.
857         instance: RuntimeComponentInstanceIndex,
858     },
859 
860     /// A `subtask.cancel` intrinsic to drop an in-progress task.
861     SubtaskCancel {
862         /// The specific component instance which is calling the intrinsic.
863         instance: RuntimeComponentInstanceIndex,
864         /// If `false`, block until cancellation completes rather than return
865         /// `BLOCKED`.
866         async_: bool,
867     },
868 
869     /// A `stream.new` intrinsic to create a new `stream` handle of the
870     /// specified type.
871     StreamNew {
872         /// The specific component instance which is calling the intrinsic.
873         instance: RuntimeComponentInstanceIndex,
874         /// The table index for the specific `stream` type and caller instance.
875         ty: TypeStreamTableIndex,
876     },
877 
878     /// A `stream.read` intrinsic to read from a `stream` of the specified type.
879     StreamRead {
880         /// The specific component instance which is calling the intrinsic.
881         instance: RuntimeComponentInstanceIndex,
882         /// The table index for the specific `stream` type and caller instance.
883         ty: TypeStreamTableIndex,
884         /// Any options (e.g. string encoding) to use when storing values to
885         /// memory.
886         options: OptionsIndex,
887     },
888 
889     /// A `stream.write` intrinsic to write to a `stream` of the specified type.
890     StreamWrite {
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         /// Any options (e.g. string encoding) to use when storing values to
896         /// memory.
897         options: OptionsIndex,
898     },
899 
900     /// A `stream.cancel-read` intrinsic to cancel an in-progress read from a
901     /// `stream` of the specified type.
902     StreamCancelRead {
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.cancel-write` intrinsic to cancel an in-progress write from a
913     /// `stream` of the specified type.
914     StreamCancelWrite {
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         /// If `false`, block until cancellation completes rather than return
920         /// `BLOCKED`.
921         async_: bool,
922     },
923 
924     /// A `stream.drop-readable` intrinsic to drop the readable end of a
925     /// `stream` of the specified type.
926     StreamDropReadable {
927         /// The specific component instance which is calling the intrinsic.
928         instance: RuntimeComponentInstanceIndex,
929         /// The table index for the specific `stream` type and caller instance.
930         ty: TypeStreamTableIndex,
931     },
932 
933     /// A `stream.drop-writable` intrinsic to drop the writable end of a
934     /// `stream` of the specified type.
935     StreamDropWritable {
936         /// The specific component instance which is calling the intrinsic.
937         instance: RuntimeComponentInstanceIndex,
938         /// The table index for the specific `stream` type and caller instance.
939         ty: TypeStreamTableIndex,
940     },
941 
942     /// A `future.new` intrinsic to create a new `future` handle of the
943     /// specified type.
944     FutureNew {
945         /// The specific component instance which is calling the intrinsic.
946         instance: RuntimeComponentInstanceIndex,
947         /// The table index for the specific `future` type and caller instance.
948         ty: TypeFutureTableIndex,
949     },
950 
951     /// A `future.read` intrinsic to read from a `future` of the specified type.
952     FutureRead {
953         /// The specific component instance which is calling the intrinsic.
954         instance: RuntimeComponentInstanceIndex,
955         /// The table index for the specific `future` type and caller instance.
956         ty: TypeFutureTableIndex,
957         /// Any options (e.g. string encoding) to use when storing values to
958         /// memory.
959         options: OptionsIndex,
960     },
961 
962     /// A `future.write` intrinsic to write to a `future` of the specified type.
963     FutureWrite {
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         /// Any options (e.g. string encoding) to use when storing values to
969         /// memory.
970         options: OptionsIndex,
971     },
972 
973     /// A `future.cancel-read` intrinsic to cancel an in-progress read from a
974     /// `future` of the specified type.
975     FutureCancelRead {
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.cancel-write` intrinsic to cancel an in-progress write from a
986     /// `future` of the specified type.
987     FutureCancelWrite {
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         /// If `false`, block until cancellation completes rather than return
993         /// `BLOCKED`.
994         async_: bool,
995     },
996 
997     /// A `future.drop-readable` intrinsic to drop the readable end of a
998     /// `future` of the specified type.
999     FutureDropReadable {
1000         /// The specific component instance which is calling the intrinsic.
1001         instance: RuntimeComponentInstanceIndex,
1002         /// The table index for the specific `future` type and caller instance.
1003         ty: TypeFutureTableIndex,
1004     },
1005 
1006     /// A `future.drop-writable` intrinsic to drop the writable end of a
1007     /// `future` of the specified type.
1008     FutureDropWritable {
1009         /// The specific component instance which is calling the intrinsic.
1010         instance: RuntimeComponentInstanceIndex,
1011         /// The table index for the specific `future` type and caller instance.
1012         ty: TypeFutureTableIndex,
1013     },
1014 
1015     /// A `error-context.new` intrinsic to create a new `error-context` with a
1016     /// specified debug message.
1017     ErrorContextNew {
1018         /// The specific component instance which is calling the intrinsic.
1019         instance: RuntimeComponentInstanceIndex,
1020         /// The table index for the `error-context` type in the caller instance.
1021         ty: TypeComponentLocalErrorContextTableIndex,
1022         /// String encoding, memory, etc. to use when loading debug message.
1023         options: OptionsIndex,
1024     },
1025 
1026     /// A `error-context.debug-message` intrinsic to get the debug message for a
1027     /// specified `error-context`.
1028     ///
1029     /// Note that the debug message might not necessarily match what was passed
1030     /// to `error.new`.
1031     ErrorContextDebugMessage {
1032         /// The specific component instance which is calling the intrinsic.
1033         instance: RuntimeComponentInstanceIndex,
1034         /// The table index for the `error-context` type in the caller instance.
1035         ty: TypeComponentLocalErrorContextTableIndex,
1036         /// String encoding, memory, etc. to use when storing debug message.
1037         options: OptionsIndex,
1038     },
1039 
1040     /// A `error-context.drop` intrinsic to drop a specified `error-context`.
1041     ErrorContextDrop {
1042         /// The specific component instance which is calling the intrinsic.
1043         instance: RuntimeComponentInstanceIndex,
1044         /// The table index for the `error-context` type in the caller instance.
1045         ty: TypeComponentLocalErrorContextTableIndex,
1046     },
1047 
1048     /// An intrinsic used by FACT-generated modules which will transfer an owned
1049     /// resource from one table to another. Used in component-to-component
1050     /// adapter trampolines.
1051     ResourceTransferOwn,
1052 
1053     /// Same as `ResourceTransferOwn` but for borrows.
1054     ResourceTransferBorrow,
1055 
1056     /// An intrinsic used by FACT-generated modules to prepare a call involving
1057     /// an async-lowered import and/or an async-lifted export.
1058     PrepareCall {
1059         /// The memory used to verify that the memory specified for the
1060         /// `task.return` that is called at runtime matches the one specified in
1061         /// the lifted export.
1062         memory: Option<RuntimeMemoryIndex>,
1063     },
1064 
1065     /// An intrinsic used by FACT-generated modules to start a call involving a
1066     /// sync-lowered import and async-lifted export.
1067     SyncStartCall {
1068         /// The callee's callback function, if any.
1069         callback: Option<RuntimeCallbackIndex>,
1070     },
1071 
1072     /// An intrinsic used by FACT-generated modules to start a call involving
1073     /// an async-lowered import function.
1074     ///
1075     /// Note that `AsyncPrepareCall` and `AsyncStartCall` could theoretically be
1076     /// combined into a single `AsyncCall` intrinsic, but we separate them to
1077     /// allow the FACT-generated module to optionally call the callee directly
1078     /// without an intermediate host stack frame.
1079     AsyncStartCall {
1080         /// The callee's callback, if any.
1081         callback: Option<RuntimeCallbackIndex>,
1082         /// The callee's post-return function, if any.
1083         post_return: Option<RuntimePostReturnIndex>,
1084     },
1085 
1086     /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1087     /// ownership of a `future`.
1088     ///
1089     /// Transferring a `future` can either mean giving away the readable end
1090     /// while retaining the writable end or only the former, depending on the
1091     /// ownership status of the `future`.
1092     FutureTransfer,
1093 
1094     /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1095     /// ownership of a `stream`.
1096     ///
1097     /// Transferring a `stream` can either mean giving away the readable end
1098     /// while retaining the writable end or only the former, depending on the
1099     /// ownership status of the `stream`.
1100     StreamTransfer,
1101 
1102     /// An intrinisic used by FACT-generated modules to (partially or entirely) transfer
1103     /// ownership of an `error-context`.
1104     ///
1105     /// Unlike futures, streams, and resource handles, `error-context` handles
1106     /// are reference counted, meaning that sharing the handle with another
1107     /// component does not invalidate the handle in the original component.
1108     ErrorContextTransfer,
1109 
1110     /// An intrinsic used by FACT-generated modules to trap with a specified
1111     /// code.
1112     Trap,
1113 
1114     /// An intrinsic used by FACT-generated modules to push a task onto the
1115     /// stack for a sync-to-sync, guest-to-guest call.
1116     EnterSyncCall,
1117     /// An intrinsic used by FACT-generated modules to pop the task previously
1118     /// pushed by `EnterSyncCall`.
1119     ExitSyncCall,
1120 
1121     /// Intrinsic used to implement the `context.get` component model builtin.
1122     ///
1123     /// The payload here represents that this is accessing the Nth slot of local
1124     /// storage.
1125     ContextGet {
1126         /// The specific component instance which is calling the intrinsic.
1127         instance: RuntimeComponentInstanceIndex,
1128         /// Which slot to access.
1129         slot: u32,
1130     },
1131 
1132     /// Intrinsic used to implement the `context.set` component model builtin.
1133     ///
1134     /// The payload here represents that this is accessing the Nth slot of local
1135     /// storage.
1136     ContextSet {
1137         /// The specific component instance which is calling the intrinsic.
1138         instance: RuntimeComponentInstanceIndex,
1139         /// Which slot to update.
1140         slot: u32,
1141     },
1142 
1143     /// Intrinsic used to implement the `thread.index` component model builtin.
1144     ThreadIndex,
1145 
1146     /// Intrinsic used to implement the `thread.new-indirect` component model builtin.
1147     ThreadNewIndirect {
1148         /// The specific component instance which is calling the intrinsic.
1149         instance: RuntimeComponentInstanceIndex,
1150         /// The type index for the start function of the thread.
1151         start_func_ty_idx: ComponentTypeIndex,
1152         /// The index of the table that stores the start function.
1153         start_func_table_idx: RuntimeTableIndex,
1154     },
1155 
1156     /// Intrinsic used to implement the `thread.suspend-to-suspended` component model builtin.
1157     ThreadSuspendToSuspended {
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.suspend-to` component model builtin.
1166     ThreadSuspendTo {
1167         /// The specific component instance which is calling the intrinsic.
1168         instance: RuntimeComponentInstanceIndex,
1169         /// If `true`, indicates the caller instance may receive notification
1170         /// of task cancellation.
1171         cancellable: bool,
1172     },
1173 
1174     /// Intrinsic used to implement the `thread.suspend` component model builtin.
1175     ThreadSuspend {
1176         /// The specific component instance which is calling the intrinsic.
1177         instance: RuntimeComponentInstanceIndex,
1178         /// If `true`, indicates the caller instance may receive notification
1179         /// of task cancellation.
1180         cancellable: bool,
1181     },
1182 
1183     /// Intrinsic used to implement the `thread.unsuspend` component model builtin.
1184     ThreadUnsuspend {
1185         /// The specific component instance which is calling the intrinsic.
1186         instance: RuntimeComponentInstanceIndex,
1187     },
1188 
1189     /// Intrinsic used to implement the `thread.yield-to-suspended` component model builtin.
1190     ThreadYieldToSuspended {
1191         /// The specific component instance which is calling the intrinsic.
1192         instance: RuntimeComponentInstanceIndex,
1193         /// If `true`, indicates the caller instance may receive notification
1194         /// of task cancellation.
1195         cancellable: bool,
1196     },
1197 }
1198 
1199 impl Trampoline {
1200     /// Returns the name to use for the symbol of this trampoline in the final
1201     /// compiled artifact
symbol_name(&self) -> String1202     pub fn symbol_name(&self) -> String {
1203         use Trampoline::*;
1204         match self {
1205             LowerImport { index, .. } => {
1206                 format!("component-lower-import[{}]", index.as_u32())
1207             }
1208             Transcoder {
1209                 op, from64, to64, ..
1210             } => {
1211                 let op = op.symbol_fragment();
1212                 let from = if *from64 { "64" } else { "32" };
1213                 let to = if *to64 { "64" } else { "32" };
1214                 format!("component-transcode-{op}-m{from}-m{to}")
1215             }
1216             ResourceNew { ty, .. } => format!("component-resource-new[{}]", ty.as_u32()),
1217             ResourceRep { ty, .. } => format!("component-resource-rep[{}]", ty.as_u32()),
1218             ResourceDrop { ty, .. } => format!("component-resource-drop[{}]", ty.as_u32()),
1219             BackpressureInc { .. } => format!("backpressure-inc"),
1220             BackpressureDec { .. } => format!("backpressure-dec"),
1221             TaskReturn { .. } => format!("task-return"),
1222             TaskCancel { .. } => format!("task-cancel"),
1223             WaitableSetNew { .. } => format!("waitable-set-new"),
1224             WaitableSetWait { .. } => format!("waitable-set-wait"),
1225             WaitableSetPoll { .. } => format!("waitable-set-poll"),
1226             WaitableSetDrop { .. } => format!("waitable-set-drop"),
1227             WaitableJoin { .. } => format!("waitable-join"),
1228             ThreadYield { .. } => format!("thread-yield"),
1229             SubtaskDrop { .. } => format!("subtask-drop"),
1230             SubtaskCancel { .. } => format!("subtask-cancel"),
1231             StreamNew { .. } => format!("stream-new"),
1232             StreamRead { .. } => format!("stream-read"),
1233             StreamWrite { .. } => format!("stream-write"),
1234             StreamCancelRead { .. } => format!("stream-cancel-read"),
1235             StreamCancelWrite { .. } => format!("stream-cancel-write"),
1236             StreamDropReadable { .. } => format!("stream-drop-readable"),
1237             StreamDropWritable { .. } => format!("stream-drop-writable"),
1238             FutureNew { .. } => format!("future-new"),
1239             FutureRead { .. } => format!("future-read"),
1240             FutureWrite { .. } => format!("future-write"),
1241             FutureCancelRead { .. } => format!("future-cancel-read"),
1242             FutureCancelWrite { .. } => format!("future-cancel-write"),
1243             FutureDropReadable { .. } => format!("future-drop-readable"),
1244             FutureDropWritable { .. } => format!("future-drop-writable"),
1245             ErrorContextNew { .. } => format!("error-context-new"),
1246             ErrorContextDebugMessage { .. } => format!("error-context-debug-message"),
1247             ErrorContextDrop { .. } => format!("error-context-drop"),
1248             ResourceTransferOwn => format!("component-resource-transfer-own"),
1249             ResourceTransferBorrow => format!("component-resource-transfer-borrow"),
1250             PrepareCall { .. } => format!("component-prepare-call"),
1251             SyncStartCall { .. } => format!("component-sync-start-call"),
1252             AsyncStartCall { .. } => format!("component-async-start-call"),
1253             FutureTransfer => format!("future-transfer"),
1254             StreamTransfer => format!("stream-transfer"),
1255             ErrorContextTransfer => format!("error-context-transfer"),
1256             Trap => format!("trap"),
1257             EnterSyncCall => format!("enter-sync-call"),
1258             ExitSyncCall => format!("exit-sync-call"),
1259             ContextGet { .. } => format!("context-get"),
1260             ContextSet { .. } => format!("context-set"),
1261             ThreadIndex => format!("thread-index"),
1262             ThreadNewIndirect { .. } => format!("thread-new-indirect"),
1263             ThreadSuspendToSuspended { .. } => format!("thread-suspend-to-suspended"),
1264             ThreadSuspendTo { .. } => format!("thread-suspend-to"),
1265             ThreadSuspend { .. } => format!("thread-suspend"),
1266             ThreadUnsuspend { .. } => format!("thread-unsuspend"),
1267             ThreadYieldToSuspended { .. } => format!("thread-yield-to-suspended"),
1268         }
1269     }
1270 }
1271