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