Path: blob/main/crates/environ/src/component/info.rs
1692 views
// General runtime type-information about a component.1//2// Compared to the `Module` structure for core wasm this type is pretty3// significantly different. The core wasm `Module` corresponds roughly 1-to-14// with the structure of the wasm module itself, but instead a `Component` is5// more of a "compiled" representation where the original structure is thrown6// away in favor of a more optimized representation. The considerations for this7// are:8//9// * This representation of a `Component` avoids the need to create a10// `PrimaryMap` of some form for each of the index spaces within a component.11// This is less so an issue about allocations and more so that this information12// generally just isn't needed any time after instantiation. Avoiding creating13// these altogether helps components be lighter weight at runtime and14// additionally accelerates instantiation.15//16// * Components can have arbitrary nesting and internally do instantiations via17// string-based matching. At instantiation-time, though, we want to do as few18// string-lookups in hash maps as much as we can since they're significantly19// slower than index-based lookups. Furthermore while the imports of a20// component are not statically known the rest of the structure of the21// component is statically known which enables the ability to track precisely22// what matches up where and do all the string lookups at compile time instead23// of instantiation time.24//25// * Finally by performing this sort of dataflow analysis we are capable of26// identifying what adapters need trampolines for compilation or fusion. For27// example this tracks when host functions are lowered which enables us to28// enumerate what trampolines are required to enter into a component.29// Additionally (eventually) this will track all of the "fused" adapter30// functions where a function from one component instance is lifted and then31// lowered into another component instance. Altogether this enables Wasmtime's32// AOT-compilation where the artifact from compilation is suitable for use in33// running the component without the support of a compiler at runtime.34//35// Note, however, that the current design of `Component` has fundamental36// limitations which it was not designed for. For example there is no feasible37// way to implement either importing or exporting a component itself from the38// root component. Currently we rely on the ability to have static knowledge of39// what's coming from the host which at this point can only be either functions40// or core wasm modules. Additionally one flat list of initializers for a41// component are produced instead of initializers-per-component which would42// otherwise be required to export a component from a component.43//44// For now this tradeoff is made as it aligns well with the intended use case45// for components in an embedding. This may need to be revisited though if the46// requirements of embeddings change over time.4748use crate::component::*;49use crate::prelude::*;50use crate::{EntityIndex, ModuleInternedTypeIndex, PrimaryMap, WasmValType};51use serde_derive::{Deserialize, Serialize};5253/// Metadata as a result of compiling a component.54pub struct ComponentTranslation {55/// Serializable information that will be emitted into the final artifact.56pub component: Component,5758/// Metadata about required trampolines and what they're supposed to do.59pub trampolines: PrimaryMap<TrampolineIndex, Trampoline>,60}6162/// Run-time-type-information about a `Component`, its structure, and how to63/// instantiate it.64///65/// This type is intended to mirror the `Module` type in this crate which66/// provides all the runtime information about the structure of a module and67/// how it works.68///69/// NB: Lots of the component model is not yet implemented in the runtime so70/// this is going to undergo a lot of churn.71#[derive(Default, Debug, Serialize, Deserialize)]72pub struct Component {73/// A list of typed values that this component imports.74///75/// Note that each name is given an `ImportIndex` here for the next map to76/// refer back to.77pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,7879/// A list of "flattened" imports that are used by this instance.80///81/// This import map represents extracting imports, as necessary, from the82/// general imported types by this component. The flattening here refers to83/// extracting items from instances. Currently the flat imports are either a84/// host function or a core wasm module.85///86/// For example if `ImportIndex(0)` pointed to an instance then this import87/// map represent extracting names from that map, for example extracting an88/// exported module or an exported function.89///90/// Each import item is keyed by a `RuntimeImportIndex` which is referred to91/// by types below whenever something refers to an import. The value for92/// each `RuntimeImportIndex` in this map is the `ImportIndex` for where93/// this items comes from (which can be associated with a name above in the94/// `import_types` array) as well as the list of export names if95/// `ImportIndex` refers to an instance. The export names array represents96/// recursively fetching names within an instance.97//98// TODO: this is probably a lot of `String` storage and may be something99// that needs optimization in the future. For example instead of lots of100// different `String` allocations this could instead be a pointer/length101// into one large string allocation for the entire component. Alternatively102// strings could otherwise be globally intern'd via some other mechanism to103// avoid `Linker`-specific intern-ing plus intern-ing here. Unsure what the104// best route is or whether such an optimization is even necessary here.105pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,106107/// This component's own root exports from the component itself.108pub exports: NameMap<String, ExportIndex>,109110/// All exports of this component and exported instances of this component.111///112/// This is indexed by `ExportIndex` for fast lookup and `Export::Instance`113/// will refer back into this list.114pub export_items: PrimaryMap<ExportIndex, Export>,115116/// Initializers that must be processed when instantiating this component.117///118/// This list of initializers does not correspond directly to the component119/// itself. The general goal with this is that the recursive nature of120/// components is "flattened" with an array like this which is a linear121/// sequence of instructions of how to instantiate a component. This will122/// have instantiations, for example, in addition to entries which123/// initialize `VMComponentContext` fields with previously instantiated124/// instances.125pub initializers: Vec<GlobalInitializer>,126127/// The number of runtime instances (maximum `RuntimeInstanceIndex`) created128/// when instantiating this component.129pub num_runtime_instances: u32,130131/// Same as `num_runtime_instances`, but for `RuntimeComponentInstanceIndex`132/// instead.133pub num_runtime_component_instances: u32,134135/// The number of runtime memories (maximum `RuntimeMemoryIndex`) needed to136/// instantiate this component.137///138/// Note that this many memories will be stored in the `VMComponentContext`139/// and each memory is intended to be unique (e.g. the same memory isn't140/// stored in two different locations).141pub num_runtime_memories: u32,142143/// The number of runtime tables (maximum `RuntimeTableIndex`) needed to144/// instantiate this component. See notes on `num_runtime_memories`.145pub num_runtime_tables: u32,146147/// The number of runtime reallocs (maximum `RuntimeReallocIndex`) needed to148/// instantiate this component.149///150/// Note that this many function pointers will be stored in the151/// `VMComponentContext`.152pub num_runtime_reallocs: u32,153154/// The number of runtime async callbacks (maximum `RuntimeCallbackIndex`)155/// needed to instantiate this component.156pub num_runtime_callbacks: u32,157158/// Same as `num_runtime_reallocs`, but for post-return functions.159pub num_runtime_post_returns: u32,160161/// WebAssembly type signature of all trampolines.162pub trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,163164/// The number of lowered host functions (maximum `LoweredIndex`) needed to165/// instantiate this component.166pub num_lowerings: u32,167168/// Total number of resources both imported and defined within this169/// component.170pub num_resources: u32,171172/// Maximal number of tables required at runtime for future-related173/// information in this component.174pub num_future_tables: usize,175176/// Maximal number of tables required at runtime for stream-related177/// information in this component.178pub num_stream_tables: usize,179180/// Maximal number of tables required at runtime for error-context-related181/// information in this component.182pub num_error_context_tables: usize,183184/// Metadata about imported resources and where they are within the runtime185/// imports array.186///187/// This map is only as large as the number of imported resources.188pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,189190/// Metadata about which component instances defined each resource within191/// this component.192///193/// This is used to determine which set of instance flags are inspected when194/// testing reentrance.195pub defined_resource_instances: PrimaryMap<DefinedResourceIndex, RuntimeComponentInstanceIndex>,196197/// All canonical options used by this component. Stored as a table here198/// from index-to-options so the options can be consulted at runtime.199pub options: PrimaryMap<OptionsIndex, CanonicalOptions>,200}201202impl Component {203/// Attempts to convert a resource index into a defined index.204///205/// Returns `None` if `idx` is for an imported resource in this component or206/// `Some` if it's a locally defined resource.207pub fn defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex> {208let idx = idx209.as_u32()210.checked_sub(self.imported_resources.len() as u32)?;211Some(DefinedResourceIndex::from_u32(idx))212}213214/// Converts a defined resource index to a component-local resource index215/// which includes all imports.216pub fn resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex {217ResourceIndex::from_u32(self.imported_resources.len() as u32 + idx.as_u32())218}219}220221/// GlobalInitializer instructions to get processed when instantiating a222/// component.223///224/// The variants of this enum are processed during the instantiation phase of a225/// component in-order from front-to-back. These are otherwise emitted as a226/// component is parsed and read and translated.227//228// FIXME(#2639) if processing this list is ever a bottleneck we could229// theoretically use cranelift to compile an initialization function which230// performs all of these duties for us and skips the overhead of interpreting231// all of these instructions.232#[derive(Debug, Serialize, Deserialize)]233pub enum GlobalInitializer {234/// A core wasm module is being instantiated.235///236/// This will result in a new core wasm instance being created, which may237/// involve running the `start` function of the instance as well if it's238/// specified. This largely delegates to the same standard instantiation239/// process as the rest of the core wasm machinery already uses.240InstantiateModule(InstantiateModule),241242/// A host function is being lowered, creating a core wasm function.243///244/// This initializer entry is intended to be used to fill out the245/// `VMComponentContext` and information about this lowering such as the246/// cranelift-compiled trampoline function pointer, the host function247/// pointer the trampoline calls, and the canonical ABI options.248LowerImport {249/// The index of the lowered function that's being created.250///251/// This is guaranteed to be the `n`th `LowerImport` instruction252/// if the index is `n`.253index: LoweredIndex,254255/// The index of the imported host function that is being lowered.256///257/// It's guaranteed that this `RuntimeImportIndex` points to a function.258import: RuntimeImportIndex,259},260261/// A core wasm linear memory is going to be saved into the262/// `VMComponentContext`.263///264/// This instruction indicates that a core wasm linear memory needs to be265/// extracted from the `export` and stored into the `VMComponentContext` at266/// the `index` specified. This lowering is then used in the future by267/// pointers from `CanonicalOptions`.268ExtractMemory(ExtractMemory),269270/// Same as `ExtractMemory`, except it's extracting a function pointer to be271/// used as a `realloc` function.272ExtractRealloc(ExtractRealloc),273274/// Same as `ExtractMemory`, except it's extracting a function pointer to be275/// used as an async `callback` function.276ExtractCallback(ExtractCallback),277278/// Same as `ExtractMemory`, except it's extracting a function pointer to be279/// used as a `post-return` function.280ExtractPostReturn(ExtractPostReturn),281282/// A core wasm table is going to be saved into the `VMComponentContext`.283///284/// This instruction indicates that s core wasm table needs to be extracted285/// from its `export` and stored into the `VMComponentContext` at the286/// `index` specified. During this extraction, we will also capture the287/// table's containing instance pointer to access the table at runtime. This288/// extraction is useful for `thread.spawn_indirect`.289ExtractTable(ExtractTable),290291/// Declares a new defined resource within this component.292///293/// Contains information about the destructor, for example.294Resource(Resource),295}296297/// Metadata for extraction of a memory; contains what's being extracted (the298/// memory at `export`) and where it's going (the `index` within a299/// `VMComponentContext`).300#[derive(Debug, Serialize, Deserialize)]301pub struct ExtractMemory {302/// The index of the memory being defined.303pub index: RuntimeMemoryIndex,304/// Where this memory is being extracted from.305pub export: CoreExport<MemoryIndex>,306}307308/// Same as `ExtractMemory` but for the `realloc` canonical option.309#[derive(Debug, Serialize, Deserialize)]310pub struct ExtractRealloc {311/// The index of the realloc being defined.312pub index: RuntimeReallocIndex,313/// Where this realloc is being extracted from.314pub def: CoreDef,315}316317/// Same as `ExtractMemory` but for the `callback` canonical option.318#[derive(Debug, Serialize, Deserialize)]319pub struct ExtractCallback {320/// The index of the callback being defined.321pub index: RuntimeCallbackIndex,322/// Where this callback is being extracted from.323pub def: CoreDef,324}325326/// Same as `ExtractMemory` but for the `post-return` canonical option.327#[derive(Debug, Serialize, Deserialize)]328pub struct ExtractPostReturn {329/// The index of the post-return being defined.330pub index: RuntimePostReturnIndex,331/// Where this post-return is being extracted from.332pub def: CoreDef,333}334335/// Metadata for extraction of a table.336#[derive(Debug, Serialize, Deserialize)]337pub struct ExtractTable {338/// The index of the table being defined in a `VMComponentContext`.339pub index: RuntimeTableIndex,340/// Where this table is being extracted from.341pub export: CoreExport<TableIndex>,342}343344/// Different methods of instantiating a core wasm module.345#[derive(Debug, Serialize, Deserialize)]346pub enum InstantiateModule {347/// A module defined within this component is being instantiated.348///349/// Note that this is distinct from the case of imported modules because the350/// order of imports required is statically known and can be pre-calculated351/// to avoid string lookups related to names at runtime, represented by the352/// flat list of arguments here.353Static(StaticModuleIndex, Box<[CoreDef]>),354355/// An imported module is being instantiated.356///357/// This is similar to `Upvar` but notably the imports are provided as a358/// two-level named map since import resolution order needs to happen at359/// runtime.360Import(361RuntimeImportIndex,362IndexMap<String, IndexMap<String, CoreDef>>,363),364}365366/// Definition of a core wasm item and where it can come from within a367/// component.368///369/// Note that this is sort of a result of data-flow-like analysis on a component370/// during compile time of the component itself. References to core wasm items371/// are "compiled" to either referring to a previous instance or to some sort of372/// lowered host import.373#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]374pub enum CoreDef {375/// This item refers to an export of a previously instantiated core wasm376/// instance.377Export(CoreExport<EntityIndex>),378/// This is a reference to a wasm global which represents the379/// runtime-managed flags for a wasm instance.380InstanceFlags(RuntimeComponentInstanceIndex),381/// This is a reference to a Cranelift-generated trampoline which is382/// described in the `trampolines` array.383Trampoline(TrampolineIndex),384}385386impl<T> From<CoreExport<T>> for CoreDef387where388EntityIndex: From<T>,389{390fn from(export: CoreExport<T>) -> CoreDef {391CoreDef::Export(export.map_index(|i| i.into()))392}393}394395/// Identifier of an exported item from a core WebAssembly module instance.396///397/// Note that the `T` here is the index type for exports which can be398/// identified by index. The `T` is monomorphized with types like399/// [`EntityIndex`] or [`FuncIndex`].400#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]401pub struct CoreExport<T> {402/// The instance that this item is located within.403///404/// Note that this is intended to index the `instances` map within a405/// component. It's validated ahead of time that all instance pointers406/// refer only to previously-created instances.407pub instance: RuntimeInstanceIndex,408409/// The item that this export is referencing, either by name or by index.410pub item: ExportItem<T>,411}412413impl<T> CoreExport<T> {414/// Maps the index type `T` to another type `U` if this export item indeed415/// refers to an index `T`.416pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {417CoreExport {418instance: self.instance,419item: match self.item {420ExportItem::Index(i) => ExportItem::Index(f(i)),421ExportItem::Name(s) => ExportItem::Name(s),422},423}424}425}426427/// An index at which to find an item within a runtime instance.428#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]429pub enum ExportItem<T> {430/// An exact index that the target can be found at.431///432/// This is used where possible to avoid name lookups at runtime during the433/// instantiation process. This can only be used on instances where the434/// module was statically known at compile time, however.435Index(T),436437/// An item which is identified by a name, so at runtime we need to438/// perform a name lookup to determine the index that the item is located439/// at.440///441/// This is used for instantiations of imported modules, for example, since442/// the precise shape of the module is not known.443Name(String),444}445446/// Possible exports from a component.447#[derive(Debug, Clone, Serialize, Deserialize)]448pub enum Export {449/// A lifted function being exported which is an adaptation of a core wasm450/// function.451LiftedFunction {452/// The component function type of the function being created.453ty: TypeFuncIndex,454/// Which core WebAssembly export is being lifted.455func: CoreDef,456/// Any options, if present, associated with this lifting.457options: OptionsIndex,458},459/// A module defined within this component is exported.460ModuleStatic {461/// The type of this module462ty: TypeModuleIndex,463/// Which module this is referring to.464index: StaticModuleIndex,465},466/// A module imported into this component is exported.467ModuleImport {468/// Module type index469ty: TypeModuleIndex,470/// Module runtime import index471import: RuntimeImportIndex,472},473/// A nested instance is being exported which has recursively defined474/// `Export` items.475Instance {476/// Instance type index, if such is assigned477ty: TypeComponentInstanceIndex,478/// Instance export map479exports: NameMap<String, ExportIndex>,480},481/// An exported type from a component or instance, currently only482/// informational.483Type(TypeDef),484}485486#[derive(Debug, Clone, Copy, Serialize, Deserialize)]487/// Data is stored in a linear memory.488pub struct LinearMemoryOptions {489/// The memory used by these options, if specified.490pub memory: Option<RuntimeMemoryIndex>,491/// The realloc function used by these options, if specified.492pub realloc: Option<RuntimeReallocIndex>,493}494495/// The data model for objects that are not unboxed in locals.496#[derive(Debug, Clone, Copy, Serialize, Deserialize)]497pub enum CanonicalOptionsDataModel {498/// Data is stored in GC objects.499Gc {},500501/// Data is stored in a linear memory.502LinearMemory(LinearMemoryOptions),503}504505/// Canonical ABI options associated with a lifted or lowered function.506#[derive(Debug, Clone, Serialize, Deserialize)]507pub struct CanonicalOptions {508/// The component instance that this bundle was associated with.509pub instance: RuntimeComponentInstanceIndex,510511/// The encoding used for strings.512pub string_encoding: StringEncoding,513514/// The async callback function used by these options, if specified.515pub callback: Option<RuntimeCallbackIndex>,516517/// The post-return function used by these options, if specified.518pub post_return: Option<RuntimePostReturnIndex>,519520/// Whether to use the async ABI for lifting or lowering.521pub async_: bool,522523/// The core function type that is being lifted from / lowered to.524pub core_type: ModuleInternedTypeIndex,525526/// The data model (GC objects or linear memory) used with these canonical527/// options.528pub data_model: CanonicalOptionsDataModel,529}530531/// Possible encodings of strings within the component model.532#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]533#[expect(missing_docs, reason = "self-describing variants")]534pub enum StringEncoding {535Utf8,536Utf16,537CompactUtf16,538}539540impl StringEncoding {541/// Decodes the `u8` provided back into a `StringEncoding`, if it's valid.542pub fn from_u8(val: u8) -> Option<StringEncoding> {543if val == StringEncoding::Utf8 as u8 {544return Some(StringEncoding::Utf8);545}546if val == StringEncoding::Utf16 as u8 {547return Some(StringEncoding::Utf16);548}549if val == StringEncoding::CompactUtf16 as u8 {550return Some(StringEncoding::CompactUtf16);551}552None553}554}555556/// Possible transcoding operations that must be provided by the host.557///558/// Note that each transcoding operation may have a unique signature depending559/// on the precise operation.560#[expect(missing_docs, reason = "self-describing variants")]561#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]562pub enum Transcode {563Copy(FixedEncoding),564Latin1ToUtf16,565Latin1ToUtf8,566Utf16ToCompactProbablyUtf16,567Utf16ToCompactUtf16,568Utf16ToLatin1,569Utf16ToUtf8,570Utf8ToCompactUtf16,571Utf8ToLatin1,572Utf8ToUtf16,573}574575impl Transcode {576/// Get this transcoding's symbol fragment.577pub fn symbol_fragment(&self) -> &'static str {578match self {579Transcode::Copy(x) => match x {580FixedEncoding::Utf8 => "copy_utf8",581FixedEncoding::Utf16 => "copy_utf16",582FixedEncoding::Latin1 => "copy_latin1",583},584Transcode::Latin1ToUtf16 => "latin1_to_utf16",585Transcode::Latin1ToUtf8 => "latin1_to_utf8",586Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",587Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",588Transcode::Utf16ToLatin1 => "utf16_to_latin1",589Transcode::Utf16ToUtf8 => "utf16_to_utf8",590Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",591Transcode::Utf8ToLatin1 => "utf8_to_latin1",592Transcode::Utf8ToUtf16 => "utf8_to_utf16",593}594}595596/// Returns a human-readable description for this transcoding operation.597pub fn desc(&self) -> &'static str {598match self {599Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",600Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",601Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",602Transcode::Latin1ToUtf16 => "latin1-to-utf16",603Transcode::Latin1ToUtf8 => "latin1-to-utf8",604Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",605Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",606Transcode::Utf16ToLatin1 => "utf16-to-latin1",607Transcode::Utf16ToUtf8 => "utf16-to-utf8",608Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",609Transcode::Utf8ToLatin1 => "utf8-to-latin1",610Transcode::Utf8ToUtf16 => "utf8-to-utf16",611}612}613}614615#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]616#[expect(missing_docs, reason = "self-describing variants")]617pub enum FixedEncoding {618Utf8,619Utf16,620Latin1,621}622623impl FixedEncoding {624/// Returns the byte width of unit loads/stores for this encoding, for625/// example the unit length is multiplied by this return value to get the626/// byte width of a string.627pub fn width(&self) -> u8 {628match self {629FixedEncoding::Utf8 => 1,630FixedEncoding::Utf16 => 2,631FixedEncoding::Latin1 => 1,632}633}634}635636/// Description of a new resource declared in a `GlobalInitializer::Resource`637/// variant.638///639/// This will have the effect of initializing runtime state for this resource,640/// namely the destructor is fetched and stored.641#[derive(Debug, Serialize, Deserialize)]642pub struct Resource {643/// The local index of the resource being defined.644pub index: DefinedResourceIndex,645/// Core wasm representation of this resource.646pub rep: WasmValType,647/// Optionally-specified destructor and where it comes from.648pub dtor: Option<CoreDef>,649/// Which component instance this resource logically belongs to.650pub instance: RuntimeComponentInstanceIndex,651}652653/// A list of all possible trampolines that may be required to compile a654/// component completely.655///656/// These trampolines are used often as core wasm definitions and require657/// Cranelift support to generate these functions. Each trampoline serves a658/// different purpose for implementing bits and pieces of the component model.659///660/// All trampolines have a core wasm function signature associated with them661/// which is stored in the `Component::trampolines` array.662///663/// Note that this type does not implement `Serialize` or `Deserialize` and664/// that's intentional as this isn't stored in the final compilation artifact.665#[derive(Debug)]666pub enum Trampoline {667/// Description of a lowered import used in conjunction with668/// `GlobalInitializer::LowerImport`.669LowerImport {670/// The runtime lowering state that this trampoline will access.671index: LoweredIndex,672673/// The type of the function that is being lowered, as perceived by the674/// component doing the lowering.675lower_ty: TypeFuncIndex,676677/// The canonical ABI options used when lowering this function specified678/// in the original component.679options: OptionsIndex,680},681682/// Information about a string transcoding function required by an adapter683/// module.684///685/// A transcoder is used when strings are passed between adapter modules,686/// optionally changing string encodings at the same time. The transcoder is687/// implemented in a few different layers:688///689/// * Each generated adapter module has some glue around invoking the690/// transcoder represented by this item. This involves bounds-checks and691/// handling `realloc` for example.692/// * Each transcoder gets a cranelift-generated trampoline which has the693/// appropriate signature for the adapter module in question. Existence of694/// this initializer indicates that this should be compiled by Cranelift.695/// * The cranelift-generated trampoline will invoke a "transcoder libcall"696/// which is implemented natively in Rust that has a signature independent697/// of memory64 configuration options for example.698Transcoder {699/// The transcoding operation being performed.700op: Transcode,701/// The linear memory that the string is being read from.702from: RuntimeMemoryIndex,703/// Whether or not the source linear memory is 64-bit or not.704from64: bool,705/// The linear memory that the string is being written to.706to: RuntimeMemoryIndex,707/// Whether or not the destination linear memory is 64-bit or not.708to64: bool,709},710711/// A small adapter which simply traps, used for degenerate lift/lower712/// combinations.713AlwaysTrap,714715/// A `resource.new` intrinsic which will inject a new resource into the716/// table specified.717ResourceNew(TypeResourceTableIndex),718719/// Same as `ResourceNew`, but for the `resource.rep` intrinsic.720ResourceRep(TypeResourceTableIndex),721722/// Same as `ResourceNew`, but for the `resource.drop` intrinsic.723ResourceDrop(TypeResourceTableIndex),724725/// A `backpressure.set` intrinsic, which tells the host to enable or726/// disable backpressure for the caller's instance.727BackpressureSet {728/// The specific component instance which is calling the intrinsic.729instance: RuntimeComponentInstanceIndex,730},731732/// A `task.return` intrinsic, which returns a result to the caller of a733/// lifted export function. This allows the callee to continue executing734/// after returning a result.735TaskReturn {736/// Tuple representing the result types this intrinsic accepts.737results: TypeTupleIndex,738739/// The canonical ABI options specified for this intrinsic.740options: OptionsIndex,741},742743/// A `task.cancel` intrinsic, which acknowledges a `CANCELLED` event744/// delivered to a guest task previously created by a call to an async745/// export.746TaskCancel {747/// The specific component instance which is calling the intrinsic.748instance: RuntimeComponentInstanceIndex,749},750751/// A `waitable-set.new` intrinsic.752WaitableSetNew {753/// The specific component instance which is calling the intrinsic.754instance: RuntimeComponentInstanceIndex,755},756757/// A `waitable-set.wait` intrinsic, which waits for at least one758/// outstanding async task/stream/future to make progress, returning the759/// first such event.760WaitableSetWait {761/// Configuration options for this intrinsic call.762options: OptionsIndex,763},764765/// A `waitable-set.poll` intrinsic, which checks whether any outstanding766/// async task/stream/future has made progress. Unlike `task.wait`, this767/// does not block and may return nothing if no such event has occurred.768WaitableSetPoll {769/// Configuration options for this intrinsic call.770options: OptionsIndex,771},772773/// A `waitable-set.drop` intrinsic.774WaitableSetDrop {775/// The specific component instance which is calling the intrinsic.776instance: RuntimeComponentInstanceIndex,777},778779/// A `waitable.join` intrinsic.780WaitableJoin {781/// The specific component instance which is calling the intrinsic.782instance: RuntimeComponentInstanceIndex,783},784785/// A `yield` intrinsic, which yields control to the host so that other786/// tasks are able to make progress, if any.787Yield {788/// If `true`, indicates the caller instance maybe reentered.789async_: bool,790},791792/// A `subtask.drop` intrinsic to drop a specified task which has completed.793SubtaskDrop {794/// The specific component instance which is calling the intrinsic.795instance: RuntimeComponentInstanceIndex,796},797798/// A `subtask.cancel` intrinsic to drop an in-progress task.799SubtaskCancel {800/// The specific component instance which is calling the intrinsic.801instance: RuntimeComponentInstanceIndex,802/// If `false`, block until cancellation completes rather than return803/// `BLOCKED`.804async_: bool,805},806807/// A `stream.new` intrinsic to create a new `stream` handle of the808/// specified type.809StreamNew {810/// The table index for the specific `stream` type and caller instance.811ty: TypeStreamTableIndex,812},813814/// A `stream.read` intrinsic to read from a `stream` of the specified type.815StreamRead {816/// The table index for the specific `stream` type and caller instance.817ty: TypeStreamTableIndex,818819/// Any options (e.g. string encoding) to use when storing values to820/// memory.821options: OptionsIndex,822},823824/// A `stream.write` intrinsic to write to a `stream` of the specified type.825StreamWrite {826/// The table index for the specific `stream` type and caller instance.827ty: TypeStreamTableIndex,828829/// Any options (e.g. string encoding) to use when storing values to830/// memory.831options: OptionsIndex,832},833834/// A `stream.cancel-read` intrinsic to cancel an in-progress read from a835/// `stream` of the specified type.836StreamCancelRead {837/// The table index for the specific `stream` type and caller instance.838ty: TypeStreamTableIndex,839/// If `false`, block until cancellation completes rather than return840/// `BLOCKED`.841async_: bool,842},843844/// A `stream.cancel-write` intrinsic to cancel an in-progress write from a845/// `stream` of the specified type.846StreamCancelWrite {847/// The table index for the specific `stream` type and caller instance.848ty: TypeStreamTableIndex,849/// If `false`, block until cancellation completes rather than return850/// `BLOCKED`.851async_: bool,852},853854/// A `stream.drop-readable` intrinsic to drop the readable end of a855/// `stream` of the specified type.856StreamDropReadable {857/// The table index for the specific `stream` type and caller instance.858ty: TypeStreamTableIndex,859},860861/// A `stream.drop-writable` intrinsic to drop the writable end of a862/// `stream` of the specified type.863StreamDropWritable {864/// The table index for the specific `stream` type and caller instance.865ty: TypeStreamTableIndex,866},867868/// A `future.new` intrinsic to create a new `future` handle of the869/// specified type.870FutureNew {871/// The table index for the specific `future` type and caller instance.872ty: TypeFutureTableIndex,873},874875/// A `future.read` intrinsic to read from a `future` of the specified type.876FutureRead {877/// The table index for the specific `future` type and caller instance.878ty: TypeFutureTableIndex,879880/// Any options (e.g. string encoding) to use when storing values to881/// memory.882options: OptionsIndex,883},884885/// A `future.write` intrinsic to write to a `future` of the specified type.886FutureWrite {887/// The table index for the specific `future` type and caller instance.888ty: TypeFutureTableIndex,889890/// Any options (e.g. string encoding) to use when storing values to891/// memory.892options: OptionsIndex,893},894895/// A `future.cancel-read` intrinsic to cancel an in-progress read from a896/// `future` of the specified type.897FutureCancelRead {898/// The table index for the specific `future` type and caller instance.899ty: TypeFutureTableIndex,900/// If `false`, block until cancellation completes rather than return901/// `BLOCKED`.902async_: bool,903},904905/// A `future.cancel-write` intrinsic to cancel an in-progress write from a906/// `future` of the specified type.907FutureCancelWrite {908/// The table index for the specific `future` type and caller instance.909ty: TypeFutureTableIndex,910/// If `false`, block until cancellation completes rather than return911/// `BLOCKED`.912async_: bool,913},914915/// A `future.drop-readable` intrinsic to drop the readable end of a916/// `future` of the specified type.917FutureDropReadable {918/// The table index for the specific `future` type and caller instance.919ty: TypeFutureTableIndex,920},921922/// A `future.drop-writable` intrinsic to drop the writable end of a923/// `future` of the specified type.924FutureDropWritable {925/// The table index for the specific `future` type and caller instance.926ty: TypeFutureTableIndex,927},928929/// A `error-context.new` intrinsic to create a new `error-context` with a930/// specified debug message.931ErrorContextNew {932/// The table index for the `error-context` type in the caller instance.933ty: TypeComponentLocalErrorContextTableIndex,934/// String encoding, memory, etc. to use when loading debug message.935options: OptionsIndex,936},937938/// A `error-context.debug-message` intrinsic to get the debug message for a939/// specified `error-context`.940///941/// Note that the debug message might not necessarily match what was passed942/// to `error.new`.943ErrorContextDebugMessage {944/// The table index for the `error-context` type in the caller instance.945ty: TypeComponentLocalErrorContextTableIndex,946/// String encoding, memory, etc. to use when storing debug message.947options: OptionsIndex,948},949950/// A `error-context.drop` intrinsic to drop a specified `error-context`.951ErrorContextDrop {952/// The table index for the `error-context` type in the caller instance.953ty: TypeComponentLocalErrorContextTableIndex,954},955956/// An intrinsic used by FACT-generated modules which will transfer an owned957/// resource from one table to another. Used in component-to-component958/// adapter trampolines.959ResourceTransferOwn,960961/// Same as `ResourceTransferOwn` but for borrows.962ResourceTransferBorrow,963964/// An intrinsic used by FACT-generated modules which indicates that a call965/// is being entered and resource-related metadata needs to be configured.966///967/// Note that this is currently only invoked when borrowed resources are968/// detected, otherwise this is "optimized out".969ResourceEnterCall,970971/// Same as `ResourceEnterCall` except for when exiting a call.972ResourceExitCall,973974/// An intrinsic used by FACT-generated modules to prepare a call involving975/// an async-lowered import and/or an async-lifted export.976PrepareCall {977/// The memory used to verify that the memory specified for the978/// `task.return` that is called at runtime matches the one specified in979/// the lifted export.980memory: Option<RuntimeMemoryIndex>,981},982983/// An intrinsic used by FACT-generated modules to start a call involving a984/// sync-lowered import and async-lifted export.985SyncStartCall {986/// The callee's callback function, if any.987callback: Option<RuntimeCallbackIndex>,988},989990/// An intrinsic used by FACT-generated modules to start a call involving991/// an async-lowered import function.992///993/// Note that `AsyncPrepareCall` and `AsyncStartCall` could theoretically be994/// combined into a single `AsyncCall` intrinsic, but we separate them to995/// allow the FACT-generated module to optionally call the callee directly996/// without an intermediate host stack frame.997AsyncStartCall {998/// The callee's callback, if any.999callback: Option<RuntimeCallbackIndex>,10001001/// The callee's post-return function, if any.1002post_return: Option<RuntimePostReturnIndex>,1003},10041005/// An intrinisic used by FACT-generated modules to (partially or entirely) transfer1006/// ownership of a `future`.1007///1008/// Transferring a `future` can either mean giving away the readable end1009/// while retaining the writable end or only the former, depending on the1010/// ownership status of the `future`.1011FutureTransfer,10121013/// An intrinisic used by FACT-generated modules to (partially or entirely) transfer1014/// ownership of a `stream`.1015///1016/// Transferring a `stream` can either mean giving away the readable end1017/// while retaining the writable end or only the former, depending on the1018/// ownership status of the `stream`.1019StreamTransfer,10201021/// An intrinisic used by FACT-generated modules to (partially or entirely) transfer1022/// ownership of an `error-context`.1023///1024/// Unlike futures, streams, and resource handles, `error-context` handles1025/// are reference counted, meaning that sharing the handle with another1026/// component does not invalidate the handle in the original component.1027ErrorContextTransfer,10281029/// Intrinsic used to implement the `context.get` component model builtin.1030///1031/// The payload here represents that this is accessing the Nth slot of local1032/// storage.1033ContextGet(u32),10341035/// Intrinsic used to implement the `context.set` component model builtin.1036///1037/// The payload here represents that this is accessing the Nth slot of local1038/// storage.1039ContextSet(u32),1040}10411042impl Trampoline {1043/// Returns the name to use for the symbol of this trampoline in the final1044/// compiled artifact1045pub fn symbol_name(&self) -> String {1046use Trampoline::*;1047match self {1048LowerImport { index, .. } => {1049format!("component-lower-import[{}]", index.as_u32())1050}1051Transcoder {1052op, from64, to64, ..1053} => {1054let op = op.symbol_fragment();1055let from = if *from64 { "64" } else { "32" };1056let to = if *to64 { "64" } else { "32" };1057format!("component-transcode-{op}-m{from}-m{to}")1058}1059AlwaysTrap => format!("component-always-trap"),1060ResourceNew(i) => format!("component-resource-new[{}]", i.as_u32()),1061ResourceRep(i) => format!("component-resource-rep[{}]", i.as_u32()),1062ResourceDrop(i) => format!("component-resource-drop[{}]", i.as_u32()),1063BackpressureSet { .. } => format!("backpressure-set"),1064TaskReturn { .. } => format!("task-return"),1065TaskCancel { .. } => format!("task-cancel"),1066WaitableSetNew { .. } => format!("waitable-set-new"),1067WaitableSetWait { .. } => format!("waitable-set-wait"),1068WaitableSetPoll { .. } => format!("waitable-set-poll"),1069WaitableSetDrop { .. } => format!("waitable-set-drop"),1070WaitableJoin { .. } => format!("waitable-join"),1071Yield { .. } => format!("yield"),1072SubtaskDrop { .. } => format!("subtask-drop"),1073SubtaskCancel { .. } => format!("subtask-cancel"),1074StreamNew { .. } => format!("stream-new"),1075StreamRead { .. } => format!("stream-read"),1076StreamWrite { .. } => format!("stream-write"),1077StreamCancelRead { .. } => format!("stream-cancel-read"),1078StreamCancelWrite { .. } => format!("stream-cancel-write"),1079StreamDropReadable { .. } => format!("stream-drop-readable"),1080StreamDropWritable { .. } => format!("stream-drop-writable"),1081FutureNew { .. } => format!("future-new"),1082FutureRead { .. } => format!("future-read"),1083FutureWrite { .. } => format!("future-write"),1084FutureCancelRead { .. } => format!("future-cancel-read"),1085FutureCancelWrite { .. } => format!("future-cancel-write"),1086FutureDropReadable { .. } => format!("future-drop-readable"),1087FutureDropWritable { .. } => format!("future-drop-writable"),1088ErrorContextNew { .. } => format!("error-context-new"),1089ErrorContextDebugMessage { .. } => format!("error-context-debug-message"),1090ErrorContextDrop { .. } => format!("error-context-drop"),1091ResourceTransferOwn => format!("component-resource-transfer-own"),1092ResourceTransferBorrow => format!("component-resource-transfer-borrow"),1093ResourceEnterCall => format!("component-resource-enter-call"),1094ResourceExitCall => format!("component-resource-exit-call"),1095PrepareCall { .. } => format!("component-prepare-call"),1096SyncStartCall { .. } => format!("component-sync-start-call"),1097AsyncStartCall { .. } => format!("component-async-start-call"),1098FutureTransfer => format!("future-transfer"),1099StreamTransfer => format!("stream-transfer"),1100ErrorContextTransfer => format!("error-context-transfer"),1101ContextGet(_) => format!("context-get"),1102ContextSet(_) => format!("context-set"),1103}1104}1105}110611071108