Skip to main content

wasmtime_environ/component/
translate.rs

1use crate::Abi;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6    DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, EngineOrModuleTypeIndex,
7    EntityIndex, FactInlineIntrinsic, FuncKey, KnownEntity, KnownGlobal, ModuleEnvironment,
8    ModuleInternedTypeIndex, ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex,
9    Tunables, TypeConvert, WasmHeapType, WasmResult, WasmValType,
10};
11use core::str::FromStr;
12use cranelift_entity::{EntityRef, SecondaryMap};
13use indexmap::IndexMap;
14use std::collections::{HashMap, HashSet};
15use std::mem;
16use wasmparser::component_types::{
17    AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
18    ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
19};
20use wasmparser::types::Types;
21use wasmparser::{Chunk, ComponentExternName, Encoding, Parser, Payload, Validator};
22
23mod adapt;
24pub use self::adapt::*;
25mod inline;
26
27/// Structure used to translate a component and parse it.
28pub struct Translator<'a, 'data> {
29    /// The current component being translated.
30    ///
31    /// This will get swapped out as translation traverses the body of a
32    /// component and a sub-component is entered or left.
33    result: Translation<'data>,
34
35    /// Current state of parsing a binary component. Note that like `result`
36    /// this will change as the component is traversed.
37    parser: Parser,
38
39    /// Stack of lexical scopes that are in-progress but not finished yet.
40    ///
41    /// This is pushed to whenever a component is entered and popped from
42    /// whenever a component is left. Each lexical scope also contains
43    /// information about the variables that it is currently required to close
44    /// over which is threaded into the current in-progress translation of
45    /// the sub-component which pushed a scope here.
46    lexical_scopes: Vec<LexicalScope<'data>>,
47
48    /// The validator in use to verify that the raw input binary is a valid
49    /// component.
50    validator: &'a mut Validator,
51
52    /// Type information shared for the entire component.
53    ///
54    /// This builder is also used for all core wasm modules found to intern
55    /// signatures across all modules.
56    types: PreInliningComponentTypes<'a>,
57
58    /// The compiler configuration provided by the embedder.
59    tunables: &'a Tunables,
60
61    /// Auxiliary location to push generated adapter modules onto.
62    scope_vec: &'data ScopeVec<u8>,
63
64    /// Completely translated core wasm modules that have been found so far.
65    ///
66    /// Note that this translation only involves learning about type
67    /// information and functions are not actually compiled here.
68    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
69
70    /// Completely translated components that have been found so far.
71    ///
72    /// As frames are popped from `lexical_scopes` their completed component
73    /// will be pushed onto this list.
74    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
75
76    /// The top-level import name for Wasmtime's unsafe intrinsics, if any.
77    unsafe_intrinsics_import: Option<&'a str>,
78}
79
80/// Representation of the syntactic scope of a component meaning where it is
81/// and what its state is at in the binary format.
82///
83/// These scopes are pushed and popped when a sub-component starts being
84/// parsed and finishes being parsed. The main purpose of this frame is to
85/// have a `ClosedOverVars` field which encapsulates data that is inherited
86/// from the scope specified into the component being translated just beneath
87/// it.
88///
89/// This structure exists to implement outer aliases to components and modules.
90/// When a component or module is closed over then that means it needs to be
91/// inherited in a sense to the component which actually had the alias. This is
92/// achieved with a deceptively simple scheme where each parent of the
93/// component with the alias will inherit the component from the desired
94/// location.
95///
96/// For example with a component structure that looks like:
97///
98/// ```wasm
99/// (component $A
100///     (core module $M)
101///     (component $B
102///         (component $C
103///             (alias outer $A $M (core module))
104///         )
105///     )
106/// )
107/// ```
108///
109/// here the `C` component is closing over `M` located in the root component
110/// `A`. When `C` is being translated the `lexical_scopes` field will look like
111/// `[A, B]`. When the alias is encountered (for module index 0) this will
112/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
113/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
114/// inserted into `closure_args` in `B`'s frame. This produces yet another
115/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
116/// via `LocalInitializer::AliasModuleUpvar` with the last index.
117///
118/// All of these upvar indices and such are interpreted in the "inline" phase
119/// of compilation and not at runtime. This means that when `A` is being
120/// instantiated one of its initializers will be
121/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
122/// variables captured for `B` are listed as local module 0, or `M`. This list
123/// is then preserved in the definition of the component `B` and later reused
124/// by `C` again to finally get access to the closed over component.
125///
126/// Effectively the scopes are managed hierarchically where a reference to an
127/// outer variable automatically injects references into all parents up to
128/// where the reference is. This variable scopes are the processed during
129/// inlining where a component definition is a reference to the static
130/// component information (`Translation`) plus closed over variables
131/// (`ComponentClosure` during inlining).
132struct LexicalScope<'data> {
133    /// Current state of translating the `translation` below.
134    parser: Parser,
135    /// Current state of the component's translation as found so far.
136    translation: Translation<'data>,
137    /// List of captures that `translation` will need to process to create the
138    /// sub-component which is directly beneath this lexical scope.
139    closure_args: ClosedOverVars,
140}
141
142/// A "local" translation of a component.
143///
144/// This structure is used as a sort of in-progress translation of a component.
145/// This is not `Component` which is the final form as consumed by Wasmtime
146/// at runtime. Instead this is a fairly simple representation of a component
147/// where almost everything is ordered as a list of initializers. The binary
148/// format is translated to a list of initializers here which is later processed
149/// during "inlining" to produce a final component with the final set of
150/// initializers.
151#[derive(Default)]
152struct Translation<'data> {
153    /// Instructions which form this component.
154    ///
155    /// There is one initializer for all members of each index space, and all
156    /// index spaces are incrementally built here as the initializer list is
157    /// processed.
158    initializers: Vec<LocalInitializer<'data>>,
159
160    /// The list of exports from this component, as pairs of names and an
161    /// index into an index space of what's being exported.
162    exports: IndexMap<&'data str, (ComponentItem, wasmparser::ComponentExternName<'data>)>,
163
164    /// Type information produced by `wasmparser` for this component.
165    ///
166    /// This type information is available after the translation of the entire
167    /// component has finished, e.g. for the `inline` pass, but beforehand this
168    /// is set to `None`.
169    types: Option<Types>,
170}
171
172// NB: the type information contained in `LocalInitializer` should always point
173// to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
174// fully determined due to resources until instantiations are known which is
175// tracked during the inlining phase. This means that all type information below
176// is straight from `wasmparser`'s passes.
177enum LocalInitializer<'data> {
178    // imports
179    Import(ComponentExternName<'data>, ComponentEntityType),
180
181    // An import of an intrinsic for compile-time builtins.
182    IntrinsicsImport,
183
184    // canonical function sections
185    Lower {
186        func: ComponentFuncIndex,
187        lower_ty: ComponentFuncTypeId,
188        options: LocalCanonicalOptions,
189    },
190    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
191
192    // resources
193    Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
194    ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
195    ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
196    ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
197
198    BackpressureInc {
199        func: ModuleInternedTypeIndex,
200    },
201    BackpressureDec {
202        func: ModuleInternedTypeIndex,
203    },
204    TaskReturn {
205        result: Option<ComponentValType>,
206        options: LocalCanonicalOptions,
207    },
208    TaskCancel {
209        func: ModuleInternedTypeIndex,
210    },
211    WaitableSetNew {
212        func: ModuleInternedTypeIndex,
213    },
214    WaitableSetWait {
215        options: LocalCanonicalOptions,
216    },
217    WaitableSetPoll {
218        options: LocalCanonicalOptions,
219    },
220    WaitableSetDrop {
221        func: ModuleInternedTypeIndex,
222    },
223    WaitableJoin {
224        func: ModuleInternedTypeIndex,
225    },
226    SubtaskDrop {
227        func: ModuleInternedTypeIndex,
228    },
229    SubtaskCancel {
230        func: ModuleInternedTypeIndex,
231        async_: bool,
232    },
233    StreamNew {
234        ty: ComponentDefinedTypeId,
235        func: ModuleInternedTypeIndex,
236    },
237    StreamRead {
238        ty: ComponentDefinedTypeId,
239        options: LocalCanonicalOptions,
240    },
241    StreamWrite {
242        ty: ComponentDefinedTypeId,
243        options: LocalCanonicalOptions,
244    },
245    StreamCancelRead {
246        ty: ComponentDefinedTypeId,
247        func: ModuleInternedTypeIndex,
248        async_: bool,
249    },
250    StreamCancelWrite {
251        ty: ComponentDefinedTypeId,
252        func: ModuleInternedTypeIndex,
253        async_: bool,
254    },
255    StreamDropReadable {
256        ty: ComponentDefinedTypeId,
257        func: ModuleInternedTypeIndex,
258    },
259    StreamDropWritable {
260        ty: ComponentDefinedTypeId,
261        func: ModuleInternedTypeIndex,
262    },
263    FutureNew {
264        ty: ComponentDefinedTypeId,
265        func: ModuleInternedTypeIndex,
266    },
267    FutureRead {
268        ty: ComponentDefinedTypeId,
269        options: LocalCanonicalOptions,
270    },
271    FutureWrite {
272        ty: ComponentDefinedTypeId,
273        options: LocalCanonicalOptions,
274    },
275    FutureCancelRead {
276        ty: ComponentDefinedTypeId,
277        func: ModuleInternedTypeIndex,
278        async_: bool,
279    },
280    FutureCancelWrite {
281        ty: ComponentDefinedTypeId,
282        func: ModuleInternedTypeIndex,
283        async_: bool,
284    },
285    FutureDropReadable {
286        ty: ComponentDefinedTypeId,
287        func: ModuleInternedTypeIndex,
288    },
289    FutureDropWritable {
290        ty: ComponentDefinedTypeId,
291        func: ModuleInternedTypeIndex,
292    },
293    ErrorContextNew {
294        options: LocalCanonicalOptions,
295    },
296    ErrorContextDebugMessage {
297        options: LocalCanonicalOptions,
298    },
299    ErrorContextDrop {
300        func: ModuleInternedTypeIndex,
301    },
302    ContextGet {
303        func: ModuleInternedTypeIndex,
304        i: u32,
305    },
306    ContextSet {
307        func: ModuleInternedTypeIndex,
308        i: u32,
309    },
310    ThreadIndex {
311        func: ModuleInternedTypeIndex,
312    },
313    ThreadNewIndirect {
314        func: ModuleInternedTypeIndex,
315        start_func_ty: ComponentTypeIndex,
316        start_func_table_index: TableIndex,
317    },
318    ThreadResumeLater {
319        func: ModuleInternedTypeIndex,
320    },
321    ThreadSuspend {
322        func: ModuleInternedTypeIndex,
323        cancellable: bool,
324    },
325    ThreadYield {
326        func: ModuleInternedTypeIndex,
327        cancellable: bool,
328    },
329    ThreadSuspendThenResume {
330        func: ModuleInternedTypeIndex,
331        cancellable: bool,
332    },
333    ThreadYieldThenResume {
334        func: ModuleInternedTypeIndex,
335        cancellable: bool,
336    },
337    ThreadSuspendThenPromote {
338        func: ModuleInternedTypeIndex,
339        cancellable: bool,
340    },
341    ThreadYieldThenPromote {
342        func: ModuleInternedTypeIndex,
343        cancellable: bool,
344    },
345
346    // core wasm modules
347    ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
348
349    // core wasm module instances
350    ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
351    ModuleSynthetic(HashMap<&'data str, EntityIndex>),
352
353    // components
354    ComponentStatic(StaticComponentIndex, ClosedOverVars),
355
356    // component instances
357    ComponentInstantiate(
358        ComponentIndex,
359        HashMap<&'data str, ComponentItem>,
360        ComponentInstanceTypeId,
361    ),
362    ComponentSynthetic(
363        HashMap<&'data str, (ComponentItem, wasmparser::ComponentExternName<'data>)>,
364        ComponentInstanceTypeId,
365    ),
366
367    // alias section
368    AliasExportFunc(ModuleInstanceIndex, &'data str),
369    AliasExportTable(ModuleInstanceIndex, &'data str),
370    AliasExportGlobal(ModuleInstanceIndex, &'data str),
371    AliasExportMemory(ModuleInstanceIndex, &'data str),
372    AliasExportTag(ModuleInstanceIndex, &'data str),
373    AliasComponentExport(ComponentInstanceIndex, &'data str),
374    AliasModule(ClosedOverModule),
375    AliasComponent(ClosedOverComponent),
376
377    // export section
378    Export(ComponentItem),
379}
380
381/// The "closure environment" of components themselves.
382///
383/// For more information see `LexicalScope`.
384#[derive(Default)]
385struct ClosedOverVars {
386    components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
387    modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
388}
389
390/// Description how a component is closed over when the closure variables for
391/// a component are being created.
392///
393/// For more information see `LexicalScope`.
394enum ClosedOverComponent {
395    /// A closed over component is coming from the local component's index
396    /// space, meaning a previously defined component is being captured.
397    Local(ComponentIndex),
398    /// A closed over component is coming from our own component's list of
399    /// upvars. This list was passed to us by our enclosing component, which
400    /// will eventually have bottomed out in closing over a `Local` component
401    /// index for some parent component.
402    Upvar(ComponentUpvarIndex),
403}
404
405/// Same as `ClosedOverComponent`, but for modules.
406enum ClosedOverModule {
407    Local(ModuleIndex),
408    Upvar(ModuleUpvarIndex),
409}
410
411/// The data model for objects that are not unboxed in locals.
412#[derive(Debug, Clone, Hash, Eq, PartialEq)]
413pub enum LocalDataModel {
414    /// Data is stored in GC objects.
415    Gc {},
416
417    /// Data is stored in a linear memory.
418    LinearMemory {
419        /// An optional memory definition supplied.
420        memory: Option<MemoryIndex>,
421        /// An optional definition of `realloc` to used.
422        realloc: Option<FuncIndex>,
423    },
424}
425
426/// Representation of canonical ABI options.
427struct LocalCanonicalOptions {
428    string_encoding: StringEncoding,
429    post_return: Option<FuncIndex>,
430    async_: bool,
431    cancellable: bool,
432    callback: Option<FuncIndex>,
433    /// The type index of the core GC types signature.
434    core_type: ModuleInternedTypeIndex,
435    data_model: LocalDataModel,
436}
437
438enum Action {
439    KeepGoing,
440    Skip(usize),
441    Done,
442}
443
444impl<'a, 'data> Translator<'a, 'data> {
445    /// Creates a new translation state ready to translate a component.
446    pub fn new(
447        tunables: &'a Tunables,
448        validator: &'a mut Validator,
449        types: &'a mut ComponentTypesBuilder,
450        scope_vec: &'data ScopeVec<u8>,
451    ) -> Self {
452        let mut parser = Parser::new(0);
453        parser.set_features(*validator.features());
454        Self {
455            result: Translation::default(),
456            tunables,
457            validator,
458            types: PreInliningComponentTypes::new(types),
459            parser,
460            lexical_scopes: Vec::new(),
461            static_components: Default::default(),
462            static_modules: Default::default(),
463            scope_vec,
464            unsafe_intrinsics_import: None,
465        }
466    }
467
468    /// Expose Wasmtime's unsafe intrinsics under the given top-level import
469    /// name.
470    pub fn expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self {
471        assert!(self.unsafe_intrinsics_import.is_none());
472        self.unsafe_intrinsics_import = Some(name);
473        self
474    }
475
476    /// Translates the binary `component`.
477    ///
478    /// This is the workhorse of compilation which will parse all of
479    /// `component` and create type information for Wasmtime and such. The
480    /// `component` does not have to be valid and it will be validated during
481    /// compilation.
482    ///
483    /// The result of this function is a tuple of the final component's
484    /// description plus a list of core wasm modules found within the
485    /// component. The component's description actually erases internal
486    /// components, instances, etc, as much as it can. Instead `Component`
487    /// retains a flat list of initializers (no nesting) which was created
488    /// as part of compilation from the nested structure of the original
489    /// component.
490    ///
491    /// The list of core wasm modules found is provided to allow compiling
492    /// modules externally in parallel. Additionally initializers in
493    /// `Component` may refer to the modules in the map returned by index.
494    ///
495    /// # Errors
496    ///
497    /// This function will return an error if the `component` provided is
498    /// invalid.
499    pub fn translate(
500        mut self,
501        component: &'data [u8],
502    ) -> Result<(
503        ComponentTranslation,
504        PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
505    )> {
506        // First up wasmparser is used to actually perform the translation and
507        // validation of this component. This will produce a list of core wasm
508        // modules in addition to components which are found during the
509        // translation process. When doing this only a `Translation` is created
510        // which is a simple representation of a component.
511        let mut remaining = component;
512        loop {
513            let payload = match self.parser.parse(remaining, true)? {
514                Chunk::Parsed { payload, consumed } => {
515                    remaining = &remaining[consumed..];
516                    payload
517                }
518                Chunk::NeedMoreData(_) => unreachable!(),
519            };
520
521            match self.translate_payload(payload, component)? {
522                Action::KeepGoing => {}
523                Action::Skip(n) => remaining = &remaining[n..],
524                Action::Done => break,
525            }
526        }
527        assert!(remaining.is_empty());
528        assert!(self.lexical_scopes.is_empty());
529
530        // ... after translation initially finishes the next pass is performed
531        // which we're calling "inlining". This will "instantiate" the root
532        // component, following nested component instantiations, creating a
533        // global list of initializers along the way. This phase uses the simple
534        // initializers in each component to track dataflow of host imports and
535        // internal references to items throughout a component at compile-time.
536        // The produce initializers in the final `Component` are intended to be
537        // much simpler than the original component and more efficient for
538        // Wasmtime to process at runtime as well (e.g. no string lookups as
539        // most everything is done through indices instead).
540        let mut component = inline::run(
541            self.types.types_mut_for_inlining(),
542            &self.result,
543            &self.static_modules,
544            &self.static_components,
545        )?;
546
547        self.partition_adapter_modules(&mut component);
548
549        let translation =
550            component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
551
552        self.analyze_imports(&translation);
553
554        Ok((translation, self.static_modules))
555    }
556
557    /// Record everything we statically know about each module's imports.
558    ///
559    /// See `ModuleTranslation::known_imported_functions` and
560    /// `ModuleTranslation::known_imported_globals` for how we can optimize
561    /// lowering based on this information.
562    fn analyze_imports(&mut self, translation: &ComponentTranslation) {
563        // First, abstract interpret the initializers to create a map from each
564        // static module to its abstract set of instantiations.
565        let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
566        let mut instances = StaticInstances::new();
567        for init in &translation.component.initializers {
568            match init {
569                GlobalInitializer::InstantiateModule(instantiation, _) => match instantiation {
570                    InstantiateModule::Static(module, args) => {
571                        instantiations[*module].join(AbstractInstantiations::One(&*args));
572                        instances.push(Some((*module, &args[..])));
573                    }
574                    _ => {
575                        instances.push(None);
576                    }
577                },
578                _ => continue,
579            }
580        }
581
582        // Second, make sure to mark exported modules as instantiated many
583        // times, since they could be linked with who-knows-what at runtime.
584        for item in translation.component.export_items.values() {
585            if let Export::ModuleStatic { index, .. } = item {
586                instantiations[*index].join(AbstractInstantiations::Many)
587            }
588        }
589
590        // Third, find the globals, memories, and tables whose identity is not
591        // statically known to everything that can access them. Note that this
592        // is a property of the whole component and not of a single module's
593        // instantiations; see `ModuleTranslation::known_imported_globals` for
594        // details.
595        let ambiguous = ambiguous_entities(
596            &self.static_modules,
597            translation,
598            &instantiations,
599            &instances,
600        );
601
602        // Fourth, record which of each module's own defined entities all of
603        // their importers agree on, which lets those modules use a precise alias
604        // region for them even when they are exported.
605        for (module, translation) in self.static_modules.iter_mut() {
606            for i in 0..translation.module.num_defined_globals() {
607                let index = DefinedGlobalIndex::new(i);
608                let global = translation.module.global_index(index);
609                if !ambiguous
610                    .entities
611                    .contains(&(module, EntityIndex::Global(global)))
612                {
613                    translation.globals_known_to_importers.insert(index);
614                }
615            }
616            for i in 0..translation.module.num_defined_memories() {
617                let index = DefinedMemoryIndex::new(i);
618                let memory = translation.module.memory_index(index);
619                if !ambiguous
620                    .entities
621                    .contains(&(module, EntityIndex::Memory(memory)))
622                {
623                    translation.memories_known_to_importers.insert(index);
624                }
625            }
626            for i in 0..translation.module.num_defined_tables() {
627                let index = DefinedTableIndex::new(i);
628                let table = translation.module.table_index(index);
629                if !ambiguous
630                    .entities
631                    .contains(&(module, EntityIndex::Table(table)))
632                {
633                    translation.tables_known_to_importers.insert(index);
634                }
635            }
636        }
637
638        // Finally, iterate over our instantiations and record statically-known
639        // imports: function imports so that they can get translated into direct
640        // calls (and eventually get inlined) rather than indirect calls through
641        // the imports table; and global, memory, and table imports so that they
642        // can get precise alias regions instead of the conservative regions
643        // shared by everything that crosses a module boundary.
644        for (module, instantiations) in instantiations.iter() {
645            let args = match instantiations {
646                dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
647                dfg::AbstractInstantiations::One(args) => args,
648            };
649
650            for (i, arg) in args.iter().enumerate() {
651                // Record that this global, memory, or table import is always the
652                // same defined entity, when we know that and when everything
653                // else that imports that entity knows it too.
654                macro_rules! record_known_entity {
655                    ($variant:ident, $imported:expr, $defined_index:ident, $known:ident, $wrap:expr) => {{
656                        let Some((arg_module, EntityIndex::$variant(arg_entity))) =
657                            unambiguous_entity(
658                                &self.static_modules,
659                                &instances,
660                                &ambiguous.entities,
661                                arg,
662                            )
663                        else {
664                            continue;
665                        };
666                        let index = self.static_modules[arg_module]
667                            .module
668                            .$defined_index(arg_entity)
669                            .expect(
670                                "`resolve_core_export` only returns entities that their module \
671                                 defines",
672                            );
673                        assert!(self.static_modules[module].$known[$imported].is_none());
674                        self.static_modules[module].$known[$imported] = Some($wrap(KnownEntity {
675                            module: arg_module,
676                            index,
677                        }));
678                    }};
679                }
680
681                match self.static_modules[module].module.import_index(i).unwrap() {
682                    EntityIndex::Function(imported_func) => {
683                        debug_assert!(
684                            self.static_modules[module]
685                                .module
686                                .defined_func_index(imported_func)
687                                .is_none()
688                        );
689
690                        let known_func = match arg {
691                            CoreDef::InstanceFlags(_) => {
692                                unreachable!("instance flags are not a function")
693                            }
694
695                            // We could in theory inline these trampolines, so it
696                            // could potentially make sense to record that we
697                            // know this imported function is this particular
698                            // trampoline. However, everything else is based
699                            // around (module, defined-function) pairs and these
700                            // trampolines don't fit that paradigm. Also,
701                            // inlining trampolines gets really tricky when we
702                            // consider the stack pointer, frame pointer, and
703                            // return address note-taking that they do for the
704                            // purposes of stack walking. We could, with enough
705                            // effort, turn them into direct calls even though we
706                            // probably wouldn't ever inline them, but it just
707                            // doesn't seem worth the effort.
708                            //
709                            // That said, a couple of adapter trampolines are
710                            // lowered inline during translation. We record these
711                            // here so `FuncEnvironment` recognizes them. All
712                            // other trampolines remain indirect calls.
713                            CoreDef::Trampoline(index) => match translation.trampolines[*index] {
714                                Trampoline::EnterSyncCall => {
715                                    FactInlineIntrinsic::EnterSyncCall.into()
716                                }
717                                Trampoline::ExitSyncCall => {
718                                    FactInlineIntrinsic::ExitSyncCall.into()
719                                }
720                                Trampoline::Trap(trap) => FactInlineIntrinsic::Trap(trap).into(),
721                                _ => continue,
722                            },
723
724                            // This import is a compile-time builtin intrinsic,
725                            // we should inline its implementation during
726                            // function translation.
727                            CoreDef::UnsafeIntrinsic(i) => {
728                                FuncKey::UnsafeIntrinsic(Abi::Wasm, *i).into()
729                            }
730
731                            // This imported function is an export from another
732                            // instance, a perfect candidate for becoming an
733                            // inlinable direct call!
734                            CoreDef::Export(export) => {
735                                let Some((arg_module, arg_entity)) =
736                                    resolve_core_export(&self.static_modules, &instances, export)
737                                else {
738                                    // Either an instance of a dynamic module that
739                                    // is not part of this component, or a
740                                    // re-export chain that bottoms out in
741                                    // something that isn't a defined function
742                                    // (for example a re-export of a trampoline;
743                                    // note that we only match trampolines and
744                                    // intrinsics as *direct* arguments above).
745                                    // Either way we have to do an indirect call.
746                                    continue;
747                                };
748
749                                let EntityIndex::Function(arg_func) = arg_entity else {
750                                    unreachable!("function imports must be functions")
751                                };
752
753                                let arg_module_def_func = self.static_modules[arg_module]
754                                    .module
755                                    .defined_func_index(arg_func)
756                                    .expect(
757                                        "`resolve_core_export` only returns entities that their \
758                                         module defines",
759                                    );
760
761                                FuncKey::DefinedWasmFunction(arg_module, arg_module_def_func).into()
762                            }
763                        };
764
765                        assert!(
766                            self.static_modules[module].known_imported_functions[imported_func]
767                                .is_none()
768                        );
769                        self.static_modules[module].known_imported_functions[imported_func] =
770                            Some(known_func);
771                    }
772
773                    // Note that a global import is not necessarily satisfied by a
774                    // wasm global: it can also be one of the component-model
775                    // flags that live in the `VMComponentContext`, and those get
776                    // their own alias regions rather than a defined-global one.
777                    EntityIndex::Global(imported_global) => match component_flags(arg) {
778                        Some(flags) => {
779                            if ambiguous.flags.contains(&flags) {
780                                continue;
781                            }
782                            assert!(
783                                self.static_modules[module].known_imported_globals[imported_global]
784                                    .is_none()
785                            );
786                            self.static_modules[module].known_imported_globals[imported_global] =
787                                Some(flags);
788                        }
789                        None => record_known_entity!(
790                            Global,
791                            imported_global,
792                            defined_global_index,
793                            known_imported_globals,
794                            KnownGlobal::Defined
795                        ),
796                    },
797
798                    EntityIndex::Memory(imported_memory) => record_known_entity!(
799                        Memory,
800                        imported_memory,
801                        defined_memory_index,
802                        known_imported_memories,
803                        core::convert::identity
804                    ),
805
806                    EntityIndex::Table(imported_table) => record_known_entity!(
807                        Table,
808                        imported_table,
809                        defined_table_index,
810                        known_imported_tables,
811                        core::convert::identity
812                    ),
813
814                    // Tags don't have alias regions of their own.
815                    EntityIndex::Tag(_) => {}
816                }
817            }
818        }
819    }
820
821    fn translate_payload(
822        &mut self,
823        payload: Payload<'data>,
824        component: &'data [u8],
825    ) -> Result<Action> {
826        match payload {
827            Payload::Version {
828                num,
829                encoding,
830                range,
831            } => {
832                self.validator.version(num, encoding, &range)?;
833
834                match encoding {
835                    Encoding::Component => {}
836                    Encoding::Module => {
837                        bail!("attempted to parse a wasm module with a component parser");
838                    }
839                }
840            }
841
842            Payload::End(offset) => {
843                assert!(self.result.types.is_none());
844                self.result.types = Some(self.validator.end(offset)?);
845
846                // Exit the current lexical scope. If there is no parent (no
847                // frame currently on the stack) then translation is finished.
848                // Otherwise that means that a nested component has been
849                // completed and is recorded as such.
850                let LexicalScope {
851                    parser,
852                    translation,
853                    closure_args,
854                } = match self.lexical_scopes.pop() {
855                    Some(frame) => frame,
856                    None => return Ok(Action::Done),
857                };
858                self.parser = parser;
859                let component = mem::replace(&mut self.result, translation);
860                let static_idx = self.static_components.push(component);
861                self.result
862                    .initializers
863                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
864            }
865
866            // When we see a type section the types are validated and then
867            // translated into Wasmtime's representation. Each active type
868            // definition is recorded in the `ComponentTypesBuilder` tables, or
869            // this component's active scope.
870            //
871            // Note that the push/pop of the component types scope happens above
872            // in `Version` and `End` since multiple type sections can appear
873            // within a component.
874            Payload::ComponentTypeSection(s) => {
875                let mut component_type_index =
876                    self.validator.types(0).unwrap().component_type_count();
877                self.validator.component_type_section(&s)?;
878
879                // Look for resource types and if a local resource is defined
880                // then an initializer is added to define that resource type and
881                // reference its destructor.
882                let types = self.validator.types(0).unwrap();
883                for ty in s {
884                    match ty? {
885                        wasmparser::ComponentType::Resource { rep, dtor } => {
886                            let rep = self.types.convert_valtype(rep)?;
887                            let id = types
888                                .component_any_type_at(component_type_index)
889                                .unwrap_resource();
890                            let dtor = dtor.map(FuncIndex::from_u32);
891                            self.result
892                                .initializers
893                                .push(LocalInitializer::Resource(id, rep, dtor));
894                        }
895
896                        // no extra processing needed
897                        wasmparser::ComponentType::Defined(_)
898                        | wasmparser::ComponentType::Func(_)
899                        | wasmparser::ComponentType::Instance(_)
900                        | wasmparser::ComponentType::Component(_) => {}
901                    }
902
903                    component_type_index += 1;
904                }
905            }
906            Payload::CoreTypeSection(s) => {
907                self.validator.core_type_section(&s)?;
908            }
909
910            // Processing the import section at this point is relatively simple
911            // which is to simply record the name of the import and the type
912            // information associated with it.
913            Payload::ComponentImportSection(s) => {
914                self.validator.component_import_section(&s)?;
915                for import in s {
916                    let import = import?;
917                    let types = self.validator.types(0).unwrap();
918                    let ty = types
919                        .component_item_for_import(import.name.name)
920                        .unwrap()
921                        .ty;
922
923                    if self.is_unsafe_intrinsics_import(import.name.name) {
924                        self.check_unsafe_intrinsics_import(import.name.name, ty)?;
925                        self.result
926                            .initializers
927                            .push(LocalInitializer::IntrinsicsImport);
928                    } else {
929                        self.result
930                            .initializers
931                            .push(LocalInitializer::Import(import.name, ty));
932                    }
933                }
934            }
935
936            // Entries in the canonical section will get initializers recorded
937            // with the listed options for lifting/lowering.
938            Payload::ComponentCanonicalSection(s) => {
939                let types = self.validator.types(0).unwrap();
940                let mut core_func_index = types.function_count();
941                self.validator.component_canonical_section(&s)?;
942                for func in s {
943                    let init = match func? {
944                        wasmparser::CanonicalFunction::Lift {
945                            type_index,
946                            core_func_index,
947                            options,
948                        } => {
949                            let ty = self
950                                .validator
951                                .types(0)
952                                .unwrap()
953                                .component_any_type_at(type_index)
954                                .unwrap_func();
955
956                            let func = FuncIndex::from_u32(core_func_index);
957                            let options = self.canonical_options(&options, core_func_index)?;
958                            LocalInitializer::Lift(ty, func, options)
959                        }
960                        wasmparser::CanonicalFunction::Lower {
961                            func_index,
962                            options,
963                        } => {
964                            let lower_ty = self
965                                .validator
966                                .types(0)
967                                .unwrap()
968                                .component_function_at(func_index);
969                            let func = ComponentFuncIndex::from_u32(func_index);
970                            let options = self.canonical_options(&options, core_func_index)?;
971                            core_func_index += 1;
972                            LocalInitializer::Lower {
973                                func,
974                                options,
975                                lower_ty,
976                            }
977                        }
978                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
979                            let resource = self
980                                .validator
981                                .types(0)
982                                .unwrap()
983                                .component_any_type_at(resource)
984                                .unwrap_resource();
985                            let ty = self.core_func_signature(core_func_index)?;
986                            core_func_index += 1;
987                            LocalInitializer::ResourceNew(resource, ty)
988                        }
989                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
990                            let resource = self
991                                .validator
992                                .types(0)
993                                .unwrap()
994                                .component_any_type_at(resource)
995                                .unwrap_resource();
996                            let ty = self.core_func_signature(core_func_index)?;
997                            core_func_index += 1;
998                            LocalInitializer::ResourceDrop(resource, ty)
999                        }
1000                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
1001                            let resource = self
1002                                .validator
1003                                .types(0)
1004                                .unwrap()
1005                                .component_any_type_at(resource)
1006                                .unwrap_resource();
1007                            let ty = self.core_func_signature(core_func_index)?;
1008                            core_func_index += 1;
1009                            LocalInitializer::ResourceRep(resource, ty)
1010                        }
1011                        wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
1012                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
1013                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
1014                            bail!("unsupported intrinsic")
1015                        }
1016                        wasmparser::CanonicalFunction::BackpressureInc => {
1017                            let core_type = self.core_func_signature(core_func_index)?;
1018                            core_func_index += 1;
1019                            LocalInitializer::BackpressureInc { func: core_type }
1020                        }
1021                        wasmparser::CanonicalFunction::BackpressureDec => {
1022                            let core_type = self.core_func_signature(core_func_index)?;
1023                            core_func_index += 1;
1024                            LocalInitializer::BackpressureDec { func: core_type }
1025                        }
1026
1027                        wasmparser::CanonicalFunction::TaskReturn { result, options } => {
1028                            let result = result.map(|ty| match ty {
1029                                wasmparser::ComponentValType::Primitive(ty) => {
1030                                    ComponentValType::Primitive(ty)
1031                                }
1032                                wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
1033                                    self.validator
1034                                        .types(0)
1035                                        .unwrap()
1036                                        .component_defined_type_at(ty),
1037                                ),
1038                            });
1039                            let options = self.canonical_options(&options, core_func_index)?;
1040                            core_func_index += 1;
1041                            LocalInitializer::TaskReturn { result, options }
1042                        }
1043                        wasmparser::CanonicalFunction::TaskCancel => {
1044                            let func = self.core_func_signature(core_func_index)?;
1045                            core_func_index += 1;
1046                            LocalInitializer::TaskCancel { func }
1047                        }
1048                        wasmparser::CanonicalFunction::WaitableSetNew => {
1049                            let func = self.core_func_signature(core_func_index)?;
1050                            core_func_index += 1;
1051                            LocalInitializer::WaitableSetNew { func }
1052                        }
1053                        wasmparser::CanonicalFunction::WaitableSetWait {
1054                            cancellable,
1055                            memory,
1056                        } => {
1057                            let core_type = self.core_func_signature(core_func_index)?;
1058                            core_func_index += 1;
1059                            LocalInitializer::WaitableSetWait {
1060                                options: LocalCanonicalOptions {
1061                                    core_type,
1062                                    cancellable,
1063                                    async_: false,
1064                                    data_model: LocalDataModel::LinearMemory {
1065                                        memory: Some(MemoryIndex::from_u32(memory)),
1066                                        realloc: None,
1067                                    },
1068                                    post_return: None,
1069                                    callback: None,
1070                                    string_encoding: StringEncoding::Utf8,
1071                                },
1072                            }
1073                        }
1074                        wasmparser::CanonicalFunction::WaitableSetPoll {
1075                            cancellable,
1076                            memory,
1077                        } => {
1078                            let core_type = self.core_func_signature(core_func_index)?;
1079                            core_func_index += 1;
1080                            LocalInitializer::WaitableSetPoll {
1081                                options: LocalCanonicalOptions {
1082                                    core_type,
1083                                    async_: false,
1084                                    cancellable,
1085                                    data_model: LocalDataModel::LinearMemory {
1086                                        memory: Some(MemoryIndex::from_u32(memory)),
1087                                        realloc: None,
1088                                    },
1089                                    post_return: None,
1090                                    callback: None,
1091                                    string_encoding: StringEncoding::Utf8,
1092                                },
1093                            }
1094                        }
1095                        wasmparser::CanonicalFunction::WaitableSetDrop => {
1096                            let func = self.core_func_signature(core_func_index)?;
1097                            core_func_index += 1;
1098                            LocalInitializer::WaitableSetDrop { func }
1099                        }
1100                        wasmparser::CanonicalFunction::WaitableJoin => {
1101                            let func = self.core_func_signature(core_func_index)?;
1102                            core_func_index += 1;
1103                            LocalInitializer::WaitableJoin { func }
1104                        }
1105                        wasmparser::CanonicalFunction::SubtaskDrop => {
1106                            let func = self.core_func_signature(core_func_index)?;
1107                            core_func_index += 1;
1108                            LocalInitializer::SubtaskDrop { func }
1109                        }
1110                        wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
1111                            let func = self.core_func_signature(core_func_index)?;
1112                            core_func_index += 1;
1113                            LocalInitializer::SubtaskCancel { func, async_ }
1114                        }
1115                        wasmparser::CanonicalFunction::StreamNew { ty } => {
1116                            let ty = self
1117                                .validator
1118                                .types(0)
1119                                .unwrap()
1120                                .component_defined_type_at(ty);
1121                            let func = self.core_func_signature(core_func_index)?;
1122                            core_func_index += 1;
1123                            LocalInitializer::StreamNew { ty, func }
1124                        }
1125                        wasmparser::CanonicalFunction::StreamRead { ty, options } => {
1126                            let ty = self
1127                                .validator
1128                                .types(0)
1129                                .unwrap()
1130                                .component_defined_type_at(ty);
1131                            let options = self.canonical_options(&options, core_func_index)?;
1132                            core_func_index += 1;
1133                            LocalInitializer::StreamRead { ty, options }
1134                        }
1135                        wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
1136                            let ty = self
1137                                .validator
1138                                .types(0)
1139                                .unwrap()
1140                                .component_defined_type_at(ty);
1141                            let options = self.canonical_options(&options, core_func_index)?;
1142                            core_func_index += 1;
1143                            LocalInitializer::StreamWrite { ty, options }
1144                        }
1145                        wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1146                            let ty = self
1147                                .validator
1148                                .types(0)
1149                                .unwrap()
1150                                .component_defined_type_at(ty);
1151                            let func = self.core_func_signature(core_func_index)?;
1152                            core_func_index += 1;
1153                            LocalInitializer::StreamCancelRead { ty, func, async_ }
1154                        }
1155                        wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1156                            let ty = self
1157                                .validator
1158                                .types(0)
1159                                .unwrap()
1160                                .component_defined_type_at(ty);
1161                            let func = self.core_func_signature(core_func_index)?;
1162                            core_func_index += 1;
1163                            LocalInitializer::StreamCancelWrite { ty, func, async_ }
1164                        }
1165                        wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1166                            let ty = self
1167                                .validator
1168                                .types(0)
1169                                .unwrap()
1170                                .component_defined_type_at(ty);
1171                            let func = self.core_func_signature(core_func_index)?;
1172                            core_func_index += 1;
1173                            LocalInitializer::StreamDropReadable { ty, func }
1174                        }
1175                        wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1176                            let ty = self
1177                                .validator
1178                                .types(0)
1179                                .unwrap()
1180                                .component_defined_type_at(ty);
1181                            let func = self.core_func_signature(core_func_index)?;
1182                            core_func_index += 1;
1183                            LocalInitializer::StreamDropWritable { ty, func }
1184                        }
1185                        wasmparser::CanonicalFunction::FutureNew { ty } => {
1186                            let ty = self
1187                                .validator
1188                                .types(0)
1189                                .unwrap()
1190                                .component_defined_type_at(ty);
1191                            let func = self.core_func_signature(core_func_index)?;
1192                            core_func_index += 1;
1193                            LocalInitializer::FutureNew { ty, func }
1194                        }
1195                        wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1196                            let ty = self
1197                                .validator
1198                                .types(0)
1199                                .unwrap()
1200                                .component_defined_type_at(ty);
1201                            let options = self.canonical_options(&options, core_func_index)?;
1202                            core_func_index += 1;
1203                            LocalInitializer::FutureRead { ty, options }
1204                        }
1205                        wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1206                            let ty = self
1207                                .validator
1208                                .types(0)
1209                                .unwrap()
1210                                .component_defined_type_at(ty);
1211                            let options = self.canonical_options(&options, core_func_index)?;
1212                            core_func_index += 1;
1213                            LocalInitializer::FutureWrite { ty, options }
1214                        }
1215                        wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1216                            let ty = self
1217                                .validator
1218                                .types(0)
1219                                .unwrap()
1220                                .component_defined_type_at(ty);
1221                            let func = self.core_func_signature(core_func_index)?;
1222                            core_func_index += 1;
1223                            LocalInitializer::FutureCancelRead { ty, func, async_ }
1224                        }
1225                        wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1226                            let ty = self
1227                                .validator
1228                                .types(0)
1229                                .unwrap()
1230                                .component_defined_type_at(ty);
1231                            let func = self.core_func_signature(core_func_index)?;
1232                            core_func_index += 1;
1233                            LocalInitializer::FutureCancelWrite { ty, func, async_ }
1234                        }
1235                        wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1236                            let ty = self
1237                                .validator
1238                                .types(0)
1239                                .unwrap()
1240                                .component_defined_type_at(ty);
1241                            let func = self.core_func_signature(core_func_index)?;
1242                            core_func_index += 1;
1243                            LocalInitializer::FutureDropReadable { ty, func }
1244                        }
1245                        wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1246                            let ty = self
1247                                .validator
1248                                .types(0)
1249                                .unwrap()
1250                                .component_defined_type_at(ty);
1251                            let func = self.core_func_signature(core_func_index)?;
1252                            core_func_index += 1;
1253                            LocalInitializer::FutureDropWritable { ty, func }
1254                        }
1255                        wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1256                            let options = self.canonical_options(&options, core_func_index)?;
1257                            core_func_index += 1;
1258                            LocalInitializer::ErrorContextNew { options }
1259                        }
1260                        wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1261                            let options = self.canonical_options(&options, core_func_index)?;
1262                            core_func_index += 1;
1263                            LocalInitializer::ErrorContextDebugMessage { options }
1264                        }
1265                        wasmparser::CanonicalFunction::ErrorContextDrop => {
1266                            let func = self.core_func_signature(core_func_index)?;
1267                            core_func_index += 1;
1268                            LocalInitializer::ErrorContextDrop { func }
1269                        }
1270                        wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1271                            if ty != wasmparser::ValType::I32 {
1272                                bail!("unsupported context.get type: {ty:?}");
1273                            }
1274                            let func = self.core_func_signature(core_func_index)?;
1275                            core_func_index += 1;
1276                            LocalInitializer::ContextGet { i: slot, func }
1277                        }
1278                        wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1279                            if ty != wasmparser::ValType::I32 {
1280                                bail!("unsupported context.set type: {ty:?}");
1281                            }
1282                            let func = self.core_func_signature(core_func_index)?;
1283                            core_func_index += 1;
1284                            LocalInitializer::ContextSet { i: slot, func }
1285                        }
1286                        wasmparser::CanonicalFunction::ThreadIndex => {
1287                            let func = self.core_func_signature(core_func_index)?;
1288                            core_func_index += 1;
1289                            LocalInitializer::ThreadIndex { func }
1290                        }
1291                        wasmparser::CanonicalFunction::ThreadNewIndirect {
1292                            func_ty_index,
1293                            table_index,
1294                        } => {
1295                            let func = self.core_func_signature(core_func_index)?;
1296                            core_func_index += 1;
1297                            LocalInitializer::ThreadNewIndirect {
1298                                func,
1299                                start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1300                                start_func_table_index: TableIndex::from_u32(table_index),
1301                            }
1302                        }
1303                        wasmparser::CanonicalFunction::ThreadResumeLater => {
1304                            let func = self.core_func_signature(core_func_index)?;
1305                            core_func_index += 1;
1306                            LocalInitializer::ThreadResumeLater { func }
1307                        }
1308                        wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1309                            let func = self.core_func_signature(core_func_index)?;
1310                            core_func_index += 1;
1311                            LocalInitializer::ThreadSuspend { func, cancellable }
1312                        }
1313                        wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
1314                            let func = self.core_func_signature(core_func_index)?;
1315                            core_func_index += 1;
1316                            LocalInitializer::ThreadYield { func, cancellable }
1317                        }
1318                        wasmparser::CanonicalFunction::ThreadSuspendThenResume { cancellable } => {
1319                            let func = self.core_func_signature(core_func_index)?;
1320                            core_func_index += 1;
1321                            LocalInitializer::ThreadSuspendThenResume { func, cancellable }
1322                        }
1323                        wasmparser::CanonicalFunction::ThreadYieldThenResume { cancellable } => {
1324                            let func = self.core_func_signature(core_func_index)?;
1325                            core_func_index += 1;
1326                            LocalInitializer::ThreadYieldThenResume { func, cancellable }
1327                        }
1328                        wasmparser::CanonicalFunction::ThreadSuspendThenPromote { cancellable } => {
1329                            let func = self.core_func_signature(core_func_index)?;
1330                            core_func_index += 1;
1331                            LocalInitializer::ThreadSuspendThenPromote { func, cancellable }
1332                        }
1333                        wasmparser::CanonicalFunction::ThreadYieldThenPromote { cancellable } => {
1334                            let func = self.core_func_signature(core_func_index)?;
1335                            core_func_index += 1;
1336                            LocalInitializer::ThreadYieldThenPromote { func, cancellable }
1337                        }
1338                    };
1339                    self.result.initializers.push(init);
1340                }
1341            }
1342
1343            // Core wasm modules are translated inline directly here with the
1344            // `ModuleEnvironment` from core wasm compilation. This will return
1345            // to the caller the size of the module so it knows how many bytes
1346            // of the input are skipped.
1347            //
1348            // Note that this is just initial type translation of the core wasm
1349            // module and actual function compilation is deferred until this
1350            // entire process has completed.
1351            Payload::ModuleSection {
1352                parser,
1353                unchecked_range,
1354            } => {
1355                let index = self.validator.types(0).unwrap().module_count();
1356                self.validator.module_section(&unchecked_range)?;
1357                let static_module_index = self.static_modules.next_key();
1358                let mut translation = ModuleEnvironment::new(
1359                    self.tunables,
1360                    self.validator,
1361                    self.types.module_types_builder(),
1362                    static_module_index,
1363                )
1364                .translate(
1365                    parser,
1366                    component
1367                        .get(unchecked_range.start as usize..unchecked_range.end as usize)
1368                        .ok_or_else(|| {
1369                            format_err!(
1370                                "section range {}..{} is out of bounds (bound = {})",
1371                                unchecked_range.start,
1372                                unchecked_range.end,
1373                                component.len()
1374                            )
1375                            .context("wasm component contains an invalid module section")
1376                        })?,
1377                )?;
1378
1379                translation.wasm_module_offset = unchecked_range.start;
1380                let static_module_index2 = self.static_modules.push(translation);
1381                assert_eq!(static_module_index, static_module_index2);
1382                let types = self.validator.types(0).unwrap();
1383                let ty = types.module_at(index);
1384                self.result
1385                    .initializers
1386                    .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1387                return Ok(Action::Skip(
1388                    (unchecked_range.end - unchecked_range.start) as usize,
1389                ));
1390            }
1391
1392            // When a sub-component is found then the current translation state
1393            // is pushed onto the `lexical_scopes` stack. This will subsequently
1394            // get popped as part of `Payload::End` processing above.
1395            //
1396            // Note that the set of closure args for this new lexical scope
1397            // starts empty since it will only get populated if translation of
1398            // the nested component ends up aliasing some outer module or
1399            // component.
1400            Payload::ComponentSection {
1401                parser,
1402                unchecked_range,
1403            } => {
1404                self.validator.component_section(&unchecked_range)?;
1405                self.lexical_scopes.push(LexicalScope {
1406                    parser: mem::replace(&mut self.parser, parser),
1407                    translation: mem::take(&mut self.result),
1408                    closure_args: ClosedOverVars::default(),
1409                });
1410            }
1411
1412            // Both core wasm instances and component instances record
1413            // initializers of what form of instantiation is performed which
1414            // largely just records the arguments given from wasmparser into a
1415            // `HashMap` for processing later during inlining.
1416            Payload::InstanceSection(s) => {
1417                self.validator.instance_section(&s)?;
1418                for instance in s {
1419                    let init = match instance? {
1420                        wasmparser::Instance::Instantiate { module_index, args } => {
1421                            let index = ModuleIndex::from_u32(module_index);
1422                            self.instantiate_module(index, &args)
1423                        }
1424                        wasmparser::Instance::FromExports(exports) => {
1425                            self.instantiate_module_from_exports(&exports)
1426                        }
1427                    };
1428                    self.result.initializers.push(init);
1429                }
1430            }
1431            Payload::ComponentInstanceSection(s) => {
1432                let mut index = self.validator.types(0).unwrap().component_instance_count();
1433                self.validator.component_instance_section(&s)?;
1434                for instance in s {
1435                    let types = self.validator.types(0).unwrap();
1436                    let ty = types.component_instance_at(index);
1437                    let init = match instance? {
1438                        wasmparser::ComponentInstance::Instantiate {
1439                            component_index,
1440                            args,
1441                        } => {
1442                            let index = ComponentIndex::from_u32(component_index);
1443                            self.instantiate_component(index, &args, ty)?
1444                        }
1445                        wasmparser::ComponentInstance::FromExports(exports) => {
1446                            self.instantiate_component_from_exports(&exports, ty)?
1447                        }
1448                    };
1449                    self.result.initializers.push(init);
1450                    index += 1;
1451                }
1452            }
1453
1454            // Exports don't actually fill out the `initializers` array but
1455            // instead fill out the one other field in a `Translation`, the
1456            // `exports` field (as one might imagine). This for now simply
1457            // records the index of what's exported and that's tracked further
1458            // later during inlining.
1459            Payload::ComponentExportSection(s) => {
1460                self.validator.component_export_section(&s)?;
1461                for export in s {
1462                    let export = export?;
1463                    let item = self.kind_to_item(export.kind, export.index)?;
1464                    let prev = self
1465                        .result
1466                        .exports
1467                        .insert(export.name.name, (item, export.name));
1468                    assert!(prev.is_none());
1469                    self.result
1470                        .initializers
1471                        .push(LocalInitializer::Export(item));
1472                }
1473            }
1474
1475            Payload::ComponentStartSection { start, range } => {
1476                self.validator.component_start_section(&start, &range)?;
1477                unimplemented!("component start section");
1478            }
1479
1480            // Aliases of instance exports (either core or component) will be
1481            // recorded as an initializer of the appropriate type with outer
1482            // aliases handled specially via upvars and type processing.
1483            Payload::ComponentAliasSection(s) => {
1484                self.validator.component_alias_section(&s)?;
1485                for alias in s {
1486                    let init = match alias? {
1487                        wasmparser::ComponentAlias::InstanceExport {
1488                            kind: _,
1489                            instance_index,
1490                            name,
1491                        } => {
1492                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1493                            LocalInitializer::AliasComponentExport(instance, name)
1494                        }
1495                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1496                            self.alias_component_outer(kind, count, index);
1497                            continue;
1498                        }
1499                        wasmparser::ComponentAlias::CoreInstanceExport {
1500                            kind,
1501                            instance_index,
1502                            name,
1503                        } => {
1504                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1505                            self.alias_module_instance_export(kind, instance, name)
1506                        }
1507                    };
1508                    self.result.initializers.push(init);
1509                }
1510            }
1511
1512            // All custom sections are ignored by Wasmtime at this time.
1513            //
1514            // FIXME(WebAssembly/component-model#14): probably want to specify
1515            // and parse a `name` section here.
1516            Payload::CustomSection { .. } => {}
1517
1518            // Anything else is either not reachable since we never enable the
1519            // feature in Wasmtime or we do enable it and it's a bug we don't
1520            // implement it, so let validation take care of most errors here and
1521            // if it gets past validation provide a helpful error message to
1522            // debug.
1523            other => {
1524                self.validator.payload(&other)?;
1525                panic!("unimplemented section {other:?}");
1526            }
1527        }
1528
1529        Ok(Action::KeepGoing)
1530    }
1531
1532    fn instantiate_module(
1533        &mut self,
1534        module: ModuleIndex,
1535        raw_args: &[wasmparser::InstantiationArg<'data>],
1536    ) -> LocalInitializer<'data> {
1537        let mut args = HashMap::with_capacity(raw_args.len());
1538        for arg in raw_args {
1539            match arg.kind {
1540                wasmparser::InstantiationArgKind::Instance => {
1541                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1542                    args.insert(arg.name, idx);
1543                }
1544            }
1545        }
1546        LocalInitializer::ModuleInstantiate(module, args)
1547    }
1548
1549    /// Creates a synthetic module from the list of items currently in the
1550    /// module and their given names.
1551    fn instantiate_module_from_exports(
1552        &mut self,
1553        exports: &[wasmparser::Export<'data>],
1554    ) -> LocalInitializer<'data> {
1555        let mut map = HashMap::with_capacity(exports.len());
1556        for export in exports {
1557            let idx = match export.kind {
1558                wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1559                    let index = FuncIndex::from_u32(export.index);
1560                    EntityIndex::Function(index)
1561                }
1562                wasmparser::ExternalKind::Table => {
1563                    let index = TableIndex::from_u32(export.index);
1564                    EntityIndex::Table(index)
1565                }
1566                wasmparser::ExternalKind::Memory => {
1567                    let index = MemoryIndex::from_u32(export.index);
1568                    EntityIndex::Memory(index)
1569                }
1570                wasmparser::ExternalKind::Global => {
1571                    let index = GlobalIndex::from_u32(export.index);
1572                    EntityIndex::Global(index)
1573                }
1574                wasmparser::ExternalKind::Tag => {
1575                    let index = TagIndex::from_u32(export.index);
1576                    EntityIndex::Tag(index)
1577                }
1578            };
1579            map.insert(export.name, idx);
1580        }
1581        LocalInitializer::ModuleSynthetic(map)
1582    }
1583
1584    fn instantiate_component(
1585        &mut self,
1586        component: ComponentIndex,
1587        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1588        ty: ComponentInstanceTypeId,
1589    ) -> Result<LocalInitializer<'data>> {
1590        let mut args = HashMap::with_capacity(raw_args.len());
1591        for arg in raw_args {
1592            let idx = self.kind_to_item(arg.kind, arg.index)?;
1593            args.insert(arg.name, idx);
1594        }
1595
1596        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1597    }
1598
1599    /// Creates a synthetic module from the list of items currently in the
1600    /// module and their given names.
1601    fn instantiate_component_from_exports(
1602        &mut self,
1603        exports: &[wasmparser::ComponentExport<'data>],
1604        ty: ComponentInstanceTypeId,
1605    ) -> Result<LocalInitializer<'data>> {
1606        let mut map = HashMap::with_capacity(exports.len());
1607        for export in exports {
1608            let idx = self.kind_to_item(export.kind, export.index)?;
1609            map.insert(export.name.name, (idx, export.name));
1610        }
1611
1612        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1613    }
1614
1615    fn kind_to_item(
1616        &mut self,
1617        kind: wasmparser::ComponentExternalKind,
1618        index: u32,
1619    ) -> Result<ComponentItem> {
1620        Ok(match kind {
1621            wasmparser::ComponentExternalKind::Func => {
1622                let index = ComponentFuncIndex::from_u32(index);
1623                ComponentItem::Func(index)
1624            }
1625            wasmparser::ComponentExternalKind::Module => {
1626                let index = ModuleIndex::from_u32(index);
1627                ComponentItem::Module(index)
1628            }
1629            wasmparser::ComponentExternalKind::Instance => {
1630                let index = ComponentInstanceIndex::from_u32(index);
1631                ComponentItem::ComponentInstance(index)
1632            }
1633            wasmparser::ComponentExternalKind::Component => {
1634                let index = ComponentIndex::from_u32(index);
1635                ComponentItem::Component(index)
1636            }
1637            wasmparser::ComponentExternalKind::Value => {
1638                unimplemented!("component values");
1639            }
1640            wasmparser::ComponentExternalKind::Type => {
1641                let types = self.validator.types(0).unwrap();
1642                let ty = types.component_any_type_at(index);
1643                ComponentItem::Type(ty)
1644            }
1645        })
1646    }
1647
1648    fn alias_module_instance_export(
1649        &mut self,
1650        kind: wasmparser::ExternalKind,
1651        instance: ModuleInstanceIndex,
1652        name: &'data str,
1653    ) -> LocalInitializer<'data> {
1654        match kind {
1655            wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1656                LocalInitializer::AliasExportFunc(instance, name)
1657            }
1658            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1659            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1660            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1661            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1662        }
1663    }
1664
1665    fn alias_component_outer(
1666        &mut self,
1667        kind: wasmparser::ComponentOuterAliasKind,
1668        count: u32,
1669        index: u32,
1670    ) {
1671        match kind {
1672            wasmparser::ComponentOuterAliasKind::CoreType
1673            | wasmparser::ComponentOuterAliasKind::Type => {}
1674
1675            // For more information about the implementation of outer aliases
1676            // see the documentation of `LexicalScope`. Otherwise though the
1677            // main idea here is that the data to close over starts as `Local`
1678            // and then transitions to `Upvar` as its inserted into the parents
1679            // in order from target we're aliasing back to the current
1680            // component.
1681            wasmparser::ComponentOuterAliasKind::CoreModule => {
1682                let index = ModuleIndex::from_u32(index);
1683                let mut module = ClosedOverModule::Local(index);
1684                let depth = self.lexical_scopes.len() - (count as usize);
1685                for frame in self.lexical_scopes[depth..].iter_mut() {
1686                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1687                }
1688
1689                // If the `module` is still `Local` then the `depth` was 0 and
1690                // it's an alias into our own space. Otherwise it's switched to
1691                // an upvar and will index into the upvar space. Either way
1692                // it's just plumbed directly into the initializer.
1693                self.result
1694                    .initializers
1695                    .push(LocalInitializer::AliasModule(module));
1696            }
1697            wasmparser::ComponentOuterAliasKind::Component => {
1698                let index = ComponentIndex::from_u32(index);
1699                let mut component = ClosedOverComponent::Local(index);
1700                let depth = self.lexical_scopes.len() - (count as usize);
1701                for frame in self.lexical_scopes[depth..].iter_mut() {
1702                    component =
1703                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1704                }
1705
1706                self.result
1707                    .initializers
1708                    .push(LocalInitializer::AliasComponent(component));
1709            }
1710        }
1711    }
1712
1713    fn canonical_options(
1714        &mut self,
1715        opts: &[wasmparser::CanonicalOption],
1716        core_func_index: u32,
1717    ) -> WasmResult<LocalCanonicalOptions> {
1718        let core_type = self.core_func_signature(core_func_index)?;
1719
1720        let mut string_encoding = StringEncoding::Utf8;
1721        let mut post_return = None;
1722        let mut async_ = false;
1723        let mut callback = None;
1724        let mut memory = None;
1725        let mut realloc = None;
1726        let mut gc = false;
1727
1728        for opt in opts {
1729            match opt {
1730                wasmparser::CanonicalOption::UTF8 => {
1731                    string_encoding = StringEncoding::Utf8;
1732                }
1733                wasmparser::CanonicalOption::UTF16 => {
1734                    string_encoding = StringEncoding::Utf16;
1735                }
1736                wasmparser::CanonicalOption::CompactUTF16 => {
1737                    string_encoding = StringEncoding::CompactUtf16;
1738                }
1739                wasmparser::CanonicalOption::Memory(idx) => {
1740                    let idx = MemoryIndex::from_u32(*idx);
1741                    memory = Some(idx);
1742                }
1743                wasmparser::CanonicalOption::Realloc(idx) => {
1744                    let idx = FuncIndex::from_u32(*idx);
1745                    realloc = Some(idx);
1746                }
1747                wasmparser::CanonicalOption::PostReturn(idx) => {
1748                    let idx = FuncIndex::from_u32(*idx);
1749                    post_return = Some(idx);
1750                }
1751                wasmparser::CanonicalOption::Async => async_ = true,
1752                wasmparser::CanonicalOption::Callback(idx) => {
1753                    let idx = FuncIndex::from_u32(*idx);
1754                    callback = Some(idx);
1755                }
1756                wasmparser::CanonicalOption::CoreType(idx) => {
1757                    if cfg!(debug_assertions) {
1758                        let types = self.validator.types(0).unwrap();
1759                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1760                        let interned = self
1761                            .types
1762                            .module_types_builder()
1763                            .intern_type(types, core_ty_id)?;
1764                        debug_assert_eq!(interned, core_type);
1765                    }
1766                }
1767                wasmparser::CanonicalOption::Gc => {
1768                    gc = true;
1769                }
1770            }
1771        }
1772
1773        Ok(LocalCanonicalOptions {
1774            string_encoding,
1775            post_return,
1776            cancellable: false,
1777            async_,
1778            callback,
1779            core_type,
1780            data_model: if gc {
1781                LocalDataModel::Gc {}
1782            } else {
1783                LocalDataModel::LinearMemory { memory, realloc }
1784            },
1785        })
1786    }
1787
1788    /// Get the interned type index for the `index`th core function.
1789    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1790        let types = self.validator.types(0).unwrap();
1791        let id = types.core_function_at(index);
1792        self.types.module_types_builder().intern_type(types, id)
1793    }
1794
1795    fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1796        self.lexical_scopes.is_empty()
1797            && self
1798                .unsafe_intrinsics_import
1799                .is_some_and(|name| import == name)
1800    }
1801
1802    fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1803        let types = &self.validator.types(0).unwrap();
1804
1805        let ComponentEntityType::Instance(instance_ty) = ty else {
1806            bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1807        };
1808        let instance_ty = &types[instance_ty];
1809
1810        ensure!(
1811            instance_ty.defined_resources.is_empty(),
1812            "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1813        );
1814        ensure!(
1815            instance_ty.explicit_resources.is_empty(),
1816            "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1817        );
1818
1819        for (name, ty) in &instance_ty.exports {
1820            let ComponentEntityType::Func(func_ty) = ty.ty else {
1821                bail!(
1822                    "bad unsafe intrinsics import: imported instance `{import}` must \
1823                     only export functions"
1824                )
1825            };
1826            let func_ty = &types[func_ty];
1827
1828            fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1829                use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1830                match (a, b) {
1831                    (InterfaceType::U8, C::Primitive(P::U8)) => true,
1832                    (InterfaceType::U8, _) => false,
1833
1834                    (InterfaceType::U16, C::Primitive(P::U16)) => true,
1835                    (InterfaceType::U16, _) => false,
1836
1837                    (InterfaceType::U32, C::Primitive(P::U32)) => true,
1838                    (InterfaceType::U32, _) => false,
1839
1840                    (InterfaceType::U64, C::Primitive(P::U64)) => true,
1841                    (InterfaceType::U64, _) => false,
1842
1843                    (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1844                }
1845            }
1846
1847            fn check_types<'a>(
1848                expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1849                actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1850                kind: &str,
1851                import: &str,
1852                name: &str,
1853            ) -> Result<()> {
1854                let expected_len = expected.len();
1855                let actual_len = actual.len();
1856                ensure!(
1857                    expected_len == actual_len,
1858                    "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1859                     {expected_len} {kind}, found {actual_len}"
1860                );
1861
1862                for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1863                    ensure!(
1864                        ty_eq(expected_ty, actual_ty),
1865                        "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1866                         `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1867                    );
1868                }
1869                Ok(())
1870            }
1871
1872            let intrinsic = UnsafeIntrinsic::from_str(name)
1873                .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1874
1875            check_types(
1876                intrinsic.component_params().iter(),
1877                func_ty.params.iter().map(|(_name, ty)| ty),
1878                "parameters",
1879                &import,
1880                &name,
1881            )?;
1882            check_types(
1883                intrinsic.component_results().iter(),
1884                func_ty.result.iter(),
1885                "results",
1886                &import,
1887                &name,
1888            )?;
1889        }
1890
1891        Ok(())
1892    }
1893}
1894
1895impl Translation<'_> {
1896    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1897        self.types.as_ref().unwrap().as_ref()
1898    }
1899}
1900
1901/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1902/// to disallow access to mutable access to the builder before the inlining
1903/// pass.
1904///
1905/// Type information in this translation pass must be preserved at the
1906/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1907/// own type system. Only during inlining are types fully assigned because
1908/// that's when resource types become available as it's known which instance
1909/// defines which resource, or more concretely the same component instantiated
1910/// twice will produce two unique resource types unlike one as seen by
1911/// wasmparser within the component.
1912mod pre_inlining {
1913    use super::*;
1914
1915    pub struct PreInliningComponentTypes<'a> {
1916        types: &'a mut ComponentTypesBuilder,
1917    }
1918
1919    impl<'a> PreInliningComponentTypes<'a> {
1920        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1921            Self { types }
1922        }
1923
1924        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1925            self.types.module_types_builder_mut()
1926        }
1927
1928        pub fn types(&self) -> &ComponentTypesBuilder {
1929            self.types
1930        }
1931
1932        // NB: this should in theory only be used for the `inline` phase of
1933        // translation.
1934        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1935            self.types
1936        }
1937    }
1938
1939    impl TypeConvert for PreInliningComponentTypes<'_> {
1940        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1941            self.types.lookup_heap_type(index)
1942        }
1943
1944        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1945            self.types.lookup_type_index(index)
1946        }
1947    }
1948}
1949use pre_inlining::PreInliningComponentTypes;
1950
1951/// A map from each runtime instance to the static module it is an instance of
1952/// and the arguments it was instantiated with, when we statically know them.
1953///
1954/// `None` for instances of modules that are not part of this component, and
1955/// whose shape we therefore cannot see into.
1956type StaticInstances<'a> =
1957    PrimaryMap<RuntimeInstanceIndex, Option<(StaticModuleIndex, &'a [CoreDef])>>;
1958
1959/// Every entity whose identity is not statically known to everything that can
1960/// access it.
1961#[derive(Default)]
1962struct Ambiguous {
1963    /// Globals, memories, and tables defined by a static module in this
1964    /// component.
1965    entities: HashSet<(StaticModuleIndex, EntityIndex)>,
1966
1967    /// Component-model flags living in the `VMComponentContext`. Only ever
1968    /// contains the non-`KnownGlobal::Defined` variants.
1969    flags: HashSet<KnownGlobal>,
1970}
1971
1972/// Get the component-model flag that a `CoreDef` names, if it names one.
1973fn component_flags(def: &CoreDef) -> Option<KnownGlobal> {
1974    match def {
1975        CoreDef::InstanceFlags(instance) => Some(KnownGlobal::ComponentInstanceFlags(*instance)),
1976        CoreDef::Export(_) | CoreDef::Trampoline(_) | CoreDef::UnsafeIntrinsic(_) => None,
1977    }
1978}
1979
1980/// Resolve a `CoreExport` to the static module that *defines* it and the entity
1981/// index it refers to within that module, when we can see through it statically.
1982///
1983/// A module may import an entity and then re-export it, in which case the
1984/// export names an index in the re-exporting module's *imported* index space.
1985/// We follow those chains all the way back to the module that actually defines
1986/// the entity, so that the returned pair is a canonical identity for it: every
1987/// reference to the same entity resolves to the same `(module, entity)` pair, no
1988/// matter how many modules it was laundered through along the way. That is
1989/// load-bearing for alias regions, where naming the same bytes with two
1990/// different keys is a miscompile.
1991///
1992/// Therefore a returned `Some((module, entity))` always satisfies
1993/// `!static_modules[module].module.is_imported(entity)`.
1994fn resolve_core_export(
1995    static_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
1996    instances: &StaticInstances<'_>,
1997    export: &CoreExport<EntityIndex>,
1998) -> Option<(StaticModuleIndex, EntityIndex)> {
1999    let mut instance = export.instance;
2000    let mut item = &export.item;
2001
2002    loop {
2003        // This can be an instance of a dynamic module that is not part of this
2004        // component, rather than a statically-known module inside of it.
2005        let (module, args) = instances[instance]?;
2006
2007        let index = match item {
2008            ExportItem::Index(index) => *index,
2009            // Names are only used for instances of modules whose shape we don't
2010            // statically know, which we already filtered out.
2011            ExportItem::Name(_) => return None,
2012        };
2013
2014        // The common case: this instance's module defines the entity itself, so
2015        // we've bottomed out at its canonical identity.
2016        if !static_modules[module].module.is_imported(index) {
2017            return Some((module, index));
2018        }
2019
2020        // Otherwise this is a re-export of one of the module's imports, so keep
2021        // walking through whichever argument satisfied that import.
2022        let position = static_modules[module]
2023            .module
2024            .import_position(index)
2025            .expect("imported entities always have an associated import initializer");
2026        match &args[position] {
2027            CoreDef::Export(next) => {
2028                // An instantiation's arguments are always exports of instances
2029                // created before the instance being instantiated: `LinearizeDfg`
2030                // builds the argument `CoreDef`s before assigning the new
2031                // instance's `RuntimeInstanceIndex`, and would panic building an
2032                // export of an instance it had not linearized yet. So this walk
2033                // strictly decreases and must terminate.
2034                assert!(next.instance < instance);
2035                instance = next.instance;
2036                item = &next.item;
2037            }
2038
2039            // The chain bottoms out in something that is not an export of
2040            // another instance in this component, so there is no defining module
2041            // for us to name.
2042            CoreDef::InstanceFlags(_) | CoreDef::Trampoline(_) | CoreDef::UnsafeIntrinsic(_) => {
2043                return None;
2044            }
2045        }
2046    }
2047}
2048
2049/// Same as `resolve_core_export`, but for a `CoreDef` that must additionally be
2050/// unambiguous.
2051fn unambiguous_entity(
2052    static_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
2053    instances: &StaticInstances<'_>,
2054    ambiguous: &HashSet<(StaticModuleIndex, EntityIndex)>,
2055    def: &CoreDef,
2056) -> Option<(StaticModuleIndex, EntityIndex)> {
2057    let CoreDef::Export(export) = def else {
2058        return None;
2059    };
2060    let entity = resolve_core_export(static_modules, instances, export)?;
2061    if ambiguous.contains(&entity) {
2062        return None;
2063    }
2064    Some(entity)
2065}
2066
2067/// Find every core wasm entity in this component whose identity is *not*
2068/// statically known to every module that may import it.
2069///
2070/// An entity is unambiguous when every argument it flows into belongs to a
2071/// module that we only ever instantiate with that same entity:
2072///
2073/// * An argument to a module that we may instantiate differently elsewhere is
2074///   ambiguous because that module cannot statically know which one of these
2075///   entities it was given at runtime.
2076///
2077/// * An argument to an imported module is ambiguous because that module is
2078///   compiled separately from this component, and it may re-export the entity
2079///   back to us under a name we cannot see through, which we may then hand to a
2080///   module whose imports we do otherwise know.
2081///
2082/// Note that ambiguity is never partial: if a module importing an entity has to
2083/// conservatively tag its accesses with that entity's public alias region, then
2084/// the module defining the entity must do the same, or else inlining one of
2085/// them into the other would access the same bytes through two different alias
2086/// regions, which is invalid.
2087///
2088/// Entities in the returned set are identified by the module that *defines*
2089/// them, as resolved by `resolve_core_export`. That is what makes the previous
2090/// paragraph work through re-exports: marking a module's re-export of an import
2091/// as ambiguous poisons the definition it ultimately refers to, and therefore
2092/// every other module that can reach that definition, and not just the
2093/// re-exporter.
2094fn ambiguous_entities(
2095    static_modules: &PrimaryMap<StaticModuleIndex, ModuleTranslation<'_>>,
2096    translation: &ComponentTranslation,
2097    instantiations: &SecondaryMap<StaticModuleIndex, dfg::AbstractInstantiations<'_>>,
2098    instances: &StaticInstances<'_>,
2099) -> Ambiguous {
2100    let mut ambiguous = Ambiguous::default();
2101
2102    let mut mark = |def: &CoreDef| match def {
2103        CoreDef::Export(export) => {
2104            if let Some(entity) = resolve_core_export(static_modules, instances, export) {
2105                ambiguous.entities.insert(entity);
2106            }
2107        }
2108
2109        CoreDef::InstanceFlags(_) => {
2110            ambiguous.flags.insert(component_flags(def).unwrap());
2111        }
2112
2113        // Neither of these is an entity that gets an alias region keyed by a
2114        // defining module and index.
2115        CoreDef::Trampoline(_) | CoreDef::UnsafeIntrinsic(_) => {}
2116    };
2117
2118    for init in &translation.component.initializers {
2119        match init {
2120            GlobalInitializer::InstantiateModule(instantiation, _) => match instantiation {
2121                InstantiateModule::Static(module, args) => {
2122                    // Arguments to modules that we only instantiate one way are
2123                    // exactly the references that keep an entity unambiguous, so
2124                    // they are the one case we do not mark here. Everything else
2125                    // gets whichever of a number of different entities it was
2126                    // handed at runtime, and so has to be conservative.
2127                    if !matches!(instantiations[*module], dfg::AbstractInstantiations::One(_)) {
2128                        for arg in args.iter() {
2129                            mark(arg);
2130                        }
2131                    }
2132                }
2133
2134                // We cannot see through an imported module's exports, so an
2135                // entity we pass into one and that comes back out to a module
2136                // whose imports we do know would be accessed via two different
2137                // alias regions.
2138                InstantiateModule::Import(_, args) => {
2139                    for arg in args.values().flat_map(|args| args.values()) {
2140                        mark(arg);
2141                    }
2142                }
2143            },
2144
2145            // The remaining initializers do not involve the global/table/memory
2146            // alias regions.
2147            GlobalInitializer::ExtractMemory(_)
2148            | GlobalInitializer::ExtractTable(_)
2149            | GlobalInitializer::ExtractRealloc(_)
2150            | GlobalInitializer::ExtractCallback(_)
2151            | GlobalInitializer::ExtractPostReturn(_)
2152            | GlobalInitializer::Resource(_)
2153            | GlobalInitializer::LowerImport { .. } => {}
2154        }
2155    }
2156
2157    ambiguous
2158}