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, PrimaryMap, WasmValType};
52use serde_derive::{Deserialize, Serialize};
53use wasmtime_types::ModuleInternedTypeIndex;
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 reallocs (maximum `RuntimeReallocIndex`) needed to
146    /// instantiate this component.
147    ///
148    /// Note that this many function pointers will be stored in the
149    /// `VMComponentContext`.
150    pub num_runtime_reallocs: u32,
151
152    /// Same as `num_runtime_reallocs`, but for post-return functions.
153    pub num_runtime_post_returns: u32,
154
155    /// WebAssembly type signature of all trampolines.
156    pub trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
157
158    /// The number of lowered host functions (maximum `LoweredIndex`) needed to
159    /// instantiate this component.
160    pub num_lowerings: u32,
161
162    /// Maximal number of tables that required at runtime for resource-related
163    /// information in this component.
164    pub num_resource_tables: usize,
165
166    /// Total number of resources both imported and defined within this
167    /// component.
168    pub num_resources: u32,
169
170    /// Metadata about imported resources and where they are within the runtime
171    /// imports array.
172    ///
173    /// This map is only as large as the number of imported resources.
174    pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
175
176    /// Metadata about which component instances defined each resource within
177    /// this component.
178    ///
179    /// This is used to determine which set of instance flags are inspected when
180    /// testing reentrance.
181    pub defined_resource_instances: PrimaryMap<DefinedResourceIndex, RuntimeComponentInstanceIndex>,
182}
183
184impl Component {
185    /// Attempts to convert a resource index into a defined index.
186    ///
187    /// Returns `None` if `idx` is for an imported resource in this component or
188    /// `Some` if it's a locally defined resource.
189    pub fn defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex> {
190        let idx = idx
191            .as_u32()
192            .checked_sub(self.imported_resources.len() as u32)?;
193        Some(DefinedResourceIndex::from_u32(idx))
194    }
195
196    /// Converts a defined resource index to a component-local resource index
197    /// which includes all imports.
198    pub fn resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex {
199        ResourceIndex::from_u32(self.imported_resources.len() as u32 + idx.as_u32())
200    }
201}
202
203/// GlobalInitializer instructions to get processed when instantiating a component
204///
205/// The variants of this enum are processed during the instantiation phase of
206/// a component in-order from front-to-back. These are otherwise emitted as a
207/// component is parsed and read and translated.
208//
209// FIXME(#2639) if processing this list is ever a bottleneck we could
210// theoretically use cranelift to compile an initialization function which
211// performs all of these duties for us and skips the overhead of interpreting
212// all of these instructions.
213#[derive(Debug, Serialize, Deserialize)]
214pub enum GlobalInitializer {
215    /// A core wasm module is being instantiated.
216    ///
217    /// This will result in a new core wasm instance being created, which may
218    /// involve running the `start` function of the instance as well if it's
219    /// specified. This largely delegates to the same standard instantiation
220    /// process as the rest of the core wasm machinery already uses.
221    InstantiateModule(InstantiateModule),
222
223    /// A host function is being lowered, creating a core wasm function.
224    ///
225    /// This initializer entry is intended to be used to fill out the
226    /// `VMComponentContext` and information about this lowering such as the
227    /// cranelift-compiled trampoline function pointer, the host function
228    /// pointer the trampoline calls, and the canonical ABI options.
229    LowerImport {
230        /// The index of the lowered function that's being created.
231        ///
232        /// This is guaranteed to be the `n`th `LowerImport` instruction
233        /// if the index is `n`.
234        index: LoweredIndex,
235
236        /// The index of the imported host function that is being lowered.
237        ///
238        /// It's guaranteed that this `RuntimeImportIndex` points to a function.
239        import: RuntimeImportIndex,
240    },
241
242    /// A core wasm linear memory is going to be saved into the
243    /// `VMComponentContext`.
244    ///
245    /// This instruction indicates that the `index`th core wasm linear memory
246    /// needs to be extracted from the `export` specified, a pointer to a
247    /// previously created module instance, and stored into the
248    /// `VMComponentContext` at the `index` specified. This lowering is then
249    /// used in the future by pointers from `CanonicalOptions`.
250    ExtractMemory(ExtractMemory),
251
252    /// Same as `ExtractMemory`, except it's extracting a function pointer to be
253    /// used as a `realloc` function.
254    ExtractRealloc(ExtractRealloc),
255
256    /// Same as `ExtractMemory`, except it's extracting a function pointer to be
257    /// used as a `post-return` function.
258    ExtractPostReturn(ExtractPostReturn),
259
260    /// Declares a new defined resource within this component.
261    ///
262    /// Contains information about the destructor, for example.
263    Resource(Resource),
264}
265
266/// Metadata for extraction of a memory of what's being extracted and where it's
267/// going.
268#[derive(Debug, Serialize, Deserialize)]
269pub struct ExtractMemory {
270    /// The index of the memory being defined.
271    pub index: RuntimeMemoryIndex,
272    /// Where this memory is being extracted from.
273    pub export: CoreExport<MemoryIndex>,
274}
275
276/// Same as `ExtractMemory` but for the `realloc` canonical option.
277#[derive(Debug, Serialize, Deserialize)]
278pub struct ExtractRealloc {
279    /// The index of the realloc being defined.
280    pub index: RuntimeReallocIndex,
281    /// Where this realloc is being extracted from.
282    pub def: CoreDef,
283}
284
285/// Same as `ExtractMemory` but for the `post-return` canonical option.
286#[derive(Debug, Serialize, Deserialize)]
287pub struct ExtractPostReturn {
288    /// The index of the post-return being defined.
289    pub index: RuntimePostReturnIndex,
290    /// Where this post-return is being extracted from.
291    pub def: CoreDef,
292}
293
294/// Different methods of instantiating a core wasm module.
295#[derive(Debug, Serialize, Deserialize)]
296pub enum InstantiateModule {
297    /// A module defined within this component is being instantiated.
298    ///
299    /// Note that this is distinct from the case of imported modules because the
300    /// order of imports required is statically known and can be pre-calculated
301    /// to avoid string lookups related to names at runtime, represented by the
302    /// flat list of arguments here.
303    Static(StaticModuleIndex, Box<[CoreDef]>),
304
305    /// An imported module is being instantiated.
306    ///
307    /// This is similar to `Upvar` but notably the imports are provided as a
308    /// two-level named map since import resolution order needs to happen at
309    /// runtime.
310    Import(
311        RuntimeImportIndex,
312        IndexMap<String, IndexMap<String, CoreDef>>,
313    ),
314}
315
316/// Definition of a core wasm item and where it can come from within a
317/// component.
318///
319/// Note that this is sort of a result of data-flow-like analysis on a component
320/// during compile time of the component itself. References to core wasm items
321/// are "compiled" to either referring to a previous instance or to some sort of
322/// lowered host import.
323#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
324pub enum CoreDef {
325    /// This item refers to an export of a previously instantiated core wasm
326    /// instance.
327    Export(CoreExport<EntityIndex>),
328    /// This is a reference to a wasm global which represents the
329    /// runtime-managed flags for a wasm instance.
330    InstanceFlags(RuntimeComponentInstanceIndex),
331    /// This is a reference to a Cranelift-generated trampoline which is
332    /// described in the `trampolines` array.
333    Trampoline(TrampolineIndex),
334}
335
336impl<T> From<CoreExport<T>> for CoreDef
337where
338    EntityIndex: From<T>,
339{
340    fn from(export: CoreExport<T>) -> CoreDef {
341        CoreDef::Export(export.map_index(|i| i.into()))
342    }
343}
344
345/// Identifier of an exported item from a core WebAssembly module instance.
346///
347/// Note that the `T` here is the index type for exports which can be
348/// identified by index. The `T` is monomorphized with types like
349/// [`EntityIndex`] or [`FuncIndex`].
350#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
351pub struct CoreExport<T> {
352    /// The instance that this item is located within.
353    ///
354    /// Note that this is intended to index the `instances` map within a
355    /// component. It's validated ahead of time that all instance pointers
356    /// refer only to previously-created instances.
357    pub instance: RuntimeInstanceIndex,
358
359    /// The item that this export is referencing, either by name or by index.
360    pub item: ExportItem<T>,
361}
362
363impl<T> CoreExport<T> {
364    /// Maps the index type `T` to another type `U` if this export item indeed
365    /// refers to an index `T`.
366    pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
367        CoreExport {
368            instance: self.instance,
369            item: match self.item {
370                ExportItem::Index(i) => ExportItem::Index(f(i)),
371                ExportItem::Name(s) => ExportItem::Name(s),
372            },
373        }
374    }
375}
376
377/// An index at which to find an item within a runtime instance.
378#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
379pub enum ExportItem<T> {
380    /// An exact index that the target can be found at.
381    ///
382    /// This is used where possible to avoid name lookups at runtime during the
383    /// instantiation process. This can only be used on instances where the
384    /// module was statically known at compile time, however.
385    Index(T),
386
387    /// An item which is identified by a name, so at runtime we need to
388    /// perform a name lookup to determine the index that the item is located
389    /// at.
390    ///
391    /// This is used for instantiations of imported modules, for example, since
392    /// the precise shape of the module is not known.
393    Name(String),
394}
395
396/// Possible exports from a component.
397#[derive(Debug, Clone, Serialize, Deserialize)]
398pub enum Export {
399    /// A lifted function being exported which is an adaptation of a core wasm
400    /// function.
401    LiftedFunction {
402        /// The component function type of the function being created.
403        ty: TypeFuncIndex,
404        /// Which core WebAssembly export is being lifted.
405        func: CoreDef,
406        /// Any options, if present, associated with this lifting.
407        options: CanonicalOptions,
408    },
409    /// A module defined within this component is exported.
410    ModuleStatic {
411        /// The type of this module
412        ty: TypeModuleIndex,
413        /// Which module this is referring to.
414        index: StaticModuleIndex,
415    },
416    /// A module imported into this component is exported.
417    ModuleImport {
418        /// Module type index
419        ty: TypeModuleIndex,
420        /// Module runtime import index
421        import: RuntimeImportIndex,
422    },
423    /// A nested instance is being exported which has recursively defined
424    /// `Export` items.
425    Instance {
426        /// Instance type index, if such is assigned
427        ty: TypeComponentInstanceIndex,
428        /// Instance export map
429        exports: NameMap<String, ExportIndex>,
430    },
431    /// An exported type from a component or instance, currently only
432    /// informational.
433    Type(TypeDef),
434}
435
436/// Canonical ABI options associated with a lifted or lowered function.
437#[derive(Debug, Clone, Serialize, Deserialize)]
438pub struct CanonicalOptions {
439    /// The component instance that this bundle was associated with.
440    pub instance: RuntimeComponentInstanceIndex,
441
442    /// The encoding used for strings.
443    pub string_encoding: StringEncoding,
444
445    /// The memory used by these options, if specified.
446    pub memory: Option<RuntimeMemoryIndex>,
447
448    /// The realloc function used by these options, if specified.
449    pub realloc: Option<RuntimeReallocIndex>,
450
451    /// The post-return function used by these options, if specified.
452    pub post_return: Option<RuntimePostReturnIndex>,
453}
454
455/// Possible encodings of strings within the component model.
456//
457// Note that the `repr(u8)` is load-bearing here since this is used in an
458// `extern "C" fn()` function argument which is called from cranelift-compiled
459// code so we must know the representation of this.
460#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
461#[allow(missing_docs)]
462#[repr(u8)]
463pub enum StringEncoding {
464    Utf8,
465    Utf16,
466    CompactUtf16,
467}
468
469/// Possible transcoding operations that must be provided by the host.
470///
471/// Note that each transcoding operation may have a unique signature depending
472/// on the precise operation.
473#[allow(missing_docs)]
474#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
475pub enum Transcode {
476    Copy(FixedEncoding),
477    Latin1ToUtf16,
478    Latin1ToUtf8,
479    Utf16ToCompactProbablyUtf16,
480    Utf16ToCompactUtf16,
481    Utf16ToLatin1,
482    Utf16ToUtf8,
483    Utf8ToCompactUtf16,
484    Utf8ToLatin1,
485    Utf8ToUtf16,
486}
487
488impl Transcode {
489    /// Get this transcoding's symbol fragment.
490    pub fn symbol_fragment(&self) -> &'static str {
491        match self {
492            Transcode::Copy(x) => match x {
493                FixedEncoding::Utf8 => "copy_utf8",
494                FixedEncoding::Utf16 => "copy_utf16",
495                FixedEncoding::Latin1 => "copy_latin1",
496            },
497            Transcode::Latin1ToUtf16 => "latin1_to_utf16",
498            Transcode::Latin1ToUtf8 => "latin1_to_utf8",
499            Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",
500            Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",
501            Transcode::Utf16ToLatin1 => "utf16_to_latin1",
502            Transcode::Utf16ToUtf8 => "utf16_to_utf8",
503            Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",
504            Transcode::Utf8ToLatin1 => "utf8_to_latin1",
505            Transcode::Utf8ToUtf16 => "utf8_to_utf16",
506        }
507    }
508
509    /// Returns a human-readable description for this transcoding operation.
510    pub fn desc(&self) -> &'static str {
511        match self {
512            Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",
513            Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",
514            Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",
515            Transcode::Latin1ToUtf16 => "latin1-to-utf16",
516            Transcode::Latin1ToUtf8 => "latin1-to-utf8",
517            Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",
518            Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",
519            Transcode::Utf16ToLatin1 => "utf16-to-latin1",
520            Transcode::Utf16ToUtf8 => "utf16-to-utf8",
521            Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",
522            Transcode::Utf8ToLatin1 => "utf8-to-latin1",
523            Transcode::Utf8ToUtf16 => "utf8-to-utf16",
524        }
525    }
526}
527
528#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
529#[allow(missing_docs)]
530pub enum FixedEncoding {
531    Utf8,
532    Utf16,
533    Latin1,
534}
535
536impl FixedEncoding {
537    /// Returns the byte width of unit loads/stores for this encoding, for
538    /// example the unit length is multiplied by this return value to get the
539    /// byte width of a string.
540    pub fn width(&self) -> u8 {
541        match self {
542            FixedEncoding::Utf8 => 1,
543            FixedEncoding::Utf16 => 2,
544            FixedEncoding::Latin1 => 1,
545        }
546    }
547}
548
549/// Description of a new resource declared in a `GlobalInitializer::Resource`
550/// variant.
551///
552/// This will have the effect of initializing runtime state for this resource,
553/// namely the destructor is fetched and stored.
554#[derive(Debug, Serialize, Deserialize)]
555pub struct Resource {
556    /// The local index of the resource being defined.
557    pub index: DefinedResourceIndex,
558    /// Core wasm representation of this resource.
559    pub rep: WasmValType,
560    /// Optionally-specified destructor and where it comes from.
561    pub dtor: Option<CoreDef>,
562    /// Which component instance this resource logically belongs to.
563    pub instance: RuntimeComponentInstanceIndex,
564}
565
566/// A list of all possible trampolines that may be required to compile a
567/// component completely.
568///
569/// These trampolines are used often as core wasm definitions and require
570/// Cranelift support to generate these functions. Each trampoline serves a
571/// different purpose for implementing bits and pieces of the component model.
572///
573/// All trampolines have a core wasm function signature associated with them
574/// which is stored in the `Component::trampolines` array.
575///
576/// Note that this type does not implement `Serialize` or `Deserialize` and
577/// that's intentional as this isn't stored in the final compilation artifact.
578pub enum Trampoline {
579    /// Description of a lowered import used in conjunction with
580    /// `GlobalInitializer::LowerImport`.
581    LowerImport {
582        /// The runtime lowering state that this trampoline will access.
583        index: LoweredIndex,
584
585        /// The type of the function that is being lowered, as perceived by the
586        /// component doing the lowering.
587        lower_ty: TypeFuncIndex,
588
589        /// The canonical ABI options used when lowering this function specified
590        /// in the original component.
591        options: CanonicalOptions,
592    },
593
594    /// Information about a string transcoding function required by an adapter
595    /// module.
596    ///
597    /// A transcoder is used when strings are passed between adapter modules,
598    /// optionally changing string encodings at the same time. The transcoder is
599    /// implemented in a few different layers:
600    ///
601    /// * Each generated adapter module has some glue around invoking the
602    ///   transcoder represented by this item. This involves bounds-checks and
603    ///   handling `realloc` for example.
604    /// * Each transcoder gets a cranelift-generated trampoline which has the
605    ///   appropriate signature for the adapter module in question. Existence of
606    ///   this initializer indicates that this should be compiled by Cranelift.
607    /// * The cranelift-generated trampoline will invoke a "transcoder libcall"
608    ///   which is implemented natively in Rust that has a signature independent
609    ///   of memory64 configuration options for example.
610    Transcoder {
611        /// The transcoding operation being performed.
612        op: Transcode,
613        /// The linear memory that the string is being read from.
614        from: RuntimeMemoryIndex,
615        /// Whether or not the source linear memory is 64-bit or not.
616        from64: bool,
617        /// The linear memory that the string is being written to.
618        to: RuntimeMemoryIndex,
619        /// Whether or not the destination linear memory is 64-bit or not.
620        to64: bool,
621    },
622
623    /// A small adapter which simply traps, used for degenerate lift/lower
624    /// combinations.
625    AlwaysTrap,
626
627    /// A `resource.new` intrinsic which will inject a new resource into the
628    /// table specified.
629    ResourceNew(TypeResourceTableIndex),
630
631    /// Same as `ResourceNew`, but for the `resource.rep` intrinsic.
632    ResourceRep(TypeResourceTableIndex),
633
634    /// Same as `ResourceNew`, but for the `resource.drop` intrinsic.
635    ResourceDrop(TypeResourceTableIndex),
636
637    /// An intrinsic used by FACT-generated modules which will transfer an owned
638    /// resource from one table to another. Used in component-to-component
639    /// adapter trampolines.
640    ResourceTransferOwn,
641
642    /// Same as `ResourceTransferOwn` but for borrows.
643    ResourceTransferBorrow,
644
645    /// An intrinsic used by FACT-generated modules which indicates that a call
646    /// is being entered and resource-related metadata needs to be configured.
647    ///
648    /// Note that this is currently only invoked when borrowed resources are
649    /// detected, otherwise this is "optimized out".
650    ResourceEnterCall,
651
652    /// Same as `ResourceEnterCall` except for when exiting a call.
653    ResourceExitCall,
654}
655
656impl Trampoline {
657    /// Returns the name to use for the symbol of this trampoline in the final
658    /// compiled artifact
659    pub fn symbol_name(&self) -> String {
660        use Trampoline::*;
661        match self {
662            LowerImport { index, .. } => {
663                format!("component-lower-import[{}]", index.as_u32())
664            }
665            Transcoder {
666                op, from64, to64, ..
667            } => {
668                let op = op.symbol_fragment();
669                let from = if *from64 { "64" } else { "32" };
670                let to = if *to64 { "64" } else { "32" };
671                format!("component-transcode-{op}-m{from}-m{to}")
672            }
673            AlwaysTrap => format!("component-always-trap"),
674            ResourceNew(i) => format!("component-resource-new[{}]", i.as_u32()),
675            ResourceRep(i) => format!("component-resource-rep[{}]", i.as_u32()),
676            ResourceDrop(i) => format!("component-resource-drop[{}]", i.as_u32()),
677            ResourceTransferOwn => format!("component-resource-transfer-own"),
678            ResourceTransferBorrow => format!("component-resource-transfer-borrow"),
679            ResourceEnterCall => format!("component-resource-enter-call"),
680            ResourceExitCall => format!("component-resource-exit-call"),
681        }
682    }
683}