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