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