wasmtime_environ/component/translate/
inline.rs

1//! Implementation of "inlining" a component into a flat list of initializers.
2//!
3//! After the first phase of compiling a component we're left with a single
4//! root `Translation` for the original component along with a "static" list of
5//! child components. Each `Translation` has a list of `LocalInitializer` items
6//! inside of it which is a primitive representation of how the component
7//! should be constructed with effectively one initializer per item in the
8//! index space of a component. This "local initializer" list would be
9//! relatively inefficient to process at runtime and more importantly doesn't
10//! convey enough information to understand what trampolines need to be
11//! compiled or what fused adapters need to be generated. This consequently is
12//! the motivation for this file.
13//!
14//! The second phase of compilation, inlining here, will in a sense interpret
15//! the initializers, at compile time, into a new list of `GlobalInitializer` entries
16//! which are a sort of "global initializer". The generated `GlobalInitializer` is
17//! much more specific than the `LocalInitializer` and additionally far fewer
18//! `GlobalInitializer` structures are generated (in theory) than there are local
19//! initializers.
20//!
21//! The "inlining" portion of the name of this module indicates how the
22//! instantiation of a component is interpreted as calling a function. The
23//! function's arguments are the imports provided to the instantiation of a
24//! component, and further nested function calls happen on a stack when a
25//! nested component is instantiated. The inlining then refers to how this
26//! stack of instantiations is flattened to one list of `GlobalInitializer`
27//! entries to represent the process of instantiating a component graph,
28//! similar to how function inlining removes call instructions and creates one
29//! giant function for a call graph. Here there are no inlining heuristics or
30//! anything like that, we simply inline everything into the root component's
31//! list of initializers.
32//!
33//! Another primary task this module performs is a form of dataflow analysis
34//! to represent items in each index space with their definition rather than
35//! references of relative indices. These definitions (all the `*Def` types in
36//! this module) are not local to any one nested component and instead
37//! represent state available at runtime tracked in the final `Component`
38//! produced.
39//!
40//! With all this pieced together the general idea is relatively
41//! straightforward. All of a component's initializers are processed in sequence
42//! where instantiating a nested component pushes a "frame" onto a stack to
43//! start executing and we resume at the old one when we're done. Items are
44//! tracked where they come from and at the end after processing only the
45//! side-effectful initializers are emitted to the `GlobalInitializer` list in the
46//! final `Component`.
47
48use crate::component::translate::*;
49use crate::{EntityType, IndexType};
50use core::str::FromStr;
51use std::borrow::Cow;
52use wasmparser::component_types::{ComponentAnyTypeId, ComponentCoreModuleTypeId};
53
54pub(super) fn run(
55    types: &mut ComponentTypesBuilder,
56    result: &Translation<'_>,
57    nested_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
58    nested_components: &PrimaryMap<StaticComponentIndex, Translation<'_>>,
59) -> Result<dfg::ComponentDfg> {
60    let mut inliner = Inliner {
61        nested_modules,
62        nested_components,
63        result: Default::default(),
64        import_path_interner: Default::default(),
65        runtime_instances: PrimaryMap::default(),
66    };
67
68    let index = RuntimeComponentInstanceIndex::from_u32(0);
69
70    // The initial arguments to the root component are all host imports. This
71    // means that they're all using the `ComponentItemDef::Host` variant. Here
72    // an `ImportIndex` is allocated for each item and then the argument is
73    // recorded.
74    //
75    // Note that this is represents the abstract state of a host import of an
76    // item since we don't know the precise structure of the host import.
77    let mut args = HashMap::with_capacity(result.exports.len());
78    let mut path = Vec::new();
79    types.resources_mut().set_current_instance(index);
80    let types_ref = result.types_ref();
81    for init in result.initializers.iter() {
82        let (name, ty) = match *init {
83            LocalInitializer::Import(name, ty) => (name, ty),
84            _ => continue,
85        };
86
87        // Before `convert_component_entity_type` below all resource types
88        // introduced by this import need to be registered and have indexes
89        // assigned to them. Any fresh new resource type referred to by imports
90        // is a brand new introduction of a resource which needs to have a type
91        // allocated to it, so new runtime imports are injected for each
92        // resource along with updating the `imported_resources` map.
93        let index = inliner.result.import_types.next_key();
94        types.resources_mut().register_component_entity_type(
95            &types_ref,
96            ty,
97            &mut path,
98            &mut |path| {
99                let index = inliner.runtime_import(&ImportPath {
100                    index,
101                    path: path.iter().copied().map(Into::into).collect(),
102                });
103                inliner.result.imported_resources.push(index)
104            },
105        );
106
107        // With resources all taken care of it's now possible to convert this
108        // into Wasmtime's type system.
109        let ty = types.convert_component_entity_type(types_ref, ty)?;
110
111        // Imports of types that aren't resources are not required to be
112        // specified by the host since it's just for type information within
113        // the component.
114        if let TypeDef::Interface(_) = ty {
115            continue;
116        }
117        let index = inliner.result.import_types.push((name.0.to_string(), ty));
118        let path = ImportPath::root(index);
119        args.insert(name.0, ComponentItemDef::from_import(path, ty)?);
120    }
121
122    // This will run the inliner to completion after being seeded with the
123    // initial frame. When the inliner finishes it will return the exports of
124    // the root frame which are then used for recording the exports of the
125    // component.
126    inliner.result.num_runtime_component_instances += 1;
127    let frame = InlinerFrame::new(index, result, ComponentClosure::default(), args, None);
128    let resources_snapshot = types.resources_mut().clone();
129    let mut frames = vec![(frame, resources_snapshot)];
130    let exports = inliner.run(types, &mut frames)?;
131    assert!(frames.is_empty());
132
133    let mut export_map = Default::default();
134    for (name, def) in exports {
135        inliner.record_export(name, def, types, &mut export_map)?;
136    }
137    inliner.result.exports = export_map;
138    inliner.result.num_future_tables = types.num_future_tables();
139    inliner.result.num_stream_tables = types.num_stream_tables();
140    inliner.result.num_error_context_tables = types.num_error_context_tables();
141
142    Ok(inliner.result)
143}
144
145struct Inliner<'a> {
146    /// The list of static modules that were found during initial translation of
147    /// the component.
148    ///
149    /// This is used during the instantiation of these modules to ahead-of-time
150    /// order the arguments precisely according to what the module is defined as
151    /// needing which avoids the need to do string lookups or permute arguments
152    /// at runtime.
153    nested_modules: &'a PrimaryMap<StaticModuleIndex, ModuleTranslation<'a>>,
154
155    /// The list of static components that were found during initial translation of
156    /// the component.
157    ///
158    /// This is used when instantiating nested components to push a new
159    /// `InlinerFrame` with the `Translation`s here.
160    nested_components: &'a PrimaryMap<StaticComponentIndex, Translation<'a>>,
161
162    /// The final `Component` that is being constructed and returned from this
163    /// inliner.
164    result: dfg::ComponentDfg,
165
166    // Maps used to "intern" various runtime items to only save them once at
167    // runtime instead of multiple times.
168    import_path_interner: HashMap<ImportPath<'a>, RuntimeImportIndex>,
169
170    /// Origin information about where each runtime instance came from
171    runtime_instances: PrimaryMap<dfg::InstanceId, InstanceModule>,
172}
173
174/// A "stack frame" as part of the inlining process, or the progress through
175/// instantiating a component.
176///
177/// All instantiations of a component will create an `InlinerFrame` and are
178/// incrementally processed via the `initializers` list here. Note that the
179/// inliner frames are stored on the heap to avoid recursion based on user
180/// input.
181struct InlinerFrame<'a> {
182    instance: RuntimeComponentInstanceIndex,
183
184    /// The remaining initializers to process when instantiating this component.
185    initializers: std::slice::Iter<'a, LocalInitializer<'a>>,
186
187    /// The component being instantiated.
188    translation: &'a Translation<'a>,
189
190    /// The "closure arguments" to this component, or otherwise the maps indexed
191    /// by `ModuleUpvarIndex` and `ComponentUpvarIndex`. This is created when
192    /// a component is created and stored as part of a component's state during
193    /// inlining.
194    closure: ComponentClosure<'a>,
195
196    /// The arguments to the creation of this component.
197    ///
198    /// At the root level these are all imports from the host and between
199    /// components this otherwise tracks how all the arguments are defined.
200    args: HashMap<&'a str, ComponentItemDef<'a>>,
201
202    // core wasm index spaces
203    funcs: PrimaryMap<FuncIndex, (ModuleInternedTypeIndex, dfg::CoreDef)>,
204    memories: PrimaryMap<MemoryIndex, dfg::CoreExport<EntityIndex>>,
205    tables: PrimaryMap<TableIndex, dfg::CoreExport<EntityIndex>>,
206    globals: PrimaryMap<GlobalIndex, dfg::CoreExport<EntityIndex>>,
207    tags: PrimaryMap<TagIndex, dfg::CoreExport<EntityIndex>>,
208    modules: PrimaryMap<ModuleIndex, ModuleDef<'a>>,
209
210    // component model index spaces
211    component_funcs: PrimaryMap<ComponentFuncIndex, ComponentFuncDef<'a>>,
212    module_instances: PrimaryMap<ModuleInstanceIndex, ModuleInstanceDef<'a>>,
213    component_instances: PrimaryMap<ComponentInstanceIndex, ComponentInstanceDef<'a>>,
214    components: PrimaryMap<ComponentIndex, ComponentDef<'a>>,
215
216    /// The type of instance produced by completing the instantiation of this
217    /// frame.
218    ///
219    /// This is a wasmparser-relative piece of type information which is used to
220    /// register resource types after instantiation has completed.
221    ///
222    /// This is `Some` for all subcomponents and `None` for the root component.
223    instance_ty: Option<ComponentInstanceTypeId>,
224}
225
226/// "Closure state" for a component which is resolved from the `ClosedOverVars`
227/// state that was calculated during translation.
228//
229// FIXME: this is cloned quite a lot and given the internal maps if this is a
230// perf issue we may want to `Rc` these fields. Note that this is only a perf
231// hit at compile-time though which we in general don't pay too much
232// attention to.
233#[derive(Default, Clone)]
234struct ComponentClosure<'a> {
235    modules: PrimaryMap<ModuleUpvarIndex, ModuleDef<'a>>,
236    components: PrimaryMap<ComponentUpvarIndex, ComponentDef<'a>>,
237}
238
239/// Representation of a "path" into an import.
240///
241/// Imports from the host at this time are one of three things:
242///
243/// * Functions
244/// * Core wasm modules
245/// * "Instances" of these three items
246///
247/// The "base" values are functions and core wasm modules, but the abstraction
248/// of an instance allows embedding functions/modules deeply within other
249/// instances. This "path" represents optionally walking through a host instance
250/// to get to the final desired item. At runtime instances are just maps of
251/// values and so this is used to ensure that we primarily only deal with
252/// individual functions and modules instead of synthetic instances.
253#[derive(Clone, PartialEq, Hash, Eq)]
254struct ImportPath<'a> {
255    index: ImportIndex,
256    path: Vec<Cow<'a, str>>,
257}
258
259/// Representation of all items which can be defined within a component.
260///
261/// This is the "value" of an item defined within a component and is used to
262/// represent both imports and exports.
263#[derive(Clone)]
264enum ComponentItemDef<'a> {
265    Component(ComponentDef<'a>),
266    Instance(ComponentInstanceDef<'a>),
267    Func(ComponentFuncDef<'a>),
268    Module(ModuleDef<'a>),
269    Type(TypeDef),
270}
271
272#[derive(Clone)]
273enum ModuleDef<'a> {
274    /// A core wasm module statically defined within the original component.
275    ///
276    /// The `StaticModuleIndex` indexes into the `static_modules` map in the
277    /// `Inliner`.
278    Static(StaticModuleIndex, ComponentCoreModuleTypeId),
279
280    /// A core wasm module that was imported from the host.
281    Import(ImportPath<'a>, TypeModuleIndex),
282}
283
284// Note that unlike all other `*Def` types which are not allowed to have local
285// indices this type does indeed have local indices. That is represented with
286// the lack of a `Clone` here where once this is created it's never moved across
287// components because module instances always stick within one component.
288enum ModuleInstanceDef<'a> {
289    /// A core wasm module instance was created through the instantiation of a
290    /// module.
291    ///
292    /// The `RuntimeInstanceIndex` was the index allocated as this was the
293    /// `n`th instantiation and the `ModuleIndex` points into an
294    /// `InlinerFrame`'s local index space.
295    Instantiated(dfg::InstanceId, ModuleIndex),
296
297    /// A "synthetic" core wasm module which is just a bag of named indices.
298    ///
299    /// Note that this can really only be used for passing as an argument to
300    /// another module's instantiation and is used to rename arguments locally.
301    Synthetic(&'a HashMap<&'a str, EntityIndex>),
302}
303
304#[derive(Clone)]
305enum ComponentFuncDef<'a> {
306    /// A compile-time builtin intrinsic.
307    UnsafeIntrinsic(UnsafeIntrinsic),
308
309    /// A host-imported component function.
310    Import(ImportPath<'a>),
311
312    /// A core wasm function was lifted into a component function.
313    Lifted {
314        /// The component function type.
315        ty: TypeFuncIndex,
316        /// The core Wasm function.
317        func: dfg::CoreDef,
318        /// Canonical options.
319        options: AdapterOptions,
320    },
321}
322
323#[derive(Clone)]
324enum ComponentInstanceDef<'a> {
325    /// The `__wasmtime_intrinsics` instance that exports all of our
326    /// compile-time builtin intrinsics.
327    Intrinsics,
328
329    /// A host-imported instance.
330    ///
331    /// This typically means that it's "just" a map of named values. It's not
332    /// actually supported to take a `wasmtime::component::Instance` and pass it
333    /// to another instance at this time.
334    Import(ImportPath<'a>, TypeComponentInstanceIndex),
335
336    /// A concrete map of values.
337    ///
338    /// This is used for both instantiated components as well as "synthetic"
339    /// components. This variant can be used for both because both are
340    /// represented by simply a bag of items within the entire component
341    /// instantiation process.
342    //
343    // FIXME: same as the issue on `ComponentClosure` where this is cloned a lot
344    // and may need `Rc`.
345    Items(
346        IndexMap<&'a str, ComponentItemDef<'a>>,
347        TypeComponentInstanceIndex,
348    ),
349}
350
351#[derive(Clone)]
352struct ComponentDef<'a> {
353    index: StaticComponentIndex,
354    closure: ComponentClosure<'a>,
355}
356
357impl<'a> Inliner<'a> {
358    /// Symbolically instantiates a component using the type information and
359    /// `frames` provided.
360    ///
361    /// The `types` provided is the type information for the entire component
362    /// translation process. This is a distinct output artifact separate from
363    /// the component metadata.
364    ///
365    /// The `frames` argument is storage to handle a "call stack" of components
366    /// instantiating one another. The youngest frame (last element) of the
367    /// frames list is a component that's currently having its initializers
368    /// processed. The second element of each frame is a snapshot of the
369    /// resource-related information just before the frame was translated. For
370    /// more information on this snapshotting see the documentation on
371    /// `ResourcesBuilder`.
372    fn run(
373        &mut self,
374        types: &mut ComponentTypesBuilder,
375        frames: &mut Vec<(InlinerFrame<'a>, ResourcesBuilder)>,
376    ) -> Result<IndexMap<&'a str, ComponentItemDef<'a>>> {
377        // This loop represents the execution of the instantiation of a
378        // component. This is an iterative process which is finished once all
379        // initializers are processed. Currently this is modeled as an infinite
380        // loop which drives the top-most iterator of the `frames` stack
381        // provided as an argument to this function.
382        loop {
383            let (frame, _) = frames.last_mut().unwrap();
384            types.resources_mut().set_current_instance(frame.instance);
385            match frame.initializers.next() {
386                // Process the initializer and if it started the instantiation
387                // of another component then we push that frame on the stack to
388                // continue onwards.
389                Some(init) => match self.initializer(frame, types, init)? {
390                    Some(new_frame) => {
391                        frames.push((new_frame, types.resources_mut().clone()));
392                    }
393                    None => {}
394                },
395
396                // If there are no more initializers for this frame then the
397                // component it represents has finished instantiation. The
398                // exports of the component are collected and then the entire
399                // frame is discarded. The exports are then either pushed in the
400                // parent frame, if any, as a new component instance or they're
401                // returned from this function for the root set of exports.
402                None => {
403                    let exports = frame
404                        .translation
405                        .exports
406                        .iter()
407                        .map(|(name, item)| Ok((*name, frame.item(*item, types)?)))
408                        .collect::<Result<_>>()?;
409                    let instance_ty = frame.instance_ty;
410                    let (_, snapshot) = frames.pop().unwrap();
411                    *types.resources_mut() = snapshot;
412                    match frames.last_mut() {
413                        Some((parent, _)) => {
414                            parent.finish_instantiate(exports, instance_ty.unwrap(), types)?;
415                        }
416                        None => break Ok(exports),
417                    }
418                }
419            }
420        }
421    }
422
423    fn initializer(
424        &mut self,
425        frame: &mut InlinerFrame<'a>,
426        types: &mut ComponentTypesBuilder,
427        initializer: &'a LocalInitializer,
428    ) -> Result<Option<InlinerFrame<'a>>> {
429        use LocalInitializer::*;
430
431        match initializer {
432            // When a component imports an item the actual definition of the
433            // item is looked up here (not at runtime) via its name. The
434            // arguments provided in our `InlinerFrame` describe how each
435            // argument was defined, so we simply move it from there into the
436            // correct index space.
437            //
438            // Note that for the root component this will add `*::Import` items
439            // but for sub-components this will do resolution to connect what
440            // was provided as an import at the instantiation-site to what was
441            // needed during the component's instantiation.
442            Import(name, ty) => {
443                let arg = match frame.args.get(name.0) {
444                    Some(arg) => arg,
445
446                    // Not all arguments need to be provided for instantiation,
447                    // namely the root component in Wasmtime doesn't require
448                    // structural type imports to be satisfied. These type
449                    // imports are relevant for bindings generators and such but
450                    // as a runtime there's not really a definition to fit in.
451                    //
452                    // If no argument was provided for `name` then it's asserted
453                    // that this is a type import and additionally it's not a
454                    // resource type import (which indeed must be provided). If
455                    // all that passes then this initializer is effectively
456                    // skipped.
457                    None => {
458                        match ty {
459                            ComponentEntityType::Type {
460                                created: ComponentAnyTypeId::Resource(_),
461                                ..
462                            } => unreachable!(),
463                            ComponentEntityType::Type { .. } => {}
464                            _ => unreachable!(),
465                        }
466                        return Ok(None);
467                    }
468                };
469
470                // Next resource types need to be handled. For example if a
471                // resource is imported into this component then it needs to be
472                // assigned a unique table to provide the isolation guarantees
473                // of resources (this component's table is shared with no
474                // others). Here `register_component_entity_type` will find
475                // imported resources and then `lookup_resource` will find the
476                // resource within `arg` as necessary to lookup the original
477                // true definition of this resource.
478                //
479                // This is what enables tracking true resource origins
480                // throughout component translation while simultaneously also
481                // tracking unique tables for each resource in each component.
482                let mut path = Vec::new();
483                let (resources, types) = types.resources_mut_and_types();
484                resources.register_component_entity_type(
485                    &frame.translation.types_ref(),
486                    *ty,
487                    &mut path,
488                    &mut |path| arg.lookup_resource(path, types),
489                );
490
491                // And now with all the type information out of the way the
492                // `arg` definition is moved into its corresponding index space.
493                frame.push_item(arg.clone());
494            }
495
496            IntrinsicsImport => {
497                frame
498                    .component_instances
499                    .push(ComponentInstanceDef::Intrinsics);
500            }
501
502            // Lowering a component function to a core wasm function is
503            // generally what "triggers compilation". Here various metadata is
504            // recorded and then the final component gets an initializer
505            // recording the lowering.
506            //
507            // NB: at this time only lowered imported functions are supported.
508            Lower {
509                func,
510                options,
511                lower_ty,
512            } => {
513                let lower_ty =
514                    types.convert_component_func_type(frame.translation.types_ref(), *lower_ty)?;
515                let options_lower = self.adapter_options(frame, types, options);
516                let lower_core_type = options_lower.core_type;
517                let func = match &frame.component_funcs[*func] {
518                    // If this component function was originally a host import
519                    // then this is a lowered host function which needs a
520                    // trampoline to enter WebAssembly. That's recorded here
521                    // with all relevant information.
522                    ComponentFuncDef::Import(path) => {
523                        let import = self.runtime_import(path);
524                        let options = self.canonical_options(options_lower);
525                        let index = self.result.trampolines.push((
526                            lower_core_type,
527                            dfg::Trampoline::LowerImport {
528                                import,
529                                options,
530                                lower_ty,
531                            },
532                        ));
533                        dfg::CoreDef::Trampoline(index)
534                    }
535
536                    // This case handles when a lifted function is later
537                    // lowered, and both the lowering and the lifting are
538                    // happening within the same component instance.
539                    //
540                    // In this situation if the `canon.lower`'d function is
541                    // called then it immediately sets `may_enter` to `false`.
542                    // When calling the callee, however, that's `canon.lift`
543                    // which immediately traps if `may_enter` is `false`. That
544                    // means that this pairing of functions creates a function
545                    // that always traps.
546                    //
547                    // When closely reading the spec though the precise trap
548                    // that comes out can be somewhat variable. Technically the
549                    // function yielded here is one that should validate the
550                    // arguments by lifting them, and then trap. This means that
551                    // the trap could be different depending on whether all
552                    // arguments are valid for now. This was discussed in
553                    // WebAssembly/component-model#51 somewhat and the
554                    // conclusion was that we can probably get away with "always
555                    // trap" here.
556                    //
557                    // The `CoreDef::AlwaysTrap` variant here is used to
558                    // indicate that this function is valid but if something
559                    // actually calls it then it just generates a trap
560                    // immediately.
561                    ComponentFuncDef::Lifted {
562                        options: options_lift,
563                        ..
564                    } if options_lift.instance == options_lower.instance => {
565                        let index = self
566                            .result
567                            .trampolines
568                            .push((lower_core_type, dfg::Trampoline::AlwaysTrap));
569                        dfg::CoreDef::Trampoline(index)
570                    }
571
572                    // Lowering a lifted function where the destination
573                    // component is different than the source component means
574                    // that a "fused adapter" was just identified.
575                    //
576                    // Metadata about this fused adapter is recorded in the
577                    // `Adapters` output of this compilation pass. Currently the
578                    // implementation of fused adapters is to generate a core
579                    // wasm module which is instantiated with relevant imports
580                    // and the exports are used as the fused adapters. At this
581                    // time we don't know when precisely the instance will be
582                    // created but we do know that the result of this will be an
583                    // export from a previously-created instance.
584                    //
585                    // To model this the result of this arm is a
586                    // `CoreDef::Export`. The actual indices listed within the
587                    // export are "fake indices" in the sense of they're not
588                    // resolved yet. This resolution will happen at a later
589                    // compilation phase. Any usages of the `CoreDef::Export`
590                    // here will be detected and rewritten to an actual runtime
591                    // instance created.
592                    //
593                    // The `instance` field of the `CoreExport` has a marker
594                    // which indicates that it's a fused adapter. The `item` is
595                    // a function where the function index corresponds to the
596                    // `adapter_idx` which contains the metadata about this
597                    // adapter being created. The metadata is used to learn
598                    // about the dependencies and when the adapter module can
599                    // be instantiated.
600                    ComponentFuncDef::Lifted {
601                        ty: lift_ty,
602                        func,
603                        options: options_lift,
604                    } => {
605                        let adapter_idx = self.result.adapters.push(Adapter {
606                            lift_ty: *lift_ty,
607                            lift_options: options_lift.clone(),
608                            lower_ty,
609                            lower_options: options_lower,
610                            func: func.clone(),
611                        });
612                        dfg::CoreDef::Adapter(adapter_idx)
613                    }
614
615                    ComponentFuncDef::UnsafeIntrinsic(intrinsic) => {
616                        dfg::CoreDef::UnsafeIntrinsic(options.core_type, *intrinsic)
617                    }
618                };
619                frame.funcs.push((lower_core_type, func));
620            }
621
622            // Lifting a core wasm function is relatively easy for now in that
623            // some metadata about the lifting is simply recorded. This'll get
624            // plumbed through to exports or a fused adapter later on.
625            Lift(ty, func, options) => {
626                let ty = types.convert_component_func_type(frame.translation.types_ref(), *ty)?;
627                let options = self.adapter_options(frame, types, options);
628                let func = frame.funcs[*func].1.clone();
629                frame
630                    .component_funcs
631                    .push(ComponentFuncDef::Lifted { ty, func, options });
632            }
633
634            // A new resource type is being introduced, so it's recorded as a
635            // brand new resource in the final `resources` array. Additionally
636            // for now resource introductions are considered side effects to
637            // know when to register their destructors so that's recorded as
638            // well.
639            //
640            // Note that this has the effect of when a component is instantiated
641            // twice it will produce unique types for the resources from each
642            // instantiation. That's the intended runtime semantics and
643            // implementation here, however.
644            Resource(ty, rep, dtor) => {
645                let idx = self.result.resources.push(dfg::Resource {
646                    rep: *rep,
647                    dtor: dtor.map(|i| frame.funcs[i].1.clone()),
648                    instance: frame.instance,
649                });
650                self.result
651                    .side_effects
652                    .push(dfg::SideEffect::Resource(idx));
653
654                // Register with type translation that all future references to
655                // `ty` will refer to `idx`.
656                //
657                // Note that this registration information is lost when this
658                // component finishes instantiation due to the snapshotting
659                // behavior in the frame processing loop above. This is also
660                // intended, though, since `ty` can't be referred to outside of
661                // this component.
662                let idx = self.result.resource_index(idx);
663                types.resources_mut().register_resource(ty.resource(), idx);
664            }
665
666            // Resource-related intrinsics are generally all the same.
667            // Wasmparser type information is converted to wasmtime type
668            // information and then new entries for each intrinsic are recorded.
669            ResourceNew(id, ty) => {
670                let id = types.resource_id(id.resource());
671                let index = self.result.trampolines.push((
672                    *ty,
673                    dfg::Trampoline::ResourceNew {
674                        instance: frame.instance,
675                        ty: id,
676                    },
677                ));
678                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
679            }
680            ResourceRep(id, ty) => {
681                let id = types.resource_id(id.resource());
682                let index = self.result.trampolines.push((
683                    *ty,
684                    dfg::Trampoline::ResourceRep {
685                        instance: frame.instance,
686                        ty: id,
687                    },
688                ));
689                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
690            }
691            ResourceDrop(id, ty) => {
692                let id = types.resource_id(id.resource());
693                let index = self.result.trampolines.push((
694                    *ty,
695                    dfg::Trampoline::ResourceDrop {
696                        instance: frame.instance,
697                        ty: id,
698                    },
699                ));
700                frame.funcs.push((*ty, dfg::CoreDef::Trampoline(index)));
701            }
702            BackpressureSet { func } => {
703                let index = self.result.trampolines.push((
704                    *func,
705                    dfg::Trampoline::BackpressureSet {
706                        instance: frame.instance,
707                    },
708                ));
709                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
710            }
711            BackpressureInc { func } => {
712                let index = self.result.trampolines.push((
713                    *func,
714                    dfg::Trampoline::BackpressureInc {
715                        instance: frame.instance,
716                    },
717                ));
718                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
719            }
720            BackpressureDec { func } => {
721                let index = self.result.trampolines.push((
722                    *func,
723                    dfg::Trampoline::BackpressureDec {
724                        instance: frame.instance,
725                    },
726                ));
727                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
728            }
729            TaskReturn { result, options } => {
730                let results = result
731                    .iter()
732                    .map(|ty| types.valtype(frame.translation.types_ref(), ty))
733                    .collect::<Result<_>>()?;
734                let results = types.new_tuple_type(results);
735                let func = options.core_type;
736                let options = self.adapter_options(frame, types, options);
737                let options = self.canonical_options(options);
738                let index = self.result.trampolines.push((
739                    func,
740                    dfg::Trampoline::TaskReturn {
741                        instance: frame.instance,
742                        results,
743                        options,
744                    },
745                ));
746                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
747            }
748            TaskCancel { func } => {
749                let index = self.result.trampolines.push((
750                    *func,
751                    dfg::Trampoline::TaskCancel {
752                        instance: frame.instance,
753                    },
754                ));
755                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
756            }
757            WaitableSetNew { func } => {
758                let index = self.result.trampolines.push((
759                    *func,
760                    dfg::Trampoline::WaitableSetNew {
761                        instance: frame.instance,
762                    },
763                ));
764                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
765            }
766            WaitableSetWait { options } => {
767                let func = options.core_type;
768                let options = self.adapter_options(frame, types, options);
769                let options = self.canonical_options(options);
770                let index = self.result.trampolines.push((
771                    func,
772                    dfg::Trampoline::WaitableSetWait {
773                        instance: frame.instance,
774                        options,
775                    },
776                ));
777                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
778            }
779            WaitableSetPoll { options } => {
780                let func = options.core_type;
781                let options = self.adapter_options(frame, types, options);
782                let options = self.canonical_options(options);
783                let index = self.result.trampolines.push((
784                    func,
785                    dfg::Trampoline::WaitableSetPoll {
786                        instance: frame.instance,
787                        options,
788                    },
789                ));
790                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
791            }
792            WaitableSetDrop { func } => {
793                let index = self.result.trampolines.push((
794                    *func,
795                    dfg::Trampoline::WaitableSetDrop {
796                        instance: frame.instance,
797                    },
798                ));
799                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
800            }
801            WaitableJoin { func } => {
802                let index = self.result.trampolines.push((
803                    *func,
804                    dfg::Trampoline::WaitableJoin {
805                        instance: frame.instance,
806                    },
807                ));
808                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
809            }
810            ThreadYield { func, cancellable } => {
811                let index = self.result.trampolines.push((
812                    *func,
813                    dfg::Trampoline::ThreadYield {
814                        instance: frame.instance,
815                        cancellable: *cancellable,
816                    },
817                ));
818                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
819            }
820            SubtaskDrop { func } => {
821                let index = self.result.trampolines.push((
822                    *func,
823                    dfg::Trampoline::SubtaskDrop {
824                        instance: frame.instance,
825                    },
826                ));
827                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
828            }
829            SubtaskCancel { func, async_ } => {
830                let index = self.result.trampolines.push((
831                    *func,
832                    dfg::Trampoline::SubtaskCancel {
833                        instance: frame.instance,
834                        async_: *async_,
835                    },
836                ));
837                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
838            }
839            StreamNew { ty, func } => {
840                let InterfaceType::Stream(ty) =
841                    types.defined_type(frame.translation.types_ref(), *ty)?
842                else {
843                    unreachable!()
844                };
845                let index = self.result.trampolines.push((
846                    *func,
847                    dfg::Trampoline::StreamNew {
848                        instance: frame.instance,
849                        ty,
850                    },
851                ));
852                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
853            }
854            StreamRead { ty, options } => {
855                let InterfaceType::Stream(ty) =
856                    types.defined_type(frame.translation.types_ref(), *ty)?
857                else {
858                    unreachable!()
859                };
860                let func = options.core_type;
861                let options = self.adapter_options(frame, types, options);
862                let options = self.canonical_options(options);
863                let index = self.result.trampolines.push((
864                    func,
865                    dfg::Trampoline::StreamRead {
866                        instance: frame.instance,
867                        ty,
868                        options,
869                    },
870                ));
871                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
872            }
873            StreamWrite { ty, options } => {
874                let InterfaceType::Stream(ty) =
875                    types.defined_type(frame.translation.types_ref(), *ty)?
876                else {
877                    unreachable!()
878                };
879                let func = options.core_type;
880                let options = self.adapter_options(frame, types, options);
881                let options = self.canonical_options(options);
882                let index = self.result.trampolines.push((
883                    func,
884                    dfg::Trampoline::StreamWrite {
885                        instance: frame.instance,
886                        ty,
887                        options,
888                    },
889                ));
890                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
891            }
892            StreamCancelRead { ty, func, async_ } => {
893                let InterfaceType::Stream(ty) =
894                    types.defined_type(frame.translation.types_ref(), *ty)?
895                else {
896                    unreachable!()
897                };
898                let index = self.result.trampolines.push((
899                    *func,
900                    dfg::Trampoline::StreamCancelRead {
901                        instance: frame.instance,
902                        ty,
903                        async_: *async_,
904                    },
905                ));
906                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
907            }
908            StreamCancelWrite { ty, func, async_ } => {
909                let InterfaceType::Stream(ty) =
910                    types.defined_type(frame.translation.types_ref(), *ty)?
911                else {
912                    unreachable!()
913                };
914                let index = self.result.trampolines.push((
915                    *func,
916                    dfg::Trampoline::StreamCancelWrite {
917                        instance: frame.instance,
918                        ty,
919                        async_: *async_,
920                    },
921                ));
922                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
923            }
924            StreamDropReadable { ty, func } => {
925                let InterfaceType::Stream(ty) =
926                    types.defined_type(frame.translation.types_ref(), *ty)?
927                else {
928                    unreachable!()
929                };
930                let index = self.result.trampolines.push((
931                    *func,
932                    dfg::Trampoline::StreamDropReadable {
933                        instance: frame.instance,
934                        ty,
935                    },
936                ));
937                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
938            }
939            StreamDropWritable { ty, func } => {
940                let InterfaceType::Stream(ty) =
941                    types.defined_type(frame.translation.types_ref(), *ty)?
942                else {
943                    unreachable!()
944                };
945                let index = self.result.trampolines.push((
946                    *func,
947                    dfg::Trampoline::StreamDropWritable {
948                        instance: frame.instance,
949                        ty,
950                    },
951                ));
952                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
953            }
954            FutureNew { ty, func } => {
955                let InterfaceType::Future(ty) =
956                    types.defined_type(frame.translation.types_ref(), *ty)?
957                else {
958                    unreachable!()
959                };
960                let index = self.result.trampolines.push((
961                    *func,
962                    dfg::Trampoline::FutureNew {
963                        instance: frame.instance,
964                        ty,
965                    },
966                ));
967                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
968            }
969            FutureRead { ty, options } => {
970                let InterfaceType::Future(ty) =
971                    types.defined_type(frame.translation.types_ref(), *ty)?
972                else {
973                    unreachable!()
974                };
975                let func = options.core_type;
976                let options = self.adapter_options(frame, types, options);
977                let options = self.canonical_options(options);
978                let index = self.result.trampolines.push((
979                    func,
980                    dfg::Trampoline::FutureRead {
981                        instance: frame.instance,
982                        ty,
983                        options,
984                    },
985                ));
986                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
987            }
988            FutureWrite { ty, options } => {
989                let InterfaceType::Future(ty) =
990                    types.defined_type(frame.translation.types_ref(), *ty)?
991                else {
992                    unreachable!()
993                };
994                let func = options.core_type;
995                let options = self.adapter_options(frame, types, options);
996                let options = self.canonical_options(options);
997                let index = self.result.trampolines.push((
998                    func,
999                    dfg::Trampoline::FutureWrite {
1000                        instance: frame.instance,
1001                        ty,
1002                        options,
1003                    },
1004                ));
1005                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1006            }
1007            FutureCancelRead { ty, func, async_ } => {
1008                let InterfaceType::Future(ty) =
1009                    types.defined_type(frame.translation.types_ref(), *ty)?
1010                else {
1011                    unreachable!()
1012                };
1013                let index = self.result.trampolines.push((
1014                    *func,
1015                    dfg::Trampoline::FutureCancelRead {
1016                        instance: frame.instance,
1017                        ty,
1018                        async_: *async_,
1019                    },
1020                ));
1021                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1022            }
1023            FutureCancelWrite { ty, func, async_ } => {
1024                let InterfaceType::Future(ty) =
1025                    types.defined_type(frame.translation.types_ref(), *ty)?
1026                else {
1027                    unreachable!()
1028                };
1029                let index = self.result.trampolines.push((
1030                    *func,
1031                    dfg::Trampoline::FutureCancelWrite {
1032                        instance: frame.instance,
1033                        ty,
1034                        async_: *async_,
1035                    },
1036                ));
1037                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1038            }
1039            FutureDropReadable { ty, func } => {
1040                let InterfaceType::Future(ty) =
1041                    types.defined_type(frame.translation.types_ref(), *ty)?
1042                else {
1043                    unreachable!()
1044                };
1045                let index = self.result.trampolines.push((
1046                    *func,
1047                    dfg::Trampoline::FutureDropReadable {
1048                        instance: frame.instance,
1049                        ty,
1050                    },
1051                ));
1052                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1053            }
1054            FutureDropWritable { ty, func } => {
1055                let InterfaceType::Future(ty) =
1056                    types.defined_type(frame.translation.types_ref(), *ty)?
1057                else {
1058                    unreachable!()
1059                };
1060                let index = self.result.trampolines.push((
1061                    *func,
1062                    dfg::Trampoline::FutureDropWritable {
1063                        instance: frame.instance,
1064                        ty,
1065                    },
1066                ));
1067                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1068            }
1069            ErrorContextNew { options } => {
1070                let ty = types.error_context_table_type()?;
1071                let func = options.core_type;
1072                let options = self.adapter_options(frame, types, options);
1073                let options = self.canonical_options(options);
1074                let index = self.result.trampolines.push((
1075                    func,
1076                    dfg::Trampoline::ErrorContextNew {
1077                        instance: frame.instance,
1078                        ty,
1079                        options,
1080                    },
1081                ));
1082                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1083            }
1084            ErrorContextDebugMessage { options } => {
1085                let ty = types.error_context_table_type()?;
1086                let func = options.core_type;
1087                let options = self.adapter_options(frame, types, options);
1088                let options = self.canonical_options(options);
1089                let index = self.result.trampolines.push((
1090                    func,
1091                    dfg::Trampoline::ErrorContextDebugMessage {
1092                        instance: frame.instance,
1093                        ty,
1094                        options,
1095                    },
1096                ));
1097                frame.funcs.push((func, dfg::CoreDef::Trampoline(index)));
1098            }
1099            ErrorContextDrop { func } => {
1100                let ty = types.error_context_table_type()?;
1101                let index = self.result.trampolines.push((
1102                    *func,
1103                    dfg::Trampoline::ErrorContextDrop {
1104                        instance: frame.instance,
1105                        ty,
1106                    },
1107                ));
1108                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1109            }
1110            ContextGet { func, i } => {
1111                let index = self.result.trampolines.push((
1112                    *func,
1113                    dfg::Trampoline::ContextGet {
1114                        instance: frame.instance,
1115                        slot: *i,
1116                    },
1117                ));
1118                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1119            }
1120            ContextSet { func, i } => {
1121                let index = self.result.trampolines.push((
1122                    *func,
1123                    dfg::Trampoline::ContextSet {
1124                        instance: frame.instance,
1125                        slot: *i,
1126                    },
1127                ));
1128                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1129            }
1130            ThreadIndex { func } => {
1131                let index = self
1132                    .result
1133                    .trampolines
1134                    .push((*func, dfg::Trampoline::ThreadIndex));
1135                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1136            }
1137            ThreadNewIndirect {
1138                func,
1139                start_func_table_index,
1140                start_func_ty,
1141            } => {
1142                let table_export = frame.tables[*start_func_table_index]
1143                    .clone()
1144                    .map_index(|i| match i {
1145                        EntityIndex::Table(i) => i,
1146                        _ => unreachable!(),
1147                    });
1148
1149                let table_id = self.result.tables.push(table_export);
1150                let index = self.result.trampolines.push((
1151                    *func,
1152                    dfg::Trampoline::ThreadNewIndirect {
1153                        instance: frame.instance,
1154                        start_func_ty_idx: *start_func_ty,
1155                        start_func_table_id: table_id,
1156                    },
1157                ));
1158                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1159            }
1160            ThreadSwitchTo { func, cancellable } => {
1161                let index = self.result.trampolines.push((
1162                    *func,
1163                    dfg::Trampoline::ThreadSwitchTo {
1164                        instance: frame.instance,
1165                        cancellable: *cancellable,
1166                    },
1167                ));
1168                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1169            }
1170            ThreadSuspend { func, cancellable } => {
1171                let index = self.result.trampolines.push((
1172                    *func,
1173                    dfg::Trampoline::ThreadSuspend {
1174                        instance: frame.instance,
1175                        cancellable: *cancellable,
1176                    },
1177                ));
1178                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1179            }
1180            ThreadResumeLater { func } => {
1181                let index = self.result.trampolines.push((
1182                    *func,
1183                    dfg::Trampoline::ThreadResumeLater {
1184                        instance: frame.instance,
1185                    },
1186                ));
1187                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1188            }
1189            ThreadYieldTo { func, cancellable } => {
1190                let index = self.result.trampolines.push((
1191                    *func,
1192                    dfg::Trampoline::ThreadYieldTo {
1193                        instance: frame.instance,
1194                        cancellable: *cancellable,
1195                    },
1196                ));
1197                frame.funcs.push((*func, dfg::CoreDef::Trampoline(index)));
1198            }
1199            ModuleStatic(idx, ty) => {
1200                frame.modules.push(ModuleDef::Static(*idx, *ty));
1201            }
1202
1203            // Instantiation of a module is one of the meatier initializers that
1204            // we'll generate. The main magic here is that for a statically
1205            // known module we can order the imports as a list to exactly what
1206            // the static module needs to be instantiated. For imported modules,
1207            // however, the runtime string resolution must happen at runtime so
1208            // that is deferred here by organizing the arguments as a two-layer
1209            // `IndexMap` of what we're providing.
1210            //
1211            // In both cases though a new `RuntimeInstanceIndex` is allocated
1212            // and an initializer is recorded to indicate that it's being
1213            // instantiated.
1214            ModuleInstantiate(module, args) => {
1215                let (instance_module, init) = match &frame.modules[*module] {
1216                    ModuleDef::Static(idx, _ty) => {
1217                        let mut defs = Vec::new();
1218                        for (module, name, _ty) in self.nested_modules[*idx].module.imports() {
1219                            let instance = args[module];
1220                            defs.push(
1221                                self.core_def_of_module_instance_export(frame, instance, name),
1222                            );
1223                        }
1224                        (
1225                            InstanceModule::Static(*idx),
1226                            dfg::Instance::Static(*idx, defs.into()),
1227                        )
1228                    }
1229                    ModuleDef::Import(path, ty) => {
1230                        let mut defs = IndexMap::new();
1231                        for ((module, name), _) in types[*ty].imports.iter() {
1232                            let instance = args[module.as_str()];
1233                            let def =
1234                                self.core_def_of_module_instance_export(frame, instance, name);
1235                            defs.entry(module.to_string())
1236                                .or_insert(IndexMap::new())
1237                                .insert(name.to_string(), def);
1238                        }
1239                        let index = self.runtime_import(path);
1240                        (
1241                            InstanceModule::Import(*ty),
1242                            dfg::Instance::Import(index, defs),
1243                        )
1244                    }
1245                };
1246
1247                let instance = self.result.instances.push(init);
1248                let instance2 = self.runtime_instances.push(instance_module);
1249                assert_eq!(instance, instance2);
1250
1251                self.result
1252                    .side_effects
1253                    .push(dfg::SideEffect::Instance(instance));
1254
1255                frame
1256                    .module_instances
1257                    .push(ModuleInstanceDef::Instantiated(instance, *module));
1258            }
1259
1260            ModuleSynthetic(map) => {
1261                frame
1262                    .module_instances
1263                    .push(ModuleInstanceDef::Synthetic(map));
1264            }
1265
1266            // This is one of the stages of the "magic" of implementing outer
1267            // aliases to components and modules. For more information on this
1268            // see the documentation on `LexicalScope`. This stage of the
1269            // implementation of outer aliases is where the `ClosedOverVars` is
1270            // transformed into a `ComponentClosure` state using the current
1271            // `InlinerFrame`'s state. This will capture the "runtime" state of
1272            // outer components and upvars and such naturally as part of the
1273            // inlining process.
1274            ComponentStatic(index, vars) => {
1275                frame.components.push(ComponentDef {
1276                    index: *index,
1277                    closure: ComponentClosure {
1278                        modules: vars
1279                            .modules
1280                            .iter()
1281                            .map(|(_, m)| frame.closed_over_module(m))
1282                            .collect(),
1283                        components: vars
1284                            .components
1285                            .iter()
1286                            .map(|(_, m)| frame.closed_over_component(m))
1287                            .collect(),
1288                    },
1289                });
1290            }
1291
1292            // Like module instantiation is this is a "meaty" part, and don't be
1293            // fooled by the relative simplicity of this case. This is
1294            // implemented primarily by the `Inliner` structure and the design
1295            // of this entire module, so the "easy" step here is to simply
1296            // create a new inliner frame and return it to get pushed onto the
1297            // stack.
1298            ComponentInstantiate(component, args, ty) => {
1299                let component: &ComponentDef<'a> = &frame.components[*component];
1300                let index = RuntimeComponentInstanceIndex::from_u32(
1301                    self.result.num_runtime_component_instances,
1302                );
1303                self.result.num_runtime_component_instances += 1;
1304                let frame = InlinerFrame::new(
1305                    index,
1306                    &self.nested_components[component.index],
1307                    component.closure.clone(),
1308                    args.iter()
1309                        .map(|(name, item)| Ok((*name, frame.item(*item, types)?)))
1310                        .collect::<Result<_>>()?,
1311                    Some(*ty),
1312                );
1313                return Ok(Some(frame));
1314            }
1315
1316            ComponentSynthetic(map, ty) => {
1317                let items = map
1318                    .iter()
1319                    .map(|(name, index)| Ok((*name, frame.item(*index, types)?)))
1320                    .collect::<Result<_>>()?;
1321                let types_ref = frame.translation.types_ref();
1322                let ty = types.convert_instance(types_ref, *ty)?;
1323                frame
1324                    .component_instances
1325                    .push(ComponentInstanceDef::Items(items, ty));
1326            }
1327
1328            // Core wasm aliases, this and the cases below, are creating
1329            // `CoreExport` items primarily to insert into the index space so we
1330            // can create a unique identifier pointing to each core wasm export
1331            // with the instance and relevant index/name as necessary.
1332            AliasExportFunc(instance, name) => {
1333                let (ty, def) = match &frame.module_instances[*instance] {
1334                    ModuleInstanceDef::Instantiated(instance, module) => {
1335                        let (ty, item) = match &frame.modules[*module] {
1336                            ModuleDef::Static(idx, _ty) => {
1337                                let entity = self.nested_modules[*idx].module.exports[*name];
1338                                let ty = match entity {
1339                                    EntityIndex::Function(f) => {
1340                                        self.nested_modules[*idx].module.functions[f]
1341                                            .signature
1342                                            .unwrap_module_type_index()
1343                                    }
1344                                    _ => unreachable!(),
1345                                };
1346                                (ty, ExportItem::Index(entity))
1347                            }
1348                            ModuleDef::Import(_path, module_ty) => {
1349                                let module_ty = &types.component_types()[*module_ty];
1350                                let entity_ty = &module_ty.exports[&**name];
1351                                let ty = entity_ty.unwrap_func().unwrap_module_type_index();
1352                                (ty, ExportItem::Name((*name).to_string()))
1353                            }
1354                        };
1355                        let def = dfg::CoreExport {
1356                            instance: *instance,
1357                            item,
1358                        }
1359                        .into();
1360                        (ty, def)
1361                    }
1362                    ModuleInstanceDef::Synthetic(instance) => match instance[*name] {
1363                        EntityIndex::Function(i) => frame.funcs[i].clone(),
1364                        _ => unreachable!(),
1365                    },
1366                };
1367                frame.funcs.push((ty, def));
1368            }
1369
1370            AliasExportTable(instance, name) => {
1371                frame.tables.push(
1372                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1373                        dfg::CoreDef::Export(e) => e,
1374                        _ => unreachable!(),
1375                    },
1376                );
1377            }
1378
1379            AliasExportGlobal(instance, name) => {
1380                frame.globals.push(
1381                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1382                        dfg::CoreDef::Export(e) => e,
1383                        _ => unreachable!(),
1384                    },
1385                );
1386            }
1387
1388            AliasExportMemory(instance, name) => {
1389                frame.memories.push(
1390                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1391                        dfg::CoreDef::Export(e) => e,
1392                        _ => unreachable!(),
1393                    },
1394                );
1395            }
1396
1397            AliasExportTag(instance, name) => {
1398                frame.tags.push(
1399                    match self.core_def_of_module_instance_export(frame, *instance, *name) {
1400                        dfg::CoreDef::Export(e) => e,
1401                        _ => unreachable!(),
1402                    },
1403                );
1404            }
1405
1406            AliasComponentExport(instance, name) => {
1407                match &frame.component_instances[*instance] {
1408                    ComponentInstanceDef::Intrinsics => {
1409                        frame.push_item(ComponentItemDef::Func(ComponentFuncDef::UnsafeIntrinsic(
1410                            UnsafeIntrinsic::from_str(name)?,
1411                        )));
1412                    }
1413
1414                    // Aliasing an export from an imported instance means that
1415                    // we're extending the `ImportPath` by one name, represented
1416                    // with the clone + push here. Afterwards an appropriate
1417                    // item is then pushed in the relevant index space.
1418                    ComponentInstanceDef::Import(path, ty) => {
1419                        let path = path.push(*name);
1420                        let def = ComponentItemDef::from_import(path, types[*ty].exports[*name])?;
1421                        frame.push_item(def);
1422                    }
1423
1424                    // Given a component instance which was either created
1425                    // through instantiation of a component or through a
1426                    // synthetic renaming of items we just schlep around the
1427                    // definitions of various items here.
1428                    ComponentInstanceDef::Items(map, _) => frame.push_item(map[*name].clone()),
1429                }
1430            }
1431
1432            // For more information on these see `LexicalScope` but otherwise
1433            // this is just taking a closed over variable and inserting the
1434            // actual definition into the local index space since this
1435            // represents an outer alias to a module/component
1436            AliasModule(idx) => {
1437                frame.modules.push(frame.closed_over_module(idx));
1438            }
1439            AliasComponent(idx) => {
1440                frame.components.push(frame.closed_over_component(idx));
1441            }
1442
1443            Export(item) => match item {
1444                ComponentItem::Func(i) => {
1445                    frame
1446                        .component_funcs
1447                        .push(frame.component_funcs[*i].clone());
1448                }
1449                ComponentItem::Module(i) => {
1450                    frame.modules.push(frame.modules[*i].clone());
1451                }
1452                ComponentItem::Component(i) => {
1453                    frame.components.push(frame.components[*i].clone());
1454                }
1455                ComponentItem::ComponentInstance(i) => {
1456                    frame
1457                        .component_instances
1458                        .push(frame.component_instances[*i].clone());
1459                }
1460
1461                // Type index spaces aren't maintained during this inlining pass
1462                // so ignore this.
1463                ComponentItem::Type(_) => {}
1464            },
1465        }
1466
1467        Ok(None)
1468    }
1469
1470    /// "Commits" a path of an import to an actual index which is something that
1471    /// will be calculated at runtime.
1472    ///
1473    /// Note that the cost of calculating an item for a `RuntimeImportIndex` at
1474    /// runtime is amortized with an `InstancePre` which represents "all the
1475    /// runtime imports are lined up" and after that no more name resolution is
1476    /// necessary.
1477    fn runtime_import(&mut self, path: &ImportPath<'a>) -> RuntimeImportIndex {
1478        *self
1479            .import_path_interner
1480            .entry(path.clone())
1481            .or_insert_with(|| {
1482                self.result.imports.push((
1483                    path.index,
1484                    path.path.iter().map(|s| s.to_string()).collect(),
1485                ))
1486            })
1487    }
1488
1489    /// Returns the `CoreDef`, the canonical definition for a core wasm item,
1490    /// for the export `name` of `instance` within `frame`.
1491    fn core_def_of_module_instance_export(
1492        &self,
1493        frame: &InlinerFrame<'a>,
1494        instance: ModuleInstanceIndex,
1495        name: &'a str,
1496    ) -> dfg::CoreDef {
1497        match &frame.module_instances[instance] {
1498            // Instantiations of a statically known module means that we can
1499            // refer to the exported item by a precise index, skipping name
1500            // lookups at runtime.
1501            //
1502            // Instantiations of an imported module, however, must do name
1503            // lookups at runtime since we don't know the structure ahead of
1504            // time here.
1505            ModuleInstanceDef::Instantiated(instance, module) => {
1506                let item = match frame.modules[*module] {
1507                    ModuleDef::Static(idx, _ty) => {
1508                        let entity = self.nested_modules[idx].module.exports[name];
1509                        ExportItem::Index(entity)
1510                    }
1511                    ModuleDef::Import(..) => ExportItem::Name(name.to_string()),
1512                };
1513                dfg::CoreExport {
1514                    instance: *instance,
1515                    item,
1516                }
1517                .into()
1518            }
1519
1520            // This is a synthetic instance so the canonical definition of the
1521            // original item is returned.
1522            ModuleInstanceDef::Synthetic(instance) => match instance[name] {
1523                EntityIndex::Function(i) => frame.funcs[i].1.clone(),
1524                EntityIndex::Table(i) => frame.tables[i].clone().into(),
1525                EntityIndex::Global(i) => frame.globals[i].clone().into(),
1526                EntityIndex::Memory(i) => frame.memories[i].clone().into(),
1527                EntityIndex::Tag(i) => frame.tags[i].clone().into(),
1528            },
1529        }
1530    }
1531
1532    fn memory(
1533        &mut self,
1534        frame: &InlinerFrame<'a>,
1535        types: &ComponentTypesBuilder,
1536        memory: MemoryIndex,
1537    ) -> (dfg::CoreExport<MemoryIndex>, bool) {
1538        let memory = frame.memories[memory].clone().map_index(|i| match i {
1539            EntityIndex::Memory(i) => i,
1540            _ => unreachable!(),
1541        });
1542        let memory64 = match &self.runtime_instances[memory.instance] {
1543            InstanceModule::Static(idx) => match &memory.item {
1544                ExportItem::Index(i) => {
1545                    let ty = &self.nested_modules[*idx].module.memories[*i];
1546                    match ty.idx_type {
1547                        IndexType::I32 => false,
1548                        IndexType::I64 => true,
1549                    }
1550                }
1551                ExportItem::Name(_) => unreachable!(),
1552            },
1553            InstanceModule::Import(ty) => match &memory.item {
1554                ExportItem::Name(name) => match types[*ty].exports[name] {
1555                    EntityType::Memory(m) => match m.idx_type {
1556                        IndexType::I32 => false,
1557                        IndexType::I64 => true,
1558                    },
1559                    _ => unreachable!(),
1560                },
1561                ExportItem::Index(_) => unreachable!(),
1562            },
1563        };
1564        (memory, memory64)
1565    }
1566
1567    /// Translates a `LocalCanonicalOptions` which indexes into the `frame`
1568    /// specified into a runtime representation.
1569    fn adapter_options(
1570        &mut self,
1571        frame: &InlinerFrame<'a>,
1572        types: &ComponentTypesBuilder,
1573        options: &LocalCanonicalOptions,
1574    ) -> AdapterOptions {
1575        let data_model = match options.data_model {
1576            LocalDataModel::Gc {} => DataModel::Gc {},
1577            LocalDataModel::LinearMemory { memory, realloc } => {
1578                let (memory, memory64) = memory
1579                    .map(|i| {
1580                        let (memory, memory64) = self.memory(frame, types, i);
1581                        (Some(memory), memory64)
1582                    })
1583                    .unwrap_or((None, false));
1584                let realloc = realloc.map(|i| frame.funcs[i].1.clone());
1585                DataModel::LinearMemory {
1586                    memory,
1587                    memory64,
1588                    realloc,
1589                }
1590            }
1591        };
1592        let callback = options.callback.map(|i| frame.funcs[i].1.clone());
1593        let post_return = options.post_return.map(|i| frame.funcs[i].1.clone());
1594        AdapterOptions {
1595            instance: frame.instance,
1596            string_encoding: options.string_encoding,
1597            callback,
1598            post_return,
1599            async_: options.async_,
1600            cancellable: options.cancellable,
1601            core_type: options.core_type,
1602            data_model,
1603        }
1604    }
1605
1606    /// Translatees an `AdapterOptions` into a `CanonicalOptions` where
1607    /// memories/functions are inserted into the global initializer list for
1608    /// use at runtime. This is only used for lowered host functions and lifted
1609    /// functions exported to the host.
1610    fn canonical_options(&mut self, options: AdapterOptions) -> dfg::OptionsId {
1611        let data_model = match options.data_model {
1612            DataModel::Gc {} => dfg::CanonicalOptionsDataModel::Gc {},
1613            DataModel::LinearMemory {
1614                memory,
1615                memory64: _,
1616                realloc,
1617            } => dfg::CanonicalOptionsDataModel::LinearMemory {
1618                memory: memory.map(|export| self.result.memories.push(export)),
1619                realloc: realloc.map(|def| self.result.reallocs.push(def)),
1620            },
1621        };
1622        let callback = options.callback.map(|def| self.result.callbacks.push(def));
1623        let post_return = options
1624            .post_return
1625            .map(|def| self.result.post_returns.push(def));
1626        self.result.options.push(dfg::CanonicalOptions {
1627            instance: options.instance,
1628            string_encoding: options.string_encoding,
1629            callback,
1630            post_return,
1631            async_: options.async_,
1632            cancellable: options.cancellable,
1633            core_type: options.core_type,
1634            data_model,
1635        })
1636    }
1637
1638    fn record_export(
1639        &mut self,
1640        name: &str,
1641        def: ComponentItemDef<'a>,
1642        types: &'a ComponentTypesBuilder,
1643        map: &mut IndexMap<String, dfg::Export>,
1644    ) -> Result<()> {
1645        let export = match def {
1646            // Exported modules are currently saved in a `PrimaryMap`, at
1647            // runtime, so an index (`RuntimeModuleIndex`) is assigned here and
1648            // then an initializer is recorded about where the module comes
1649            // from.
1650            ComponentItemDef::Module(module) => match module {
1651                ModuleDef::Static(index, ty) => dfg::Export::ModuleStatic { ty, index },
1652                ModuleDef::Import(path, ty) => dfg::Export::ModuleImport {
1653                    ty,
1654                    import: self.runtime_import(&path),
1655                },
1656            },
1657
1658            ComponentItemDef::Func(func) => match func {
1659                // If this is a lifted function from something lowered in this
1660                // component then the configured options are plumbed through
1661                // here.
1662                ComponentFuncDef::Lifted { ty, func, options } => {
1663                    let options = self.canonical_options(options);
1664                    dfg::Export::LiftedFunction { ty, func, options }
1665                }
1666
1667                // Currently reexported functions from an import are not
1668                // supported. Being able to actually call these functions is
1669                // somewhat tricky and needs something like temporary scratch
1670                // space that isn't implemented.
1671                ComponentFuncDef::Import(_) => {
1672                    bail!(
1673                        "component export `{name}` is a reexport of an imported function which is not implemented"
1674                    )
1675                }
1676
1677                ComponentFuncDef::UnsafeIntrinsic(_) => {
1678                    bail!(
1679                        "component export `{name}` is a reexport of an intrinsic function which is not supported"
1680                    )
1681                }
1682            },
1683
1684            ComponentItemDef::Instance(instance) => {
1685                let mut exports = IndexMap::new();
1686                match instance {
1687                    ComponentInstanceDef::Intrinsics => {
1688                        bail!(
1689                            "component export `{name}` is a reexport of the intrinsics instance which is not supported"
1690                        )
1691                    }
1692
1693                    // If this instance is one that was originally imported by
1694                    // the component itself then the imports are translated here
1695                    // by converting to a `ComponentItemDef` and then
1696                    // recursively recording the export as a reexport.
1697                    //
1698                    // Note that for now this would only work with
1699                    // module-exporting instances.
1700                    ComponentInstanceDef::Import(path, ty) => {
1701                        for (name, ty) in types[ty].exports.iter() {
1702                            let path = path.push(name);
1703                            let def = ComponentItemDef::from_import(path, *ty)?;
1704                            self.record_export(name, def, types, &mut exports)?;
1705                        }
1706                        dfg::Export::Instance { ty, exports }
1707                    }
1708
1709                    // An exported instance which is itself a bag of items is
1710                    // translated recursively here to our `exports` map which is
1711                    // the bag of items we're exporting.
1712                    ComponentInstanceDef::Items(map, ty) => {
1713                        for (name, def) in map {
1714                            self.record_export(name, def, types, &mut exports)?;
1715                        }
1716                        dfg::Export::Instance { ty, exports }
1717                    }
1718                }
1719            }
1720
1721            // FIXME(#4283) should make an official decision on whether this is
1722            // the final treatment of this or not.
1723            ComponentItemDef::Component(_) => {
1724                bail!("exporting a component from the root component is not supported")
1725            }
1726
1727            ComponentItemDef::Type(def) => dfg::Export::Type(def),
1728        };
1729
1730        map.insert(name.to_string(), export);
1731        Ok(())
1732    }
1733}
1734
1735impl<'a> InlinerFrame<'a> {
1736    fn new(
1737        instance: RuntimeComponentInstanceIndex,
1738        translation: &'a Translation<'a>,
1739        closure: ComponentClosure<'a>,
1740        args: HashMap<&'a str, ComponentItemDef<'a>>,
1741        instance_ty: Option<ComponentInstanceTypeId>,
1742    ) -> Self {
1743        // FIXME: should iterate over the initializers of `translation` and
1744        // calculate the size of each index space to use `with_capacity` for
1745        // all the maps below. Given that doing such would be wordy and compile
1746        // time is otherwise not super crucial it's not done at this time.
1747        InlinerFrame {
1748            instance,
1749            translation,
1750            closure,
1751            args,
1752            instance_ty,
1753            initializers: translation.initializers.iter(),
1754
1755            funcs: Default::default(),
1756            memories: Default::default(),
1757            tables: Default::default(),
1758            globals: Default::default(),
1759            tags: Default::default(),
1760
1761            component_instances: Default::default(),
1762            component_funcs: Default::default(),
1763            module_instances: Default::default(),
1764            components: Default::default(),
1765            modules: Default::default(),
1766        }
1767    }
1768
1769    fn item(
1770        &self,
1771        index: ComponentItem,
1772        types: &mut ComponentTypesBuilder,
1773    ) -> Result<ComponentItemDef<'a>> {
1774        Ok(match index {
1775            ComponentItem::Func(i) => ComponentItemDef::Func(self.component_funcs[i].clone()),
1776            ComponentItem::Component(i) => ComponentItemDef::Component(self.components[i].clone()),
1777            ComponentItem::ComponentInstance(i) => {
1778                ComponentItemDef::Instance(self.component_instances[i].clone())
1779            }
1780            ComponentItem::Module(i) => ComponentItemDef::Module(self.modules[i].clone()),
1781            ComponentItem::Type(t) => {
1782                let types_ref = self.translation.types_ref();
1783                ComponentItemDef::Type(types.convert_type(types_ref, t)?)
1784            }
1785        })
1786    }
1787
1788    /// Pushes the component `item` definition provided into the appropriate
1789    /// index space within this component.
1790    fn push_item(&mut self, item: ComponentItemDef<'a>) {
1791        match item {
1792            ComponentItemDef::Func(i) => {
1793                self.component_funcs.push(i);
1794            }
1795            ComponentItemDef::Module(i) => {
1796                self.modules.push(i);
1797            }
1798            ComponentItemDef::Component(i) => {
1799                self.components.push(i);
1800            }
1801            ComponentItemDef::Instance(i) => {
1802                self.component_instances.push(i);
1803            }
1804
1805            // In short, type definitions aren't tracked here.
1806            //
1807            // The longer form explanation for this is that structural types
1808            // like lists and records don't need to be tracked at all and the
1809            // only significant type which needs tracking is resource types
1810            // themselves. Resource types, however, are tracked within the
1811            // `ResourcesBuilder` state rather than an `InlinerFrame` so they're
1812            // ignored here as well. The general reason for that is that type
1813            // information is everywhere and this `InlinerFrame` is not
1814            // everywhere so it seemed like it would make sense to split the
1815            // two.
1816            //
1817            // Note though that this case is actually frequently hit, so it
1818            // can't be `unreachable!()`. Instead callers are responsible for
1819            // handling this appropriately with respect to resources.
1820            ComponentItemDef::Type(_ty) => {}
1821        }
1822    }
1823
1824    fn closed_over_module(&self, index: &ClosedOverModule) -> ModuleDef<'a> {
1825        match *index {
1826            ClosedOverModule::Local(i) => self.modules[i].clone(),
1827            ClosedOverModule::Upvar(i) => self.closure.modules[i].clone(),
1828        }
1829    }
1830
1831    fn closed_over_component(&self, index: &ClosedOverComponent) -> ComponentDef<'a> {
1832        match *index {
1833            ClosedOverComponent::Local(i) => self.components[i].clone(),
1834            ClosedOverComponent::Upvar(i) => self.closure.components[i].clone(),
1835        }
1836    }
1837
1838    /// Completes the instantiation of a subcomponent and records type
1839    /// information for the instance that was produced.
1840    ///
1841    /// This method is invoked when an `InlinerFrame` finishes for a
1842    /// subcomponent. The `def` provided represents the instance that was
1843    /// produced from instantiation, and `ty` is the wasmparser-defined type of
1844    /// the instance produced.
1845    ///
1846    /// The purpose of this method is to record type information about resources
1847    /// in the instance produced. In the component model all instantiations of a
1848    /// component produce fresh new types for all resources which are unequal to
1849    /// all prior resources. This means that if wasmparser's `ty` type
1850    /// information references a unique resource within `def` that has never
1851    /// been registered before then that means it's a defined resource within
1852    /// the component that was just instantiated (as opposed to an imported
1853    /// resource which was reexported).
1854    ///
1855    /// Further type translation after this instantiation can refer to these
1856    /// resource types and a mapping from those types to the wasmtime-internal
1857    /// types is required, so this method builds up those mappings.
1858    ///
1859    /// Essentially what happens here is that the `ty` type is registered and
1860    /// any new unique resources are registered so new tables can be introduced
1861    /// along with origin information about the actual underlying resource type
1862    /// and which component instantiated it.
1863    fn finish_instantiate(
1864        &mut self,
1865        exports: IndexMap<&'a str, ComponentItemDef<'a>>,
1866        ty: ComponentInstanceTypeId,
1867        types: &mut ComponentTypesBuilder,
1868    ) -> Result<()> {
1869        let types_ref = self.translation.types_ref();
1870        {
1871            let (resources, types) = types.resources_mut_and_types();
1872            let mut path = Vec::new();
1873            resources.register_component_entity_type(
1874                &types_ref,
1875                ComponentEntityType::Instance(ty),
1876                &mut path,
1877                &mut |path| match path {
1878                    [] => unreachable!(),
1879                    [name, rest @ ..] => exports[name].lookup_resource(rest, types),
1880                },
1881            );
1882        }
1883        let ty = types.convert_instance(types_ref, ty)?;
1884        let def = ComponentInstanceDef::Items(exports, ty);
1885        let arg = ComponentItemDef::Instance(def);
1886        self.push_item(arg);
1887        Ok(())
1888    }
1889}
1890
1891impl<'a> ImportPath<'a> {
1892    fn root(index: ImportIndex) -> ImportPath<'a> {
1893        ImportPath {
1894            index,
1895            path: Vec::new(),
1896        }
1897    }
1898
1899    fn push(&self, s: impl Into<Cow<'a, str>>) -> ImportPath<'a> {
1900        let mut new = self.clone();
1901        new.path.push(s.into());
1902        new
1903    }
1904}
1905
1906impl<'a> ComponentItemDef<'a> {
1907    fn from_import(path: ImportPath<'a>, ty: TypeDef) -> Result<ComponentItemDef<'a>> {
1908        let item = match ty {
1909            TypeDef::Module(ty) => ComponentItemDef::Module(ModuleDef::Import(path, ty)),
1910            TypeDef::ComponentInstance(ty) => {
1911                ComponentItemDef::Instance(ComponentInstanceDef::Import(path, ty))
1912            }
1913            TypeDef::ComponentFunc(_ty) => ComponentItemDef::Func(ComponentFuncDef::Import(path)),
1914            // FIXME(#4283) should commit one way or another to how this
1915            // should be treated.
1916            TypeDef::Component(_ty) => bail!("root-level component imports are not supported"),
1917            TypeDef::Interface(_) | TypeDef::Resource(_) => ComponentItemDef::Type(ty),
1918            TypeDef::CoreFunc(_) => unreachable!(),
1919        };
1920        Ok(item)
1921    }
1922
1923    /// Walks the `path` within `self` to find a resource at that path.
1924    ///
1925    /// This method is used when resources are found within wasmparser's type
1926    /// information and they need to be correlated with actual concrete
1927    /// definitions from this inlining pass. The `path` here is a list of
1928    /// instance export names (or empty) to walk to reach down into the final
1929    /// definition which should refer to a resource itself.
1930    fn lookup_resource(&self, path: &[&str], types: &ComponentTypes) -> ResourceIndex {
1931        let mut cur = self.clone();
1932
1933        // Each element of `path` represents unwrapping a layer of an instance
1934        // type, so handle those here by updating `cur` iteratively.
1935        for element in path.iter().copied() {
1936            let instance = match cur {
1937                ComponentItemDef::Instance(def) => def,
1938                _ => unreachable!(),
1939            };
1940            cur = match instance {
1941                // If this instance is a "bag of things" then this is as easy as
1942                // looking up the name in the bag of names.
1943                ComponentInstanceDef::Items(names, _) => names[element].clone(),
1944
1945                // If, however, this instance is an imported instance then this
1946                // is a further projection within the import with one more path
1947                // element. The `types` type information is used to lookup the
1948                // type of `element` within the instance type, and that's used
1949                // in conjunction with a one-longer `path` to produce a new item
1950                // definition.
1951                ComponentInstanceDef::Import(path, ty) => {
1952                    ComponentItemDef::from_import(path.push(element), types[ty].exports[element])
1953                        .unwrap()
1954                }
1955                ComponentInstanceDef::Intrinsics => {
1956                    unreachable!("intrinsics do not define resources")
1957                }
1958            };
1959        }
1960
1961        // Once `path` has been iterated over it must be the case that the final
1962        // item is a resource type, in which case a lookup can be performed.
1963        match cur {
1964            ComponentItemDef::Type(TypeDef::Resource(idx)) => types[idx].unwrap_concrete_ty(),
1965            _ => unreachable!(),
1966        }
1967    }
1968}
1969
1970#[derive(Clone, Copy)]
1971enum InstanceModule {
1972    Static(StaticModuleIndex),
1973    Import(TypeModuleIndex),
1974}