1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
// General runtime type-information about a component.
//
// Compared to the `Module` structure for core wasm this type is pretty
// significantly different. The core wasm `Module` corresponds roughly 1-to-1
// with the structure of the wasm module itself, but instead a `Component` is
// more of a "compiled" representation where the original structure is thrown
// away in favor of a more optimized representation. The considerations for this
// are:
//
// * This representation of a `Component` avoids the need to create a
// `PrimaryMap` of some form for each of the index spaces within a component.
// This is less so an issue about allocations and more so that this information
// generally just isn't needed any time after instantiation. Avoiding creating
// these altogether helps components be lighter weight at runtime and
// additionally accelerates instantiation.
//
// * Components can have arbitrary nesting and internally do instantiations via
// string-based matching. At instantiation-time, though, we want to do as few
// string-lookups in hash maps as much as we can since they're significantly
// slower than index-based lookups. Furthermore while the imports of a
// component are not statically known the rest of the structure of the
// component is statically known which enables the ability to track precisely
// what matches up where and do all the string lookups at compile time instead
// of instantiation time.
//
// * Finally by performing this sort of dataflow analysis we are capable of
// identifying what adapters need trampolines for compilation or fusion. For
// example this tracks when host functions are lowered which enables us to
// enumerate what trampolines are required to enter into a component.
// Additionally (eventually) this will track all of the "fused" adapter
// functions where a function from one component instance is lifted and then
// lowered into another component instance. Altogether this enables Wasmtime's
// AOT-compilation where the artifact from compilation is suitable for use in
// running the component without the support of a compiler at runtime.
//
// Note, however, that the current design of `Component` has fundamental
// limitations which it was not designed for. For example there is no feasible
// way to implement either importing or exporting a component itself from the
// root component. Currently we rely on the ability to have static knowledge of
// what's coming from the host which at this point can only be either functions
// or core wasm modules. Additionally one flat list of initializers for a
// component are produced instead of initializers-per-component which would
// otherwise be required to export a component from a component.
//
// For now this tradeoff is made as it aligns well with the intended use case
// for components in an embedding. This may need to be revisited though if the
// requirements of embeddings change over time.
use crate::component::*;
use crate::prelude::*;
use crate::{EntityIndex, ModuleInternedTypeIndex, PrimaryMap, WasmValType};
use serde_derive::{Deserialize, Serialize};
/// Metadata as a result of compiling a component.
pub struct ComponentTranslation {
/// Serializable information that will be emitted into the final artifact.
pub component: Component,
/// Metadata about required trampolines and what they're supposed to do.
pub trampolines: PrimaryMap<TrampolineIndex, Trampoline>,
}
/// Run-time-type-information about a `Component`, its structure, and how to
/// instantiate it.
///
/// This type is intended to mirror the `Module` type in this crate which
/// provides all the runtime information about the structure of a module and
/// how it works.
///
/// NB: Lots of the component model is not yet implemented in the runtime so
/// this is going to undergo a lot of churn.
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Component {
/// A list of typed values that this component imports.
///
/// Note that each name is given an `ImportIndex` here for the next map to
/// refer back to.
pub import_types: PrimaryMap<ImportIndex, (String, TypeDef)>,
/// A list of "flattened" imports that are used by this instance.
///
/// This import map represents extracting imports, as necessary, from the
/// general imported types by this component. The flattening here refers to
/// extracting items from instances. Currently the flat imports are either a
/// host function or a core wasm module.
///
/// For example if `ImportIndex(0)` pointed to an instance then this import
/// map represent extracting names from that map, for example extracting an
/// exported module or an exported function.
///
/// Each import item is keyed by a `RuntimeImportIndex` which is referred to
/// by types below whenever something refers to an import. The value for
/// each `RuntimeImportIndex` in this map is the `ImportIndex` for where
/// this items comes from (which can be associated with a name above in the
/// `import_types` array) as well as the list of export names if
/// `ImportIndex` refers to an instance. The export names array represents
/// recursively fetching names within an instance.
//
// TODO: this is probably a lot of `String` storage and may be something
// that needs optimization in the future. For example instead of lots of
// different `String` allocations this could instead be a pointer/length
// into one large string allocation for the entire component. Alternatively
// strings could otherwise be globally intern'd via some other mechanism to
// avoid `Linker`-specific intern-ing plus intern-ing here. Unsure what the
// best route is or whether such an optimization is even necessary here.
pub imports: PrimaryMap<RuntimeImportIndex, (ImportIndex, Vec<String>)>,
/// This component's own root exports from the component itself.
pub exports: NameMap<String, ExportIndex>,
/// All exports of this component and exported instances of this component.
///
/// This is indexed by `ExportIndex` for fast lookup and `Export::Instance`
/// will refer back into this list.
pub export_items: PrimaryMap<ExportIndex, Export>,
/// Initializers that must be processed when instantiating this component.
///
/// This list of initializers does not correspond directly to the component
/// itself. The general goal with this is that the recursive nature of
/// components is "flattened" with an array like this which is a linear
/// sequence of instructions of how to instantiate a component. This will
/// have instantiations, for example, in addition to entries which
/// initialize `VMComponentContext` fields with previously instantiated
/// instances.
pub initializers: Vec<GlobalInitializer>,
/// The number of runtime instances (maximum `RuntimeInstanceIndex`) created
/// when instantiating this component.
pub num_runtime_instances: u32,
/// Same as `num_runtime_instances`, but for `RuntimeComponentInstanceIndex`
/// instead.
pub num_runtime_component_instances: u32,
/// The number of runtime memories (maximum `RuntimeMemoryIndex`) needed to
/// instantiate this component.
///
/// Note that this many memories will be stored in the `VMComponentContext`
/// and each memory is intended to be unique (e.g. the same memory isn't
/// stored in two different locations).
pub num_runtime_memories: u32,
/// The number of runtime reallocs (maximum `RuntimeReallocIndex`) needed to
/// instantiate this component.
///
/// Note that this many function pointers will be stored in the
/// `VMComponentContext`.
pub num_runtime_reallocs: u32,
/// Same as `num_runtime_reallocs`, but for post-return functions.
pub num_runtime_post_returns: u32,
/// WebAssembly type signature of all trampolines.
pub trampolines: PrimaryMap<TrampolineIndex, ModuleInternedTypeIndex>,
/// The number of lowered host functions (maximum `LoweredIndex`) needed to
/// instantiate this component.
pub num_lowerings: u32,
/// Maximal number of tables that required at runtime for resource-related
/// information in this component.
pub num_resource_tables: usize,
/// Total number of resources both imported and defined within this
/// component.
pub num_resources: u32,
/// Metadata about imported resources and where they are within the runtime
/// imports array.
///
/// This map is only as large as the number of imported resources.
pub imported_resources: PrimaryMap<ResourceIndex, RuntimeImportIndex>,
/// Metadata about which component instances defined each resource within
/// this component.
///
/// This is used to determine which set of instance flags are inspected when
/// testing reentrance.
pub defined_resource_instances: PrimaryMap<DefinedResourceIndex, RuntimeComponentInstanceIndex>,
}
impl Component {
/// Attempts to convert a resource index into a defined index.
///
/// Returns `None` if `idx` is for an imported resource in this component or
/// `Some` if it's a locally defined resource.
pub fn defined_resource_index(&self, idx: ResourceIndex) -> Option<DefinedResourceIndex> {
let idx = idx
.as_u32()
.checked_sub(self.imported_resources.len() as u32)?;
Some(DefinedResourceIndex::from_u32(idx))
}
/// Converts a defined resource index to a component-local resource index
/// which includes all imports.
pub fn resource_index(&self, idx: DefinedResourceIndex) -> ResourceIndex {
ResourceIndex::from_u32(self.imported_resources.len() as u32 + idx.as_u32())
}
}
/// GlobalInitializer instructions to get processed when instantiating a component
///
/// The variants of this enum are processed during the instantiation phase of
/// a component in-order from front-to-back. These are otherwise emitted as a
/// component is parsed and read and translated.
//
// FIXME(#2639) if processing this list is ever a bottleneck we could
// theoretically use cranelift to compile an initialization function which
// performs all of these duties for us and skips the overhead of interpreting
// all of these instructions.
#[derive(Debug, Serialize, Deserialize)]
pub enum GlobalInitializer {
/// A core wasm module is being instantiated.
///
/// This will result in a new core wasm instance being created, which may
/// involve running the `start` function of the instance as well if it's
/// specified. This largely delegates to the same standard instantiation
/// process as the rest of the core wasm machinery already uses.
InstantiateModule(InstantiateModule),
/// A host function is being lowered, creating a core wasm function.
///
/// This initializer entry is intended to be used to fill out the
/// `VMComponentContext` and information about this lowering such as the
/// cranelift-compiled trampoline function pointer, the host function
/// pointer the trampoline calls, and the canonical ABI options.
LowerImport {
/// The index of the lowered function that's being created.
///
/// This is guaranteed to be the `n`th `LowerImport` instruction
/// if the index is `n`.
index: LoweredIndex,
/// The index of the imported host function that is being lowered.
///
/// It's guaranteed that this `RuntimeImportIndex` points to a function.
import: RuntimeImportIndex,
},
/// A core wasm linear memory is going to be saved into the
/// `VMComponentContext`.
///
/// This instruction indicates that the `index`th core wasm linear memory
/// needs to be extracted from the `export` specified, a pointer to a
/// previously created module instance, and stored into the
/// `VMComponentContext` at the `index` specified. This lowering is then
/// used in the future by pointers from `CanonicalOptions`.
ExtractMemory(ExtractMemory),
/// Same as `ExtractMemory`, except it's extracting a function pointer to be
/// used as a `realloc` function.
ExtractRealloc(ExtractRealloc),
/// Same as `ExtractMemory`, except it's extracting a function pointer to be
/// used as a `post-return` function.
ExtractPostReturn(ExtractPostReturn),
/// Declares a new defined resource within this component.
///
/// Contains information about the destructor, for example.
Resource(Resource),
}
/// Metadata for extraction of a memory of what's being extracted and where it's
/// going.
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractMemory {
/// The index of the memory being defined.
pub index: RuntimeMemoryIndex,
/// Where this memory is being extracted from.
pub export: CoreExport<MemoryIndex>,
}
/// Same as `ExtractMemory` but for the `realloc` canonical option.
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractRealloc {
/// The index of the realloc being defined.
pub index: RuntimeReallocIndex,
/// Where this realloc is being extracted from.
pub def: CoreDef,
}
/// Same as `ExtractMemory` but for the `post-return` canonical option.
#[derive(Debug, Serialize, Deserialize)]
pub struct ExtractPostReturn {
/// The index of the post-return being defined.
pub index: RuntimePostReturnIndex,
/// Where this post-return is being extracted from.
pub def: CoreDef,
}
/// Different methods of instantiating a core wasm module.
#[derive(Debug, Serialize, Deserialize)]
pub enum InstantiateModule {
/// A module defined within this component is being instantiated.
///
/// Note that this is distinct from the case of imported modules because the
/// order of imports required is statically known and can be pre-calculated
/// to avoid string lookups related to names at runtime, represented by the
/// flat list of arguments here.
Static(StaticModuleIndex, Box<[CoreDef]>),
/// An imported module is being instantiated.
///
/// This is similar to `Upvar` but notably the imports are provided as a
/// two-level named map since import resolution order needs to happen at
/// runtime.
Import(
RuntimeImportIndex,
IndexMap<String, IndexMap<String, CoreDef>>,
),
}
/// Definition of a core wasm item and where it can come from within a
/// component.
///
/// Note that this is sort of a result of data-flow-like analysis on a component
/// during compile time of the component itself. References to core wasm items
/// are "compiled" to either referring to a previous instance or to some sort of
/// lowered host import.
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub enum CoreDef {
/// This item refers to an export of a previously instantiated core wasm
/// instance.
Export(CoreExport<EntityIndex>),
/// This is a reference to a wasm global which represents the
/// runtime-managed flags for a wasm instance.
InstanceFlags(RuntimeComponentInstanceIndex),
/// This is a reference to a Cranelift-generated trampoline which is
/// described in the `trampolines` array.
Trampoline(TrampolineIndex),
}
impl<T> From<CoreExport<T>> for CoreDef
where
EntityIndex: From<T>,
{
fn from(export: CoreExport<T>) -> CoreDef {
CoreDef::Export(export.map_index(|i| i.into()))
}
}
/// Identifier of an exported item from a core WebAssembly module instance.
///
/// Note that the `T` here is the index type for exports which can be
/// identified by index. The `T` is monomorphized with types like
/// [`EntityIndex`] or [`FuncIndex`].
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub struct CoreExport<T> {
/// The instance that this item is located within.
///
/// Note that this is intended to index the `instances` map within a
/// component. It's validated ahead of time that all instance pointers
/// refer only to previously-created instances.
pub instance: RuntimeInstanceIndex,
/// The item that this export is referencing, either by name or by index.
pub item: ExportItem<T>,
}
impl<T> CoreExport<T> {
/// Maps the index type `T` to another type `U` if this export item indeed
/// refers to an index `T`.
pub fn map_index<U>(self, f: impl FnOnce(T) -> U) -> CoreExport<U> {
CoreExport {
instance: self.instance,
item: match self.item {
ExportItem::Index(i) => ExportItem::Index(f(i)),
ExportItem::Name(s) => ExportItem::Name(s),
},
}
}
}
/// An index at which to find an item within a runtime instance.
#[derive(Debug, Clone, Serialize, Deserialize, Hash, Eq, PartialEq)]
pub enum ExportItem<T> {
/// An exact index that the target can be found at.
///
/// This is used where possible to avoid name lookups at runtime during the
/// instantiation process. This can only be used on instances where the
/// module was statically known at compile time, however.
Index(T),
/// An item which is identified by a name, so at runtime we need to
/// perform a name lookup to determine the index that the item is located
/// at.
///
/// This is used for instantiations of imported modules, for example, since
/// the precise shape of the module is not known.
Name(String),
}
/// Possible exports from a component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Export {
/// A lifted function being exported which is an adaptation of a core wasm
/// function.
LiftedFunction {
/// The component function type of the function being created.
ty: TypeFuncIndex,
/// Which core WebAssembly export is being lifted.
func: CoreDef,
/// Any options, if present, associated with this lifting.
options: CanonicalOptions,
},
/// A module defined within this component is exported.
ModuleStatic {
/// The type of this module
ty: TypeModuleIndex,
/// Which module this is referring to.
index: StaticModuleIndex,
},
/// A module imported into this component is exported.
ModuleImport {
/// Module type index
ty: TypeModuleIndex,
/// Module runtime import index
import: RuntimeImportIndex,
},
/// A nested instance is being exported which has recursively defined
/// `Export` items.
Instance {
/// Instance type index, if such is assigned
ty: TypeComponentInstanceIndex,
/// Instance export map
exports: NameMap<String, ExportIndex>,
},
/// An exported type from a component or instance, currently only
/// informational.
Type(TypeDef),
}
/// Canonical ABI options associated with a lifted or lowered function.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CanonicalOptions {
/// The component instance that this bundle was associated with.
pub instance: RuntimeComponentInstanceIndex,
/// The encoding used for strings.
pub string_encoding: StringEncoding,
/// The memory used by these options, if specified.
pub memory: Option<RuntimeMemoryIndex>,
/// The realloc function used by these options, if specified.
pub realloc: Option<RuntimeReallocIndex>,
/// The post-return function used by these options, if specified.
pub post_return: Option<RuntimePostReturnIndex>,
}
/// Possible encodings of strings within the component model.
//
// Note that the `repr(u8)` is load-bearing here since this is used in an
// `extern "C" fn()` function argument which is called from cranelift-compiled
// code so we must know the representation of this.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
#[repr(u8)]
pub enum StringEncoding {
Utf8,
Utf16,
CompactUtf16,
}
/// Possible transcoding operations that must be provided by the host.
///
/// Note that each transcoding operation may have a unique signature depending
/// on the precise operation.
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
pub enum Transcode {
Copy(FixedEncoding),
Latin1ToUtf16,
Latin1ToUtf8,
Utf16ToCompactProbablyUtf16,
Utf16ToCompactUtf16,
Utf16ToLatin1,
Utf16ToUtf8,
Utf8ToCompactUtf16,
Utf8ToLatin1,
Utf8ToUtf16,
}
impl Transcode {
/// Get this transcoding's symbol fragment.
pub fn symbol_fragment(&self) -> &'static str {
match self {
Transcode::Copy(x) => match x {
FixedEncoding::Utf8 => "copy_utf8",
FixedEncoding::Utf16 => "copy_utf16",
FixedEncoding::Latin1 => "copy_latin1",
},
Transcode::Latin1ToUtf16 => "latin1_to_utf16",
Transcode::Latin1ToUtf8 => "latin1_to_utf8",
Transcode::Utf16ToCompactProbablyUtf16 => "utf16_to_compact_probably_utf16",
Transcode::Utf16ToCompactUtf16 => "utf16_to_compact_utf16",
Transcode::Utf16ToLatin1 => "utf16_to_latin1",
Transcode::Utf16ToUtf8 => "utf16_to_utf8",
Transcode::Utf8ToCompactUtf16 => "utf8_to_compact_utf16",
Transcode::Utf8ToLatin1 => "utf8_to_latin1",
Transcode::Utf8ToUtf16 => "utf8_to_utf16",
}
}
/// Returns a human-readable description for this transcoding operation.
pub fn desc(&self) -> &'static str {
match self {
Transcode::Copy(FixedEncoding::Utf8) => "utf8-to-utf8",
Transcode::Copy(FixedEncoding::Utf16) => "utf16-to-utf16",
Transcode::Copy(FixedEncoding::Latin1) => "latin1-to-latin1",
Transcode::Latin1ToUtf16 => "latin1-to-utf16",
Transcode::Latin1ToUtf8 => "latin1-to-utf8",
Transcode::Utf16ToCompactProbablyUtf16 => "utf16-to-compact-probably-utf16",
Transcode::Utf16ToCompactUtf16 => "utf16-to-compact-utf16",
Transcode::Utf16ToLatin1 => "utf16-to-latin1",
Transcode::Utf16ToUtf8 => "utf16-to-utf8",
Transcode::Utf8ToCompactUtf16 => "utf8-to-compact-utf16",
Transcode::Utf8ToLatin1 => "utf8-to-latin1",
Transcode::Utf8ToUtf16 => "utf8-to-utf16",
}
}
}
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
#[allow(missing_docs)]
pub enum FixedEncoding {
Utf8,
Utf16,
Latin1,
}
impl FixedEncoding {
/// Returns the byte width of unit loads/stores for this encoding, for
/// example the unit length is multiplied by this return value to get the
/// byte width of a string.
pub fn width(&self) -> u8 {
match self {
FixedEncoding::Utf8 => 1,
FixedEncoding::Utf16 => 2,
FixedEncoding::Latin1 => 1,
}
}
}
/// Description of a new resource declared in a `GlobalInitializer::Resource`
/// variant.
///
/// This will have the effect of initializing runtime state for this resource,
/// namely the destructor is fetched and stored.
#[derive(Debug, Serialize, Deserialize)]
pub struct Resource {
/// The local index of the resource being defined.
pub index: DefinedResourceIndex,
/// Core wasm representation of this resource.
pub rep: WasmValType,
/// Optionally-specified destructor and where it comes from.
pub dtor: Option<CoreDef>,
/// Which component instance this resource logically belongs to.
pub instance: RuntimeComponentInstanceIndex,
}
/// A list of all possible trampolines that may be required to compile a
/// component completely.
///
/// These trampolines are used often as core wasm definitions and require
/// Cranelift support to generate these functions. Each trampoline serves a
/// different purpose for implementing bits and pieces of the component model.
///
/// All trampolines have a core wasm function signature associated with them
/// which is stored in the `Component::trampolines` array.
///
/// Note that this type does not implement `Serialize` or `Deserialize` and
/// that's intentional as this isn't stored in the final compilation artifact.
pub enum Trampoline {
/// Description of a lowered import used in conjunction with
/// `GlobalInitializer::LowerImport`.
LowerImport {
/// The runtime lowering state that this trampoline will access.
index: LoweredIndex,
/// The type of the function that is being lowered, as perceived by the
/// component doing the lowering.
lower_ty: TypeFuncIndex,
/// The canonical ABI options used when lowering this function specified
/// in the original component.
options: CanonicalOptions,
},
/// Information about a string transcoding function required by an adapter
/// module.
///
/// A transcoder is used when strings are passed between adapter modules,
/// optionally changing string encodings at the same time. The transcoder is
/// implemented in a few different layers:
///
/// * Each generated adapter module has some glue around invoking the
/// transcoder represented by this item. This involves bounds-checks and
/// handling `realloc` for example.
/// * Each transcoder gets a cranelift-generated trampoline which has the
/// appropriate signature for the adapter module in question. Existence of
/// this initializer indicates that this should be compiled by Cranelift.
/// * The cranelift-generated trampoline will invoke a "transcoder libcall"
/// which is implemented natively in Rust that has a signature independent
/// of memory64 configuration options for example.
Transcoder {
/// The transcoding operation being performed.
op: Transcode,
/// The linear memory that the string is being read from.
from: RuntimeMemoryIndex,
/// Whether or not the source linear memory is 64-bit or not.
from64: bool,
/// The linear memory that the string is being written to.
to: RuntimeMemoryIndex,
/// Whether or not the destination linear memory is 64-bit or not.
to64: bool,
},
/// A small adapter which simply traps, used for degenerate lift/lower
/// combinations.
AlwaysTrap,
/// A `resource.new` intrinsic which will inject a new resource into the
/// table specified.
ResourceNew(TypeResourceTableIndex),
/// Same as `ResourceNew`, but for the `resource.rep` intrinsic.
ResourceRep(TypeResourceTableIndex),
/// Same as `ResourceNew`, but for the `resource.drop` intrinsic.
ResourceDrop(TypeResourceTableIndex),
/// An intrinsic used by FACT-generated modules which will transfer an owned
/// resource from one table to another. Used in component-to-component
/// adapter trampolines.
ResourceTransferOwn,
/// Same as `ResourceTransferOwn` but for borrows.
ResourceTransferBorrow,
/// An intrinsic used by FACT-generated modules which indicates that a call
/// is being entered and resource-related metadata needs to be configured.
///
/// Note that this is currently only invoked when borrowed resources are
/// detected, otherwise this is "optimized out".
ResourceEnterCall,
/// Same as `ResourceEnterCall` except for when exiting a call.
ResourceExitCall,
}
impl Trampoline {
/// Returns the name to use for the symbol of this trampoline in the final
/// compiled artifact
pub fn symbol_name(&self) -> String {
use Trampoline::*;
match self {
LowerImport { index, .. } => {
format!("component-lower-import[{}]", index.as_u32())
}
Transcoder {
op, from64, to64, ..
} => {
let op = op.symbol_fragment();
let from = if *from64 { "64" } else { "32" };
let to = if *to64 { "64" } else { "32" };
format!("component-transcode-{op}-m{from}-m{to}")
}
AlwaysTrap => format!("component-always-trap"),
ResourceNew(i) => format!("component-resource-new[{}]", i.as_u32()),
ResourceRep(i) => format!("component-resource-rep[{}]", i.as_u32()),
ResourceDrop(i) => format!("component-resource-drop[{}]", i.as_u32()),
ResourceTransferOwn => format!("component-resource-transfer-own"),
ResourceTransferBorrow => format!("component-resource-transfer-borrow"),
ResourceEnterCall => format!("component-resource-enter-call"),
ResourceExitCall => format!("component-resource-exit-call"),
}
}
}