wasmtime_environ/component/
translate.rs

1use crate::ScopeVec;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6    EngineOrModuleTypeIndex, EntityIndex, ModuleEnvironment, ModuleInternedTypeIndex,
7    ModuleTranslation, ModuleTypesBuilder, PrimaryMap, TagIndex, Tunables, TypeConvert,
8    WasmHeapType, WasmResult, WasmValType,
9};
10use anyhow::anyhow;
11use anyhow::{Result, bail};
12use cranelift_entity::SecondaryMap;
13use cranelift_entity::packed_option::PackedOption;
14use indexmap::IndexMap;
15use std::collections::HashMap;
16use std::mem;
17use wasmparser::component_types::{
18    AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
19    ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
20};
21use wasmparser::types::Types;
22use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
23
24mod adapt;
25pub use self::adapt::*;
26mod inline;
27
28/// Structure used to translate a component and parse it.
29pub struct Translator<'a, 'data> {
30    /// The current component being translated.
31    ///
32    /// This will get swapped out as translation traverses the body of a
33    /// component and a sub-component is entered or left.
34    result: Translation<'data>,
35
36    /// Current state of parsing a binary component. Note that like `result`
37    /// this will change as the component is traversed.
38    parser: Parser,
39
40    /// Stack of lexical scopes that are in-progress but not finished yet.
41    ///
42    /// This is pushed to whenever a component is entered and popped from
43    /// whenever a component is left. Each lexical scope also contains
44    /// information about the variables that it is currently required to close
45    /// over which is threaded into the current in-progress translation of
46    /// the sub-component which pushed a scope here.
47    lexical_scopes: Vec<LexicalScope<'data>>,
48
49    /// The validator in use to verify that the raw input binary is a valid
50    /// component.
51    validator: &'a mut Validator,
52
53    /// Type information shared for the entire component.
54    ///
55    /// This builder is also used for all core wasm modules found to intern
56    /// signatures across all modules.
57    types: PreInliningComponentTypes<'a>,
58
59    /// The compiler configuration provided by the embedder.
60    tunables: &'a Tunables,
61
62    /// Auxiliary location to push generated adapter modules onto.
63    scope_vec: &'data ScopeVec<u8>,
64
65    /// Completely translated core wasm modules that have been found so far.
66    ///
67    /// Note that this translation only involves learning about type
68    /// information and functions are not actually compiled here.
69    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
70
71    /// Completely translated components that have been found so far.
72    ///
73    /// As frames are popped from `lexical_scopes` their completed component
74    /// will be pushed onto this list.
75    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
76}
77
78/// Representation of the syntactic scope of a component meaning where it is
79/// and what its state is at in the binary format.
80///
81/// These scopes are pushed and popped when a sub-component starts being
82/// parsed and finishes being parsed. The main purpose of this frame is to
83/// have a `ClosedOverVars` field which encapsulates data that is inherited
84/// from the scope specified into the component being translated just beneath
85/// it.
86///
87/// This structure exists to implement outer aliases to components and modules.
88/// When a component or module is closed over then that means it needs to be
89/// inherited in a sense to the component which actually had the alias. This is
90/// achieved with a deceptively simple scheme where each parent of the
91/// component with the alias will inherit the component from the desired
92/// location.
93///
94/// For example with a component structure that looks like:
95///
96/// ```wasm
97/// (component $A
98///     (core module $M)
99///     (component $B
100///         (component $C
101///             (alias outer $A $M (core module))
102///         )
103///     )
104/// )
105/// ```
106///
107/// here the `C` component is closing over `M` located in the root component
108/// `A`. When `C` is being translated the `lexical_scopes` field will look like
109/// `[A, B]`. When the alias is encountered (for module index 0) this will
110/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
111/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
112/// inserted into `closure_args` in `B`'s frame. This produces yet another
113/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
114/// via `LocalInitializer::AliasModuleUpvar` with the last index.
115///
116/// All of these upvar indices and such are interpreted in the "inline" phase
117/// of compilation and not at runtime. This means that when `A` is being
118/// instantiated one of its initializers will be
119/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
120/// variables captured for `B` are listed as local module 0, or `M`. This list
121/// is then preserved in the definition of the component `B` and later reused
122/// by `C` again to finally get access to the closed over component.
123///
124/// Effectively the scopes are managed hierarchically where a reference to an
125/// outer variable automatically injects references into all parents up to
126/// where the reference is. This variable scopes are the processed during
127/// inlining where a component definition is a reference to the static
128/// component information (`Translation`) plus closed over variables
129/// (`ComponentClosure` during inlining).
130struct LexicalScope<'data> {
131    /// Current state of translating the `translation` below.
132    parser: Parser,
133    /// Current state of the component's translation as found so far.
134    translation: Translation<'data>,
135    /// List of captures that `translation` will need to process to create the
136    /// sub-component which is directly beneath this lexical scope.
137    closure_args: ClosedOverVars,
138}
139
140/// A "local" translation of a component.
141///
142/// This structure is used as a sort of in-progress translation of a component.
143/// This is not `Component` which is the final form as consumed by Wasmtime
144/// at runtime. Instead this is a fairly simple representation of a component
145/// where almost everything is ordered as a list of initializers. The binary
146/// format is translated to a list of initializers here which is later processed
147/// during "inlining" to produce a final component with the final set of
148/// initializers.
149#[derive(Default)]
150struct Translation<'data> {
151    /// Instructions which form this component.
152    ///
153    /// There is one initializer for all members of each index space, and all
154    /// index spaces are incrementally built here as the initializer list is
155    /// processed.
156    initializers: Vec<LocalInitializer<'data>>,
157
158    /// The list of exports from this component, as pairs of names and an
159    /// index into an index space of what's being exported.
160    exports: IndexMap<&'data str, ComponentItem>,
161
162    /// Type information produced by `wasmparser` for this component.
163    ///
164    /// This type information is available after the translation of the entire
165    /// component has finished, e.g. for the `inline` pass, but beforehand this
166    /// is set to `None`.
167    types: Option<Types>,
168}
169
170// NB: the type information contained in `LocalInitializer` should always point
171// to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
172// fully determined due to resources until instantiations are known which is
173// tracked during the inlining phase. This means that all type information below
174// is straight from `wasmparser`'s passes.
175enum LocalInitializer<'data> {
176    // imports
177    Import(ComponentImportName<'data>, ComponentEntityType),
178
179    // canonical function sections
180    Lower {
181        func: ComponentFuncIndex,
182        lower_ty: ComponentFuncTypeId,
183        options: LocalCanonicalOptions,
184    },
185    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
186
187    // resources
188    Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
189    ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
190    ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
191    ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
192
193    BackpressureSet {
194        func: ModuleInternedTypeIndex,
195    },
196    TaskReturn {
197        result: Option<ComponentValType>,
198        options: LocalCanonicalOptions,
199    },
200    TaskCancel {
201        func: ModuleInternedTypeIndex,
202    },
203    WaitableSetNew {
204        func: ModuleInternedTypeIndex,
205    },
206    WaitableSetWait {
207        func: ModuleInternedTypeIndex,
208        async_: bool,
209        memory: MemoryIndex,
210    },
211    WaitableSetPoll {
212        func: ModuleInternedTypeIndex,
213        async_: bool,
214        memory: MemoryIndex,
215    },
216    WaitableSetDrop {
217        func: ModuleInternedTypeIndex,
218    },
219    WaitableJoin {
220        func: ModuleInternedTypeIndex,
221    },
222    Yield {
223        func: ModuleInternedTypeIndex,
224        async_: bool,
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
311    // core wasm modules
312    ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
313
314    // core wasm module instances
315    ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
316    ModuleSynthetic(HashMap<&'data str, EntityIndex>),
317
318    // components
319    ComponentStatic(StaticComponentIndex, ClosedOverVars),
320
321    // component instances
322    ComponentInstantiate(
323        ComponentIndex,
324        HashMap<&'data str, ComponentItem>,
325        ComponentInstanceTypeId,
326    ),
327    ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
328
329    // alias section
330    AliasExportFunc(ModuleInstanceIndex, &'data str),
331    AliasExportTable(ModuleInstanceIndex, &'data str),
332    AliasExportGlobal(ModuleInstanceIndex, &'data str),
333    AliasExportMemory(ModuleInstanceIndex, &'data str),
334    AliasExportTag(ModuleInstanceIndex, &'data str),
335    AliasComponentExport(ComponentInstanceIndex, &'data str),
336    AliasModule(ClosedOverModule),
337    AliasComponent(ClosedOverComponent),
338
339    // export section
340    Export(ComponentItem),
341}
342
343/// The "closure environment" of components themselves.
344///
345/// For more information see `LexicalScope`.
346#[derive(Default)]
347struct ClosedOverVars {
348    components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
349    modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
350}
351
352/// Description how a component is closed over when the closure variables for
353/// a component are being created.
354///
355/// For more information see `LexicalScope`.
356enum ClosedOverComponent {
357    /// A closed over component is coming from the local component's index
358    /// space, meaning a previously defined component is being captured.
359    Local(ComponentIndex),
360    /// A closed over component is coming from our own component's list of
361    /// upvars. This list was passed to us by our enclosing component, which
362    /// will eventually have bottomed out in closing over a `Local` component
363    /// index for some parent component.
364    Upvar(ComponentUpvarIndex),
365}
366
367/// Same as `ClosedOverComponent`, but for modules.
368enum ClosedOverModule {
369    Local(ModuleIndex),
370    Upvar(ModuleUpvarIndex),
371}
372
373/// The data model for objects that are not unboxed in locals.
374#[derive(Debug, Clone, Hash, Eq, PartialEq)]
375pub enum LocalDataModel {
376    /// Data is stored in GC objects.
377    Gc {},
378
379    /// Data is stored in a linear memory.
380    LinearMemory {
381        /// An optional memory definition supplied.
382        memory: Option<MemoryIndex>,
383        /// An optional definition of `realloc` to used.
384        realloc: Option<FuncIndex>,
385    },
386}
387
388/// Representation of canonical ABI options.
389struct LocalCanonicalOptions {
390    string_encoding: StringEncoding,
391    post_return: Option<FuncIndex>,
392    async_: bool,
393    callback: Option<FuncIndex>,
394    /// The type index of the core GC types signature.
395    core_type: ModuleInternedTypeIndex,
396    data_model: LocalDataModel,
397}
398
399enum Action {
400    KeepGoing,
401    Skip(usize),
402    Done,
403}
404
405impl<'a, 'data> Translator<'a, 'data> {
406    /// Creates a new translation state ready to translate a component.
407    pub fn new(
408        tunables: &'a Tunables,
409        validator: &'a mut Validator,
410        types: &'a mut ComponentTypesBuilder,
411        scope_vec: &'data ScopeVec<u8>,
412    ) -> Self {
413        let mut parser = Parser::new(0);
414        parser.set_features(*validator.features());
415        Self {
416            result: Translation::default(),
417            tunables,
418            validator,
419            types: PreInliningComponentTypes::new(types),
420            parser,
421            lexical_scopes: Vec::new(),
422            static_components: Default::default(),
423            static_modules: Default::default(),
424            scope_vec,
425        }
426    }
427
428    /// Translates the binary `component`.
429    ///
430    /// This is the workhorse of compilation which will parse all of
431    /// `component` and create type information for Wasmtime and such. The
432    /// `component` does not have to be valid and it will be validated during
433    /// compilation.
434    ///
435    /// The result of this function is a tuple of the final component's
436    /// description plus a list of core wasm modules found within the
437    /// component. The component's description actually erases internal
438    /// components, instances, etc, as much as it can. Instead `Component`
439    /// retains a flat list of initializers (no nesting) which was created
440    /// as part of compilation from the nested structure of the original
441    /// component.
442    ///
443    /// The list of core wasm modules found is provided to allow compiling
444    /// modules externally in parallel. Additionally initializers in
445    /// `Component` may refer to the modules in the map returned by index.
446    ///
447    /// # Errors
448    ///
449    /// This function will return an error if the `component` provided is
450    /// invalid.
451    pub fn translate(
452        mut self,
453        component: &'data [u8],
454    ) -> Result<(
455        ComponentTranslation,
456        PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
457    )> {
458        // First up wasmparser is used to actually perform the translation and
459        // validation of this component. This will produce a list of core wasm
460        // modules in addition to components which are found during the
461        // translation process. When doing this only a `Translation` is created
462        // which is a simple representation of a component.
463        let mut remaining = component;
464        loop {
465            let payload = match self.parser.parse(remaining, true)? {
466                Chunk::Parsed { payload, consumed } => {
467                    remaining = &remaining[consumed..];
468                    payload
469                }
470                Chunk::NeedMoreData(_) => unreachable!(),
471            };
472
473            match self.translate_payload(payload, component)? {
474                Action::KeepGoing => {}
475                Action::Skip(n) => remaining = &remaining[n..],
476                Action::Done => break,
477            }
478        }
479        assert!(remaining.is_empty());
480        assert!(self.lexical_scopes.is_empty());
481
482        // ... after translation initially finishes the next pass is performed
483        // which we're calling "inlining". This will "instantiate" the root
484        // component, following nested component instantiations, creating a
485        // global list of initializers along the way. This phase uses the simple
486        // initializers in each component to track dataflow of host imports and
487        // internal references to items throughout a component at compile-time.
488        // The produce initializers in the final `Component` are intended to be
489        // much simpler than the original component and more efficient for
490        // Wasmtime to process at runtime as well (e.g. no string lookups as
491        // most everything is done through indices instead).
492        let mut component = inline::run(
493            self.types.types_mut_for_inlining(),
494            &self.result,
495            &self.static_modules,
496            &self.static_components,
497        )?;
498
499        self.partition_adapter_modules(&mut component);
500
501        let translation =
502            component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
503
504        self.analyze_function_imports(&translation);
505
506        Ok((translation, self.static_modules))
507    }
508
509    fn analyze_function_imports(&mut self, translation: &ComponentTranslation) {
510        // First, abstract interpret the initializers to create a map from each
511        // static module to its abstract set of instantiations.
512        let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
513        let mut instance_to_module =
514            PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new();
515        for init in &translation.component.initializers {
516            match init {
517                GlobalInitializer::InstantiateModule(instantiation) => match instantiation {
518                    InstantiateModule::Static(module, args) => {
519                        instantiations[*module].join(AbstractInstantiations::One(&*args));
520                        instance_to_module.push(Some(*module).into());
521                    }
522                    _ => {
523                        instance_to_module.push(None.into());
524                    }
525                },
526                _ => continue,
527            }
528        }
529
530        // Second, make sure to mark exported modules as instantiated many
531        // times, since they could be linked with who-knows-what at runtime.
532        for item in translation.component.export_items.values() {
533            if let Export::ModuleStatic { index, .. } = item {
534                instantiations[*index].join(AbstractInstantiations::Many)
535            }
536        }
537
538        // Finally, iterate over our instantiations and record statically-known
539        // function imports so that they can get translated into direct calls
540        // (and eventually get inlined) rather than indirect calls through the
541        // imports table.
542        for (module, instantiations) in instantiations.iter() {
543            let args = match instantiations {
544                dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
545                dfg::AbstractInstantiations::One(args) => args,
546            };
547
548            let mut imported_func_counter = 0_u32;
549            for (i, arg) in args.iter().enumerate() {
550                // Only consider function imports.
551                let (_, _, crate::types::EntityType::Function(_)) =
552                    self.static_modules[module].module.import(i).unwrap()
553                else {
554                    continue;
555                };
556
557                let imported_func = FuncIndex::from_u32(imported_func_counter);
558                imported_func_counter += 1;
559                debug_assert!(
560                    self.static_modules[module]
561                        .module
562                        .defined_func_index(imported_func)
563                        .is_none()
564                );
565
566                match arg {
567                    CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"),
568
569                    // We could in theory inline these trampolines, so it could
570                    // potentially make sense to record that we know this
571                    // imported function is this particular trampoline. However,
572                    // everything else is based around (module,
573                    // defined-function) pairs and these trampolines don't fit
574                    // that paradigm. Also, inlining trampolines gets really
575                    // tricky when we consider the stack pointer, frame pointer,
576                    // and return address note-taking that they do for the
577                    // purposes of stack walking. We could, with enough effort,
578                    // turn them into direct calls even though we probably
579                    // wouldn't ever inline them, but it just doesn't seem worth
580                    // the effort.
581                    CoreDef::Trampoline(_) => continue,
582
583                    // This imported function is an export from another
584                    // instance, a perfect candidate for becoming an inlinable
585                    // direct call!
586                    CoreDef::Export(export) => {
587                        let Some(arg_module) = &instance_to_module[export.instance].expand() else {
588                            // Instance of a dynamic module that is not part of
589                            // this component, not a statically-known module
590                            // inside this component. We have to do an indirect
591                            // call.
592                            continue;
593                        };
594
595                        let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
596                        else {
597                            unreachable!("function imports must be functions")
598                        };
599
600                        let Some(arg_module_def_func) = self.static_modules[*arg_module]
601                            .module
602                            .defined_func_index(*arg_func)
603                        else {
604                            // TODO: we should ideally follow re-export chains
605                            // to bottom out the instantiation argument in
606                            // either a definition or an import at the root
607                            // component boundary. In practice, this pattern is
608                            // rare, so following these chains is left for the
609                            // Future.
610                            continue;
611                        };
612
613                        assert!(
614                            self.static_modules[module].known_imported_functions[imported_func]
615                                .is_none()
616                        );
617                        self.static_modules[module].known_imported_functions[imported_func] =
618                            Some((*arg_module, arg_module_def_func));
619                    }
620                }
621            }
622        }
623    }
624
625    fn translate_payload(
626        &mut self,
627        payload: Payload<'data>,
628        component: &'data [u8],
629    ) -> Result<Action> {
630        match payload {
631            Payload::Version {
632                num,
633                encoding,
634                range,
635            } => {
636                self.validator.version(num, encoding, &range)?;
637
638                match encoding {
639                    Encoding::Component => {}
640                    Encoding::Module => {
641                        bail!("attempted to parse a wasm module with a component parser");
642                    }
643                }
644            }
645
646            Payload::End(offset) => {
647                assert!(self.result.types.is_none());
648                self.result.types = Some(self.validator.end(offset)?);
649
650                // Exit the current lexical scope. If there is no parent (no
651                // frame currently on the stack) then translation is finished.
652                // Otherwise that means that a nested component has been
653                // completed and is recorded as such.
654                let LexicalScope {
655                    parser,
656                    translation,
657                    closure_args,
658                } = match self.lexical_scopes.pop() {
659                    Some(frame) => frame,
660                    None => return Ok(Action::Done),
661                };
662                self.parser = parser;
663                let component = mem::replace(&mut self.result, translation);
664                let static_idx = self.static_components.push(component);
665                self.result
666                    .initializers
667                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
668            }
669
670            // When we see a type section the types are validated and then
671            // translated into Wasmtime's representation. Each active type
672            // definition is recorded in the `ComponentTypesBuilder` tables, or
673            // this component's active scope.
674            //
675            // Note that the push/pop of the component types scope happens above
676            // in `Version` and `End` since multiple type sections can appear
677            // within a component.
678            Payload::ComponentTypeSection(s) => {
679                let mut component_type_index =
680                    self.validator.types(0).unwrap().component_type_count();
681                self.validator.component_type_section(&s)?;
682
683                // Look for resource types and if a local resource is defined
684                // then an initializer is added to define that resource type and
685                // reference its destructor.
686                let types = self.validator.types(0).unwrap();
687                for ty in s {
688                    match ty? {
689                        wasmparser::ComponentType::Resource { rep, dtor } => {
690                            let rep = self.types.convert_valtype(rep)?;
691                            let id = types
692                                .component_any_type_at(component_type_index)
693                                .unwrap_resource();
694                            let dtor = dtor.map(FuncIndex::from_u32);
695                            self.result
696                                .initializers
697                                .push(LocalInitializer::Resource(id, rep, dtor));
698                        }
699
700                        // no extra processing needed
701                        wasmparser::ComponentType::Defined(_)
702                        | wasmparser::ComponentType::Func(_)
703                        | wasmparser::ComponentType::Instance(_)
704                        | wasmparser::ComponentType::Component(_) => {}
705                    }
706
707                    component_type_index += 1;
708                }
709            }
710            Payload::CoreTypeSection(s) => {
711                self.validator.core_type_section(&s)?;
712            }
713
714            // Processing the import section at this point is relatively simple
715            // which is to simply record the name of the import and the type
716            // information associated with it.
717            Payload::ComponentImportSection(s) => {
718                self.validator.component_import_section(&s)?;
719                for import in s {
720                    let import = import?;
721                    let types = self.validator.types(0).unwrap();
722                    let ty = types
723                        .component_entity_type_of_import(import.name.0)
724                        .unwrap();
725                    self.result
726                        .initializers
727                        .push(LocalInitializer::Import(import.name, ty));
728                }
729            }
730
731            // Entries in the canonical section will get initializers recorded
732            // with the listed options for lifting/lowering.
733            Payload::ComponentCanonicalSection(s) => {
734                let types = self.validator.types(0).unwrap();
735                let mut core_func_index = types.function_count();
736                self.validator.component_canonical_section(&s)?;
737                for func in s {
738                    let init = match func? {
739                        wasmparser::CanonicalFunction::Lift {
740                            type_index,
741                            core_func_index,
742                            options,
743                        } => {
744                            let ty = self
745                                .validator
746                                .types(0)
747                                .unwrap()
748                                .component_any_type_at(type_index)
749                                .unwrap_func();
750
751                            let func = FuncIndex::from_u32(core_func_index);
752                            let options = self.canonical_options(&options, core_func_index)?;
753                            LocalInitializer::Lift(ty, func, options)
754                        }
755                        wasmparser::CanonicalFunction::Lower {
756                            func_index,
757                            options,
758                        } => {
759                            let lower_ty = self
760                                .validator
761                                .types(0)
762                                .unwrap()
763                                .component_function_at(func_index);
764                            let func = ComponentFuncIndex::from_u32(func_index);
765                            let options = self.canonical_options(&options, core_func_index)?;
766                            core_func_index += 1;
767                            LocalInitializer::Lower {
768                                func,
769                                options,
770                                lower_ty,
771                            }
772                        }
773                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
774                            let resource = self
775                                .validator
776                                .types(0)
777                                .unwrap()
778                                .component_any_type_at(resource)
779                                .unwrap_resource();
780                            let ty = self.core_func_signature(core_func_index)?;
781                            core_func_index += 1;
782                            LocalInitializer::ResourceNew(resource, ty)
783                        }
784                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
785                            let resource = self
786                                .validator
787                                .types(0)
788                                .unwrap()
789                                .component_any_type_at(resource)
790                                .unwrap_resource();
791                            let ty = self.core_func_signature(core_func_index)?;
792                            core_func_index += 1;
793                            LocalInitializer::ResourceDrop(resource, ty)
794                        }
795                        wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
796                            let _ = resource;
797                            bail!("support for `resource.drop async` not implemented yet")
798                        }
799                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
800                            let resource = self
801                                .validator
802                                .types(0)
803                                .unwrap()
804                                .component_any_type_at(resource)
805                                .unwrap_resource();
806                            let ty = self.core_func_signature(core_func_index)?;
807                            core_func_index += 1;
808                            LocalInitializer::ResourceRep(resource, ty)
809                        }
810                        wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
811                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
812                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
813                            bail!("unsupported intrinsic")
814                        }
815                        wasmparser::CanonicalFunction::BackpressureSet => {
816                            let core_type = self.core_func_signature(core_func_index)?;
817                            core_func_index += 1;
818                            LocalInitializer::BackpressureSet { func: core_type }
819                        }
820                        wasmparser::CanonicalFunction::TaskReturn { result, options } => {
821                            let result = result.map(|ty| match ty {
822                                wasmparser::ComponentValType::Primitive(ty) => {
823                                    ComponentValType::Primitive(ty)
824                                }
825                                wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
826                                    self.validator
827                                        .types(0)
828                                        .unwrap()
829                                        .component_defined_type_at(ty),
830                                ),
831                            });
832                            let options = self.canonical_options(&options, core_func_index)?;
833                            core_func_index += 1;
834                            LocalInitializer::TaskReturn { result, options }
835                        }
836                        wasmparser::CanonicalFunction::TaskCancel => {
837                            let func = self.core_func_signature(core_func_index)?;
838                            core_func_index += 1;
839                            LocalInitializer::TaskCancel { func }
840                        }
841                        wasmparser::CanonicalFunction::WaitableSetNew => {
842                            let func = self.core_func_signature(core_func_index)?;
843                            core_func_index += 1;
844                            LocalInitializer::WaitableSetNew { func }
845                        }
846                        wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
847                            let func = self.core_func_signature(core_func_index)?;
848                            core_func_index += 1;
849                            LocalInitializer::WaitableSetWait {
850                                func,
851                                async_,
852                                memory: MemoryIndex::from_u32(memory),
853                            }
854                        }
855                        wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
856                            let func = self.core_func_signature(core_func_index)?;
857                            core_func_index += 1;
858                            LocalInitializer::WaitableSetPoll {
859                                func,
860                                async_,
861                                memory: MemoryIndex::from_u32(memory),
862                            }
863                        }
864                        wasmparser::CanonicalFunction::WaitableSetDrop => {
865                            let func = self.core_func_signature(core_func_index)?;
866                            core_func_index += 1;
867                            LocalInitializer::WaitableSetDrop { func }
868                        }
869                        wasmparser::CanonicalFunction::WaitableJoin => {
870                            let func = self.core_func_signature(core_func_index)?;
871                            core_func_index += 1;
872                            LocalInitializer::WaitableJoin { func }
873                        }
874                        wasmparser::CanonicalFunction::Yield { async_ } => {
875                            let func = self.core_func_signature(core_func_index)?;
876                            core_func_index += 1;
877                            LocalInitializer::Yield { func, async_ }
878                        }
879                        wasmparser::CanonicalFunction::SubtaskDrop => {
880                            let func = self.core_func_signature(core_func_index)?;
881                            core_func_index += 1;
882                            LocalInitializer::SubtaskDrop { func }
883                        }
884                        wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
885                            let func = self.core_func_signature(core_func_index)?;
886                            core_func_index += 1;
887                            LocalInitializer::SubtaskCancel { func, async_ }
888                        }
889                        wasmparser::CanonicalFunction::StreamNew { ty } => {
890                            let ty = self
891                                .validator
892                                .types(0)
893                                .unwrap()
894                                .component_defined_type_at(ty);
895                            let func = self.core_func_signature(core_func_index)?;
896                            core_func_index += 1;
897                            LocalInitializer::StreamNew { ty, func }
898                        }
899                        wasmparser::CanonicalFunction::StreamRead { ty, options } => {
900                            let ty = self
901                                .validator
902                                .types(0)
903                                .unwrap()
904                                .component_defined_type_at(ty);
905                            let options = self.canonical_options(&options, core_func_index)?;
906                            core_func_index += 1;
907                            LocalInitializer::StreamRead { ty, options }
908                        }
909                        wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
910                            let ty = self
911                                .validator
912                                .types(0)
913                                .unwrap()
914                                .component_defined_type_at(ty);
915                            let options = self.canonical_options(&options, core_func_index)?;
916                            core_func_index += 1;
917                            LocalInitializer::StreamWrite { ty, options }
918                        }
919                        wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
920                            let ty = self
921                                .validator
922                                .types(0)
923                                .unwrap()
924                                .component_defined_type_at(ty);
925                            let func = self.core_func_signature(core_func_index)?;
926                            core_func_index += 1;
927                            LocalInitializer::StreamCancelRead { ty, func, async_ }
928                        }
929                        wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
930                            let ty = self
931                                .validator
932                                .types(0)
933                                .unwrap()
934                                .component_defined_type_at(ty);
935                            let func = self.core_func_signature(core_func_index)?;
936                            core_func_index += 1;
937                            LocalInitializer::StreamCancelWrite { ty, func, async_ }
938                        }
939                        wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
940                            let ty = self
941                                .validator
942                                .types(0)
943                                .unwrap()
944                                .component_defined_type_at(ty);
945                            let func = self.core_func_signature(core_func_index)?;
946                            core_func_index += 1;
947                            LocalInitializer::StreamDropReadable { ty, func }
948                        }
949                        wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
950                            let ty = self
951                                .validator
952                                .types(0)
953                                .unwrap()
954                                .component_defined_type_at(ty);
955                            let func = self.core_func_signature(core_func_index)?;
956                            core_func_index += 1;
957                            LocalInitializer::StreamDropWritable { ty, func }
958                        }
959                        wasmparser::CanonicalFunction::FutureNew { ty } => {
960                            let ty = self
961                                .validator
962                                .types(0)
963                                .unwrap()
964                                .component_defined_type_at(ty);
965                            let func = self.core_func_signature(core_func_index)?;
966                            core_func_index += 1;
967                            LocalInitializer::FutureNew { ty, func }
968                        }
969                        wasmparser::CanonicalFunction::FutureRead { ty, options } => {
970                            let ty = self
971                                .validator
972                                .types(0)
973                                .unwrap()
974                                .component_defined_type_at(ty);
975                            let options = self.canonical_options(&options, core_func_index)?;
976                            core_func_index += 1;
977                            LocalInitializer::FutureRead { ty, options }
978                        }
979                        wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
980                            let ty = self
981                                .validator
982                                .types(0)
983                                .unwrap()
984                                .component_defined_type_at(ty);
985                            let options = self.canonical_options(&options, core_func_index)?;
986                            core_func_index += 1;
987                            LocalInitializer::FutureWrite { ty, options }
988                        }
989                        wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
990                            let ty = self
991                                .validator
992                                .types(0)
993                                .unwrap()
994                                .component_defined_type_at(ty);
995                            let func = self.core_func_signature(core_func_index)?;
996                            core_func_index += 1;
997                            LocalInitializer::FutureCancelRead { ty, func, async_ }
998                        }
999                        wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1000                            let ty = self
1001                                .validator
1002                                .types(0)
1003                                .unwrap()
1004                                .component_defined_type_at(ty);
1005                            let func = self.core_func_signature(core_func_index)?;
1006                            core_func_index += 1;
1007                            LocalInitializer::FutureCancelWrite { ty, func, async_ }
1008                        }
1009                        wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1010                            let ty = self
1011                                .validator
1012                                .types(0)
1013                                .unwrap()
1014                                .component_defined_type_at(ty);
1015                            let func = self.core_func_signature(core_func_index)?;
1016                            core_func_index += 1;
1017                            LocalInitializer::FutureDropReadable { ty, func }
1018                        }
1019                        wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1020                            let ty = self
1021                                .validator
1022                                .types(0)
1023                                .unwrap()
1024                                .component_defined_type_at(ty);
1025                            let func = self.core_func_signature(core_func_index)?;
1026                            core_func_index += 1;
1027                            LocalInitializer::FutureDropWritable { ty, func }
1028                        }
1029                        wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1030                            let options = self.canonical_options(&options, core_func_index)?;
1031                            core_func_index += 1;
1032                            LocalInitializer::ErrorContextNew { options }
1033                        }
1034                        wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1035                            let options = self.canonical_options(&options, core_func_index)?;
1036                            core_func_index += 1;
1037                            LocalInitializer::ErrorContextDebugMessage { options }
1038                        }
1039                        wasmparser::CanonicalFunction::ErrorContextDrop => {
1040                            let func = self.core_func_signature(core_func_index)?;
1041                            core_func_index += 1;
1042                            LocalInitializer::ErrorContextDrop { func }
1043                        }
1044                        wasmparser::CanonicalFunction::ContextGet(i) => {
1045                            let func = self.core_func_signature(core_func_index)?;
1046                            core_func_index += 1;
1047                            LocalInitializer::ContextGet { i, func }
1048                        }
1049                        wasmparser::CanonicalFunction::ContextSet(i) => {
1050                            let func = self.core_func_signature(core_func_index)?;
1051                            core_func_index += 1;
1052                            LocalInitializer::ContextSet { i, func }
1053                        }
1054                    };
1055                    self.result.initializers.push(init);
1056                }
1057            }
1058
1059            // Core wasm modules are translated inline directly here with the
1060            // `ModuleEnvironment` from core wasm compilation. This will return
1061            // to the caller the size of the module so it knows how many bytes
1062            // of the input are skipped.
1063            //
1064            // Note that this is just initial type translation of the core wasm
1065            // module and actual function compilation is deferred until this
1066            // entire process has completed.
1067            Payload::ModuleSection {
1068                parser,
1069                unchecked_range,
1070            } => {
1071                let index = self.validator.types(0).unwrap().module_count();
1072                self.validator.module_section(&unchecked_range)?;
1073                let translation = ModuleEnvironment::new(
1074                    self.tunables,
1075                    self.validator,
1076                    self.types.module_types_builder(),
1077                )
1078                .translate(
1079                    parser,
1080                    component
1081                        .get(unchecked_range.start..unchecked_range.end)
1082                        .ok_or_else(|| {
1083                            anyhow!(
1084                                "section range {}..{} is out of bounds (bound = {})",
1085                                unchecked_range.start,
1086                                unchecked_range.end,
1087                                component.len()
1088                            )
1089                            .context("wasm component contains an invalid module section")
1090                        })?,
1091                )?;
1092                let static_idx = self.static_modules.push(translation);
1093                let types = self.validator.types(0).unwrap();
1094                let ty = types.module_at(index);
1095                self.result
1096                    .initializers
1097                    .push(LocalInitializer::ModuleStatic(static_idx, ty));
1098                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1099            }
1100
1101            // When a sub-component is found then the current translation state
1102            // is pushed onto the `lexical_scopes` stack. This will subsequently
1103            // get popped as part of `Payload::End` processing above.
1104            //
1105            // Note that the set of closure args for this new lexical scope
1106            // starts empty since it will only get populated if translation of
1107            // the nested component ends up aliasing some outer module or
1108            // component.
1109            Payload::ComponentSection {
1110                parser,
1111                unchecked_range,
1112            } => {
1113                self.validator.component_section(&unchecked_range)?;
1114                self.lexical_scopes.push(LexicalScope {
1115                    parser: mem::replace(&mut self.parser, parser),
1116                    translation: mem::take(&mut self.result),
1117                    closure_args: ClosedOverVars::default(),
1118                });
1119            }
1120
1121            // Both core wasm instances and component instances record
1122            // initializers of what form of instantiation is performed which
1123            // largely just records the arguments given from wasmparser into a
1124            // `HashMap` for processing later during inlining.
1125            Payload::InstanceSection(s) => {
1126                self.validator.instance_section(&s)?;
1127                for instance in s {
1128                    let init = match instance? {
1129                        wasmparser::Instance::Instantiate { module_index, args } => {
1130                            let index = ModuleIndex::from_u32(module_index);
1131                            self.instantiate_module(index, &args)
1132                        }
1133                        wasmparser::Instance::FromExports(exports) => {
1134                            self.instantiate_module_from_exports(&exports)
1135                        }
1136                    };
1137                    self.result.initializers.push(init);
1138                }
1139            }
1140            Payload::ComponentInstanceSection(s) => {
1141                let mut index = self.validator.types(0).unwrap().component_instance_count();
1142                self.validator.component_instance_section(&s)?;
1143                for instance in s {
1144                    let types = self.validator.types(0).unwrap();
1145                    let ty = types.component_instance_at(index);
1146                    let init = match instance? {
1147                        wasmparser::ComponentInstance::Instantiate {
1148                            component_index,
1149                            args,
1150                        } => {
1151                            let index = ComponentIndex::from_u32(component_index);
1152                            self.instantiate_component(index, &args, ty)?
1153                        }
1154                        wasmparser::ComponentInstance::FromExports(exports) => {
1155                            self.instantiate_component_from_exports(&exports, ty)?
1156                        }
1157                    };
1158                    self.result.initializers.push(init);
1159                    index += 1;
1160                }
1161            }
1162
1163            // Exports don't actually fill out the `initializers` array but
1164            // instead fill out the one other field in a `Translation`, the
1165            // `exports` field (as one might imagine). This for now simply
1166            // records the index of what's exported and that's tracked further
1167            // later during inlining.
1168            Payload::ComponentExportSection(s) => {
1169                self.validator.component_export_section(&s)?;
1170                for export in s {
1171                    let export = export?;
1172                    let item = self.kind_to_item(export.kind, export.index)?;
1173                    let prev = self.result.exports.insert(export.name.0, item);
1174                    assert!(prev.is_none());
1175                    self.result
1176                        .initializers
1177                        .push(LocalInitializer::Export(item));
1178                }
1179            }
1180
1181            Payload::ComponentStartSection { start, range } => {
1182                self.validator.component_start_section(&start, &range)?;
1183                unimplemented!("component start section");
1184            }
1185
1186            // Aliases of instance exports (either core or component) will be
1187            // recorded as an initializer of the appropriate type with outer
1188            // aliases handled specially via upvars and type processing.
1189            Payload::ComponentAliasSection(s) => {
1190                self.validator.component_alias_section(&s)?;
1191                for alias in s {
1192                    let init = match alias? {
1193                        wasmparser::ComponentAlias::InstanceExport {
1194                            kind: _,
1195                            instance_index,
1196                            name,
1197                        } => {
1198                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1199                            LocalInitializer::AliasComponentExport(instance, name)
1200                        }
1201                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1202                            self.alias_component_outer(kind, count, index);
1203                            continue;
1204                        }
1205                        wasmparser::ComponentAlias::CoreInstanceExport {
1206                            kind,
1207                            instance_index,
1208                            name,
1209                        } => {
1210                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1211                            self.alias_module_instance_export(kind, instance, name)
1212                        }
1213                    };
1214                    self.result.initializers.push(init);
1215                }
1216            }
1217
1218            // All custom sections are ignored by Wasmtime at this time.
1219            //
1220            // FIXME(WebAssembly/component-model#14): probably want to specify
1221            // and parse a `name` section here.
1222            Payload::CustomSection { .. } => {}
1223
1224            // Anything else is either not reachable since we never enable the
1225            // feature in Wasmtime or we do enable it and it's a bug we don't
1226            // implement it, so let validation take care of most errors here and
1227            // if it gets past validation provide a helpful error message to
1228            // debug.
1229            other => {
1230                self.validator.payload(&other)?;
1231                panic!("unimplemented section {other:?}");
1232            }
1233        }
1234
1235        Ok(Action::KeepGoing)
1236    }
1237
1238    fn instantiate_module(
1239        &mut self,
1240        module: ModuleIndex,
1241        raw_args: &[wasmparser::InstantiationArg<'data>],
1242    ) -> LocalInitializer<'data> {
1243        let mut args = HashMap::with_capacity(raw_args.len());
1244        for arg in raw_args {
1245            match arg.kind {
1246                wasmparser::InstantiationArgKind::Instance => {
1247                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1248                    args.insert(arg.name, idx);
1249                }
1250            }
1251        }
1252        LocalInitializer::ModuleInstantiate(module, args)
1253    }
1254
1255    /// Creates a synthetic module from the list of items currently in the
1256    /// module and their given names.
1257    fn instantiate_module_from_exports(
1258        &mut self,
1259        exports: &[wasmparser::Export<'data>],
1260    ) -> LocalInitializer<'data> {
1261        let mut map = HashMap::with_capacity(exports.len());
1262        for export in exports {
1263            let idx = match export.kind {
1264                wasmparser::ExternalKind::Func => {
1265                    let index = FuncIndex::from_u32(export.index);
1266                    EntityIndex::Function(index)
1267                }
1268                wasmparser::ExternalKind::Table => {
1269                    let index = TableIndex::from_u32(export.index);
1270                    EntityIndex::Table(index)
1271                }
1272                wasmparser::ExternalKind::Memory => {
1273                    let index = MemoryIndex::from_u32(export.index);
1274                    EntityIndex::Memory(index)
1275                }
1276                wasmparser::ExternalKind::Global => {
1277                    let index = GlobalIndex::from_u32(export.index);
1278                    EntityIndex::Global(index)
1279                }
1280                wasmparser::ExternalKind::Tag => {
1281                    let index = TagIndex::from_u32(export.index);
1282                    EntityIndex::Tag(index)
1283                }
1284            };
1285            map.insert(export.name, idx);
1286        }
1287        LocalInitializer::ModuleSynthetic(map)
1288    }
1289
1290    fn instantiate_component(
1291        &mut self,
1292        component: ComponentIndex,
1293        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1294        ty: ComponentInstanceTypeId,
1295    ) -> Result<LocalInitializer<'data>> {
1296        let mut args = HashMap::with_capacity(raw_args.len());
1297        for arg in raw_args {
1298            let idx = self.kind_to_item(arg.kind, arg.index)?;
1299            args.insert(arg.name, idx);
1300        }
1301
1302        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1303    }
1304
1305    /// Creates a synthetic module from the list of items currently in the
1306    /// module and their given names.
1307    fn instantiate_component_from_exports(
1308        &mut self,
1309        exports: &[wasmparser::ComponentExport<'data>],
1310        ty: ComponentInstanceTypeId,
1311    ) -> Result<LocalInitializer<'data>> {
1312        let mut map = HashMap::with_capacity(exports.len());
1313        for export in exports {
1314            let idx = self.kind_to_item(export.kind, export.index)?;
1315            map.insert(export.name.0, idx);
1316        }
1317
1318        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1319    }
1320
1321    fn kind_to_item(
1322        &mut self,
1323        kind: wasmparser::ComponentExternalKind,
1324        index: u32,
1325    ) -> Result<ComponentItem> {
1326        Ok(match kind {
1327            wasmparser::ComponentExternalKind::Func => {
1328                let index = ComponentFuncIndex::from_u32(index);
1329                ComponentItem::Func(index)
1330            }
1331            wasmparser::ComponentExternalKind::Module => {
1332                let index = ModuleIndex::from_u32(index);
1333                ComponentItem::Module(index)
1334            }
1335            wasmparser::ComponentExternalKind::Instance => {
1336                let index = ComponentInstanceIndex::from_u32(index);
1337                ComponentItem::ComponentInstance(index)
1338            }
1339            wasmparser::ComponentExternalKind::Component => {
1340                let index = ComponentIndex::from_u32(index);
1341                ComponentItem::Component(index)
1342            }
1343            wasmparser::ComponentExternalKind::Value => {
1344                unimplemented!("component values");
1345            }
1346            wasmparser::ComponentExternalKind::Type => {
1347                let types = self.validator.types(0).unwrap();
1348                let ty = types.component_any_type_at(index);
1349                ComponentItem::Type(ty)
1350            }
1351        })
1352    }
1353
1354    fn alias_module_instance_export(
1355        &mut self,
1356        kind: wasmparser::ExternalKind,
1357        instance: ModuleInstanceIndex,
1358        name: &'data str,
1359    ) -> LocalInitializer<'data> {
1360        match kind {
1361            wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1362            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1363            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1364            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1365            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1366        }
1367    }
1368
1369    fn alias_component_outer(
1370        &mut self,
1371        kind: wasmparser::ComponentOuterAliasKind,
1372        count: u32,
1373        index: u32,
1374    ) {
1375        match kind {
1376            wasmparser::ComponentOuterAliasKind::CoreType
1377            | wasmparser::ComponentOuterAliasKind::Type => {}
1378
1379            // For more information about the implementation of outer aliases
1380            // see the documentation of `LexicalScope`. Otherwise though the
1381            // main idea here is that the data to close over starts as `Local`
1382            // and then transitions to `Upvar` as its inserted into the parents
1383            // in order from target we're aliasing back to the current
1384            // component.
1385            wasmparser::ComponentOuterAliasKind::CoreModule => {
1386                let index = ModuleIndex::from_u32(index);
1387                let mut module = ClosedOverModule::Local(index);
1388                let depth = self.lexical_scopes.len() - (count as usize);
1389                for frame in self.lexical_scopes[depth..].iter_mut() {
1390                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1391                }
1392
1393                // If the `module` is still `Local` then the `depth` was 0 and
1394                // it's an alias into our own space. Otherwise it's switched to
1395                // an upvar and will index into the upvar space. Either way
1396                // it's just plumbed directly into the initializer.
1397                self.result
1398                    .initializers
1399                    .push(LocalInitializer::AliasModule(module));
1400            }
1401            wasmparser::ComponentOuterAliasKind::Component => {
1402                let index = ComponentIndex::from_u32(index);
1403                let mut component = ClosedOverComponent::Local(index);
1404                let depth = self.lexical_scopes.len() - (count as usize);
1405                for frame in self.lexical_scopes[depth..].iter_mut() {
1406                    component =
1407                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1408                }
1409
1410                self.result
1411                    .initializers
1412                    .push(LocalInitializer::AliasComponent(component));
1413            }
1414        }
1415    }
1416
1417    fn canonical_options(
1418        &mut self,
1419        opts: &[wasmparser::CanonicalOption],
1420        core_func_index: u32,
1421    ) -> WasmResult<LocalCanonicalOptions> {
1422        let core_type = self.core_func_signature(core_func_index)?;
1423
1424        let mut string_encoding = StringEncoding::Utf8;
1425        let mut post_return = None;
1426        let mut async_ = false;
1427        let mut callback = None;
1428        let mut memory = None;
1429        let mut realloc = None;
1430        let mut gc = false;
1431
1432        for opt in opts {
1433            match opt {
1434                wasmparser::CanonicalOption::UTF8 => {
1435                    string_encoding = StringEncoding::Utf8;
1436                }
1437                wasmparser::CanonicalOption::UTF16 => {
1438                    string_encoding = StringEncoding::Utf16;
1439                }
1440                wasmparser::CanonicalOption::CompactUTF16 => {
1441                    string_encoding = StringEncoding::CompactUtf16;
1442                }
1443                wasmparser::CanonicalOption::Memory(idx) => {
1444                    let idx = MemoryIndex::from_u32(*idx);
1445                    memory = Some(idx);
1446                }
1447                wasmparser::CanonicalOption::Realloc(idx) => {
1448                    let idx = FuncIndex::from_u32(*idx);
1449                    realloc = Some(idx);
1450                }
1451                wasmparser::CanonicalOption::PostReturn(idx) => {
1452                    let idx = FuncIndex::from_u32(*idx);
1453                    post_return = Some(idx);
1454                }
1455                wasmparser::CanonicalOption::Async => async_ = true,
1456                wasmparser::CanonicalOption::Callback(idx) => {
1457                    let idx = FuncIndex::from_u32(*idx);
1458                    callback = Some(idx);
1459                }
1460                wasmparser::CanonicalOption::CoreType(idx) => {
1461                    if cfg!(debug_assertions) {
1462                        let types = self.validator.types(0).unwrap();
1463                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1464                        let interned = self
1465                            .types
1466                            .module_types_builder()
1467                            .intern_type(types, core_ty_id)?;
1468                        debug_assert_eq!(interned, core_type);
1469                    }
1470                }
1471                wasmparser::CanonicalOption::Gc => {
1472                    gc = true;
1473                }
1474            }
1475        }
1476
1477        Ok(LocalCanonicalOptions {
1478            string_encoding,
1479            post_return,
1480            async_,
1481            callback,
1482            core_type,
1483            data_model: if gc {
1484                LocalDataModel::Gc {}
1485            } else {
1486                LocalDataModel::LinearMemory { memory, realloc }
1487            },
1488        })
1489    }
1490
1491    /// Get the interned type index for the `index`th core function.
1492    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1493        let types = self.validator.types(0).unwrap();
1494        let id = types.core_function_at(index);
1495        self.types.module_types_builder().intern_type(types, id)
1496    }
1497}
1498
1499impl Translation<'_> {
1500    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1501        self.types.as_ref().unwrap().as_ref()
1502    }
1503}
1504
1505/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1506/// to disallow access to mutable access to the builder before the inlining
1507/// pass.
1508///
1509/// Type information in this translation pass must be preserved at the
1510/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1511/// own type system. Only during inlining are types fully assigned because
1512/// that's when resource types become available as it's known which instance
1513/// defines which resource, or more concretely the same component instantiated
1514/// twice will produce two unique resource types unlike one as seen by
1515/// wasmparser within the component.
1516mod pre_inlining {
1517    use super::*;
1518
1519    pub struct PreInliningComponentTypes<'a> {
1520        types: &'a mut ComponentTypesBuilder,
1521    }
1522
1523    impl<'a> PreInliningComponentTypes<'a> {
1524        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1525            Self { types }
1526        }
1527
1528        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1529            self.types.module_types_builder_mut()
1530        }
1531
1532        pub fn types(&self) -> &ComponentTypesBuilder {
1533            self.types
1534        }
1535
1536        // NB: this should in theory only be used for the `inline` phase of
1537        // translation.
1538        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1539            self.types
1540        }
1541    }
1542
1543    impl TypeConvert for PreInliningComponentTypes<'_> {
1544        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1545            self.types.lookup_heap_type(index)
1546        }
1547
1548        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1549            self.types.lookup_type_index(index)
1550        }
1551    }
1552}
1553use pre_inlining::PreInliningComponentTypes;