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