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