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