Skip to main content

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