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