Skip to main content

wasmtime_environ/component/
translate.rs

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