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    ThreadSuspendToSuspended {
323        func: ModuleInternedTypeIndex,
324        cancellable: bool,
325    },
326    ThreadSuspend {
327        func: ModuleInternedTypeIndex,
328        cancellable: bool,
329    },
330    ThreadSuspendTo {
331        func: ModuleInternedTypeIndex,
332        cancellable: bool,
333    },
334    ThreadUnsuspend {
335        func: ModuleInternedTypeIndex,
336    },
337    ThreadYieldToSuspended {
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                    CoreDef::TaskMayBlock => unreachable!("task_may_block is not a function"),
610
611                    // We could in theory inline these trampolines, so it could
612                    // potentially make sense to record that we know this
613                    // imported function is this particular trampoline. However,
614                    // everything else is based around (module,
615                    // defined-function) pairs and these trampolines don't fit
616                    // that paradigm. Also, inlining trampolines gets really
617                    // tricky when we consider the stack pointer, frame pointer,
618                    // and return address note-taking that they do for the
619                    // purposes of stack walking. We could, with enough effort,
620                    // turn them into direct calls even though we probably
621                    // wouldn't ever inline them, but it just doesn't seem worth
622                    // the effort.
623                    CoreDef::Trampoline(_) => continue,
624
625                    // This import is a compile-time builtin intrinsic, we
626                    // should inline its implementation during function
627                    // translation.
628                    CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i),
629
630                    // This imported function is an export from another
631                    // instance, a perfect candidate for becoming an inlinable
632                    // direct call!
633                    CoreDef::Export(export) => {
634                        let Some(arg_module) = &instance_to_module[export.instance].expand() else {
635                            // Instance of a dynamic module that is not part of
636                            // this component, not a statically-known module
637                            // inside this component. We have to do an indirect
638                            // call.
639                            continue;
640                        };
641
642                        let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
643                        else {
644                            unreachable!("function imports must be functions")
645                        };
646
647                        let Some(arg_module_def_func) = self.static_modules[*arg_module]
648                            .module
649                            .defined_func_index(*arg_func)
650                        else {
651                            // TODO: we should ideally follow re-export chains
652                            // to bottom out the instantiation argument in
653                            // either a definition or an import at the root
654                            // component boundary. In practice, this pattern is
655                            // rare, so following these chains is left for the
656                            // Future.
657                            continue;
658                        };
659
660                        FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func)
661                    }
662                };
663
664                assert!(
665                    self.static_modules[module].known_imported_functions[imported_func].is_none()
666                );
667                self.static_modules[module].known_imported_functions[imported_func] =
668                    Some(known_func);
669            }
670        }
671    }
672
673    fn translate_payload(
674        &mut self,
675        payload: Payload<'data>,
676        component: &'data [u8],
677    ) -> Result<Action> {
678        match payload {
679            Payload::Version {
680                num,
681                encoding,
682                range,
683            } => {
684                self.validator.version(num, encoding, &range)?;
685
686                match encoding {
687                    Encoding::Component => {}
688                    Encoding::Module => {
689                        bail!("attempted to parse a wasm module with a component parser");
690                    }
691                }
692            }
693
694            Payload::End(offset) => {
695                assert!(self.result.types.is_none());
696                self.result.types = Some(self.validator.end(offset)?);
697
698                // Exit the current lexical scope. If there is no parent (no
699                // frame currently on the stack) then translation is finished.
700                // Otherwise that means that a nested component has been
701                // completed and is recorded as such.
702                let LexicalScope {
703                    parser,
704                    translation,
705                    closure_args,
706                } = match self.lexical_scopes.pop() {
707                    Some(frame) => frame,
708                    None => return Ok(Action::Done),
709                };
710                self.parser = parser;
711                let component = mem::replace(&mut self.result, translation);
712                let static_idx = self.static_components.push(component);
713                self.result
714                    .initializers
715                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
716            }
717
718            // When we see a type section the types are validated and then
719            // translated into Wasmtime's representation. Each active type
720            // definition is recorded in the `ComponentTypesBuilder` tables, or
721            // this component's active scope.
722            //
723            // Note that the push/pop of the component types scope happens above
724            // in `Version` and `End` since multiple type sections can appear
725            // within a component.
726            Payload::ComponentTypeSection(s) => {
727                let mut component_type_index =
728                    self.validator.types(0).unwrap().component_type_count();
729                self.validator.component_type_section(&s)?;
730
731                // Look for resource types and if a local resource is defined
732                // then an initializer is added to define that resource type and
733                // reference its destructor.
734                let types = self.validator.types(0).unwrap();
735                for ty in s {
736                    match ty? {
737                        wasmparser::ComponentType::Resource { rep, dtor } => {
738                            let rep = self.types.convert_valtype(rep)?;
739                            let id = types
740                                .component_any_type_at(component_type_index)
741                                .unwrap_resource();
742                            let dtor = dtor.map(FuncIndex::from_u32);
743                            self.result
744                                .initializers
745                                .push(LocalInitializer::Resource(id, rep, dtor));
746                        }
747
748                        // no extra processing needed
749                        wasmparser::ComponentType::Defined(_)
750                        | wasmparser::ComponentType::Func(_)
751                        | wasmparser::ComponentType::Instance(_)
752                        | wasmparser::ComponentType::Component(_) => {}
753                    }
754
755                    component_type_index += 1;
756                }
757            }
758            Payload::CoreTypeSection(s) => {
759                self.validator.core_type_section(&s)?;
760            }
761
762            // Processing the import section at this point is relatively simple
763            // which is to simply record the name of the import and the type
764            // information associated with it.
765            Payload::ComponentImportSection(s) => {
766                self.validator.component_import_section(&s)?;
767                for import in s {
768                    let import = import?;
769                    let types = self.validator.types(0).unwrap();
770                    let ty = types
771                        .component_entity_type_of_import(import.name.0)
772                        .unwrap();
773
774                    if self.is_unsafe_intrinsics_import(import.name.0) {
775                        self.check_unsafe_intrinsics_import(import.name.0, ty)?;
776                        self.result
777                            .initializers
778                            .push(LocalInitializer::IntrinsicsImport);
779                    } else {
780                        self.result
781                            .initializers
782                            .push(LocalInitializer::Import(import.name, ty));
783                    }
784                }
785            }
786
787            // Entries in the canonical section will get initializers recorded
788            // with the listed options for lifting/lowering.
789            Payload::ComponentCanonicalSection(s) => {
790                let types = self.validator.types(0).unwrap();
791                let mut core_func_index = types.function_count();
792                self.validator.component_canonical_section(&s)?;
793                for func in s {
794                    let init = match func? {
795                        wasmparser::CanonicalFunction::Lift {
796                            type_index,
797                            core_func_index,
798                            options,
799                        } => {
800                            let ty = self
801                                .validator
802                                .types(0)
803                                .unwrap()
804                                .component_any_type_at(type_index)
805                                .unwrap_func();
806
807                            let func = FuncIndex::from_u32(core_func_index);
808                            let options = self.canonical_options(&options, core_func_index)?;
809                            LocalInitializer::Lift(ty, func, options)
810                        }
811                        wasmparser::CanonicalFunction::Lower {
812                            func_index,
813                            options,
814                        } => {
815                            let lower_ty = self
816                                .validator
817                                .types(0)
818                                .unwrap()
819                                .component_function_at(func_index);
820                            let func = ComponentFuncIndex::from_u32(func_index);
821                            let options = self.canonical_options(&options, core_func_index)?;
822                            core_func_index += 1;
823                            LocalInitializer::Lower {
824                                func,
825                                options,
826                                lower_ty,
827                            }
828                        }
829                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
830                            let resource = self
831                                .validator
832                                .types(0)
833                                .unwrap()
834                                .component_any_type_at(resource)
835                                .unwrap_resource();
836                            let ty = self.core_func_signature(core_func_index)?;
837                            core_func_index += 1;
838                            LocalInitializer::ResourceNew(resource, ty)
839                        }
840                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
841                            let resource = self
842                                .validator
843                                .types(0)
844                                .unwrap()
845                                .component_any_type_at(resource)
846                                .unwrap_resource();
847                            let ty = self.core_func_signature(core_func_index)?;
848                            core_func_index += 1;
849                            LocalInitializer::ResourceDrop(resource, ty)
850                        }
851                        wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
852                            let _ = resource;
853                            bail!("support for `resource.drop async` not implemented yet")
854                        }
855                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
856                            let resource = self
857                                .validator
858                                .types(0)
859                                .unwrap()
860                                .component_any_type_at(resource)
861                                .unwrap_resource();
862                            let ty = self.core_func_signature(core_func_index)?;
863                            core_func_index += 1;
864                            LocalInitializer::ResourceRep(resource, ty)
865                        }
866                        wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
867                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
868                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
869                            bail!("unsupported intrinsic")
870                        }
871                        wasmparser::CanonicalFunction::BackpressureInc => {
872                            let core_type = self.core_func_signature(core_func_index)?;
873                            core_func_index += 1;
874                            LocalInitializer::BackpressureInc { func: core_type }
875                        }
876                        wasmparser::CanonicalFunction::BackpressureDec => {
877                            let core_type = self.core_func_signature(core_func_index)?;
878                            core_func_index += 1;
879                            LocalInitializer::BackpressureDec { func: core_type }
880                        }
881
882                        wasmparser::CanonicalFunction::TaskReturn { result, options } => {
883                            let result = result.map(|ty| match ty {
884                                wasmparser::ComponentValType::Primitive(ty) => {
885                                    ComponentValType::Primitive(ty)
886                                }
887                                wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
888                                    self.validator
889                                        .types(0)
890                                        .unwrap()
891                                        .component_defined_type_at(ty),
892                                ),
893                            });
894                            let options = self.canonical_options(&options, core_func_index)?;
895                            core_func_index += 1;
896                            LocalInitializer::TaskReturn { result, options }
897                        }
898                        wasmparser::CanonicalFunction::TaskCancel => {
899                            let func = self.core_func_signature(core_func_index)?;
900                            core_func_index += 1;
901                            LocalInitializer::TaskCancel { func }
902                        }
903                        wasmparser::CanonicalFunction::WaitableSetNew => {
904                            let func = self.core_func_signature(core_func_index)?;
905                            core_func_index += 1;
906                            LocalInitializer::WaitableSetNew { func }
907                        }
908                        wasmparser::CanonicalFunction::WaitableSetWait {
909                            cancellable,
910                            memory,
911                        } => {
912                            let core_type = self.core_func_signature(core_func_index)?;
913                            core_func_index += 1;
914                            LocalInitializer::WaitableSetWait {
915                                options: LocalCanonicalOptions {
916                                    core_type,
917                                    cancellable,
918                                    async_: false,
919                                    data_model: LocalDataModel::LinearMemory {
920                                        memory: Some(MemoryIndex::from_u32(memory)),
921                                        realloc: None,
922                                    },
923                                    post_return: None,
924                                    callback: None,
925                                    string_encoding: StringEncoding::Utf8,
926                                },
927                            }
928                        }
929                        wasmparser::CanonicalFunction::WaitableSetPoll {
930                            cancellable,
931                            memory,
932                        } => {
933                            let core_type = self.core_func_signature(core_func_index)?;
934                            core_func_index += 1;
935                            LocalInitializer::WaitableSetPoll {
936                                options: LocalCanonicalOptions {
937                                    core_type,
938                                    async_: false,
939                                    cancellable,
940                                    data_model: LocalDataModel::LinearMemory {
941                                        memory: Some(MemoryIndex::from_u32(memory)),
942                                        realloc: None,
943                                    },
944                                    post_return: None,
945                                    callback: None,
946                                    string_encoding: StringEncoding::Utf8,
947                                },
948                            }
949                        }
950                        wasmparser::CanonicalFunction::WaitableSetDrop => {
951                            let func = self.core_func_signature(core_func_index)?;
952                            core_func_index += 1;
953                            LocalInitializer::WaitableSetDrop { func }
954                        }
955                        wasmparser::CanonicalFunction::WaitableJoin => {
956                            let func = self.core_func_signature(core_func_index)?;
957                            core_func_index += 1;
958                            LocalInitializer::WaitableJoin { func }
959                        }
960                        wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
961                            let func = self.core_func_signature(core_func_index)?;
962                            core_func_index += 1;
963                            LocalInitializer::ThreadYield { func, cancellable }
964                        }
965                        wasmparser::CanonicalFunction::SubtaskDrop => {
966                            let func = self.core_func_signature(core_func_index)?;
967                            core_func_index += 1;
968                            LocalInitializer::SubtaskDrop { func }
969                        }
970                        wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
971                            let func = self.core_func_signature(core_func_index)?;
972                            core_func_index += 1;
973                            LocalInitializer::SubtaskCancel { func, async_ }
974                        }
975                        wasmparser::CanonicalFunction::StreamNew { ty } => {
976                            let ty = self
977                                .validator
978                                .types(0)
979                                .unwrap()
980                                .component_defined_type_at(ty);
981                            let func = self.core_func_signature(core_func_index)?;
982                            core_func_index += 1;
983                            LocalInitializer::StreamNew { ty, func }
984                        }
985                        wasmparser::CanonicalFunction::StreamRead { ty, options } => {
986                            let ty = self
987                                .validator
988                                .types(0)
989                                .unwrap()
990                                .component_defined_type_at(ty);
991                            let options = self.canonical_options(&options, core_func_index)?;
992                            core_func_index += 1;
993                            LocalInitializer::StreamRead { ty, options }
994                        }
995                        wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
996                            let ty = self
997                                .validator
998                                .types(0)
999                                .unwrap()
1000                                .component_defined_type_at(ty);
1001                            let options = self.canonical_options(&options, core_func_index)?;
1002                            core_func_index += 1;
1003                            LocalInitializer::StreamWrite { ty, options }
1004                        }
1005                        wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1006                            let ty = self
1007                                .validator
1008                                .types(0)
1009                                .unwrap()
1010                                .component_defined_type_at(ty);
1011                            let func = self.core_func_signature(core_func_index)?;
1012                            core_func_index += 1;
1013                            LocalInitializer::StreamCancelRead { ty, func, async_ }
1014                        }
1015                        wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1016                            let ty = self
1017                                .validator
1018                                .types(0)
1019                                .unwrap()
1020                                .component_defined_type_at(ty);
1021                            let func = self.core_func_signature(core_func_index)?;
1022                            core_func_index += 1;
1023                            LocalInitializer::StreamCancelWrite { ty, func, async_ }
1024                        }
1025                        wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1026                            let ty = self
1027                                .validator
1028                                .types(0)
1029                                .unwrap()
1030                                .component_defined_type_at(ty);
1031                            let func = self.core_func_signature(core_func_index)?;
1032                            core_func_index += 1;
1033                            LocalInitializer::StreamDropReadable { ty, func }
1034                        }
1035                        wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1036                            let ty = self
1037                                .validator
1038                                .types(0)
1039                                .unwrap()
1040                                .component_defined_type_at(ty);
1041                            let func = self.core_func_signature(core_func_index)?;
1042                            core_func_index += 1;
1043                            LocalInitializer::StreamDropWritable { ty, func }
1044                        }
1045                        wasmparser::CanonicalFunction::FutureNew { ty } => {
1046                            let ty = self
1047                                .validator
1048                                .types(0)
1049                                .unwrap()
1050                                .component_defined_type_at(ty);
1051                            let func = self.core_func_signature(core_func_index)?;
1052                            core_func_index += 1;
1053                            LocalInitializer::FutureNew { ty, func }
1054                        }
1055                        wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1056                            let ty = self
1057                                .validator
1058                                .types(0)
1059                                .unwrap()
1060                                .component_defined_type_at(ty);
1061                            let options = self.canonical_options(&options, core_func_index)?;
1062                            core_func_index += 1;
1063                            LocalInitializer::FutureRead { ty, options }
1064                        }
1065                        wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1066                            let ty = self
1067                                .validator
1068                                .types(0)
1069                                .unwrap()
1070                                .component_defined_type_at(ty);
1071                            let options = self.canonical_options(&options, core_func_index)?;
1072                            core_func_index += 1;
1073                            LocalInitializer::FutureWrite { ty, options }
1074                        }
1075                        wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1076                            let ty = self
1077                                .validator
1078                                .types(0)
1079                                .unwrap()
1080                                .component_defined_type_at(ty);
1081                            let func = self.core_func_signature(core_func_index)?;
1082                            core_func_index += 1;
1083                            LocalInitializer::FutureCancelRead { ty, func, async_ }
1084                        }
1085                        wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1086                            let ty = self
1087                                .validator
1088                                .types(0)
1089                                .unwrap()
1090                                .component_defined_type_at(ty);
1091                            let func = self.core_func_signature(core_func_index)?;
1092                            core_func_index += 1;
1093                            LocalInitializer::FutureCancelWrite { ty, func, async_ }
1094                        }
1095                        wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1096                            let ty = self
1097                                .validator
1098                                .types(0)
1099                                .unwrap()
1100                                .component_defined_type_at(ty);
1101                            let func = self.core_func_signature(core_func_index)?;
1102                            core_func_index += 1;
1103                            LocalInitializer::FutureDropReadable { ty, func }
1104                        }
1105                        wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1106                            let ty = self
1107                                .validator
1108                                .types(0)
1109                                .unwrap()
1110                                .component_defined_type_at(ty);
1111                            let func = self.core_func_signature(core_func_index)?;
1112                            core_func_index += 1;
1113                            LocalInitializer::FutureDropWritable { ty, func }
1114                        }
1115                        wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1116                            let options = self.canonical_options(&options, core_func_index)?;
1117                            core_func_index += 1;
1118                            LocalInitializer::ErrorContextNew { options }
1119                        }
1120                        wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1121                            let options = self.canonical_options(&options, core_func_index)?;
1122                            core_func_index += 1;
1123                            LocalInitializer::ErrorContextDebugMessage { options }
1124                        }
1125                        wasmparser::CanonicalFunction::ErrorContextDrop => {
1126                            let func = self.core_func_signature(core_func_index)?;
1127                            core_func_index += 1;
1128                            LocalInitializer::ErrorContextDrop { func }
1129                        }
1130                        wasmparser::CanonicalFunction::ContextGet(i) => {
1131                            let func = self.core_func_signature(core_func_index)?;
1132                            core_func_index += 1;
1133                            LocalInitializer::ContextGet { i, func }
1134                        }
1135                        wasmparser::CanonicalFunction::ContextSet(i) => {
1136                            let func = self.core_func_signature(core_func_index)?;
1137                            core_func_index += 1;
1138                            LocalInitializer::ContextSet { i, func }
1139                        }
1140                        wasmparser::CanonicalFunction::ThreadIndex => {
1141                            let func = self.core_func_signature(core_func_index)?;
1142                            core_func_index += 1;
1143                            LocalInitializer::ThreadIndex { func }
1144                        }
1145                        wasmparser::CanonicalFunction::ThreadNewIndirect {
1146                            func_ty_index,
1147                            table_index,
1148                        } => {
1149                            let func = self.core_func_signature(core_func_index)?;
1150                            core_func_index += 1;
1151                            LocalInitializer::ThreadNewIndirect {
1152                                func,
1153                                start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1154                                start_func_table_index: TableIndex::from_u32(table_index),
1155                            }
1156                        }
1157                        wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1158                            let func = self.core_func_signature(core_func_index)?;
1159                            core_func_index += 1;
1160                            LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1161                        }
1162                        wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1163                            let func = self.core_func_signature(core_func_index)?;
1164                            core_func_index += 1;
1165                            LocalInitializer::ThreadSuspend { func, cancellable }
1166                        }
1167                        wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1168                            let func = self.core_func_signature(core_func_index)?;
1169                            core_func_index += 1;
1170                            LocalInitializer::ThreadSuspendTo { func, cancellable }
1171                        }
1172                        wasmparser::CanonicalFunction::ThreadUnsuspend => {
1173                            let func = self.core_func_signature(core_func_index)?;
1174                            core_func_index += 1;
1175                            LocalInitializer::ThreadUnsuspend { func }
1176                        }
1177                        wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1178                            let func = self.core_func_signature(core_func_index)?;
1179                            core_func_index += 1;
1180                            LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1181                        }
1182                    };
1183                    self.result.initializers.push(init);
1184                }
1185            }
1186
1187            // Core wasm modules are translated inline directly here with the
1188            // `ModuleEnvironment` from core wasm compilation. This will return
1189            // to the caller the size of the module so it knows how many bytes
1190            // of the input are skipped.
1191            //
1192            // Note that this is just initial type translation of the core wasm
1193            // module and actual function compilation is deferred until this
1194            // entire process has completed.
1195            Payload::ModuleSection {
1196                parser,
1197                unchecked_range,
1198            } => {
1199                let index = self.validator.types(0).unwrap().module_count();
1200                self.validator.module_section(&unchecked_range)?;
1201                let static_module_index = self.static_modules.next_key();
1202                let translation = ModuleEnvironment::new(
1203                    self.tunables,
1204                    self.validator,
1205                    self.types.module_types_builder(),
1206                    static_module_index,
1207                )
1208                .translate(
1209                    parser,
1210                    component
1211                        .get(unchecked_range.start..unchecked_range.end)
1212                        .ok_or_else(|| {
1213                            format_err!(
1214                                "section range {}..{} is out of bounds (bound = {})",
1215                                unchecked_range.start,
1216                                unchecked_range.end,
1217                                component.len()
1218                            )
1219                            .context("wasm component contains an invalid module section")
1220                        })?,
1221                )?;
1222                let static_module_index2 = self.static_modules.push(translation);
1223                assert_eq!(static_module_index, static_module_index2);
1224                let types = self.validator.types(0).unwrap();
1225                let ty = types.module_at(index);
1226                self.result
1227                    .initializers
1228                    .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1229                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1230            }
1231
1232            // When a sub-component is found then the current translation state
1233            // is pushed onto the `lexical_scopes` stack. This will subsequently
1234            // get popped as part of `Payload::End` processing above.
1235            //
1236            // Note that the set of closure args for this new lexical scope
1237            // starts empty since it will only get populated if translation of
1238            // the nested component ends up aliasing some outer module or
1239            // component.
1240            Payload::ComponentSection {
1241                parser,
1242                unchecked_range,
1243            } => {
1244                self.validator.component_section(&unchecked_range)?;
1245                self.lexical_scopes.push(LexicalScope {
1246                    parser: mem::replace(&mut self.parser, parser),
1247                    translation: mem::take(&mut self.result),
1248                    closure_args: ClosedOverVars::default(),
1249                });
1250            }
1251
1252            // Both core wasm instances and component instances record
1253            // initializers of what form of instantiation is performed which
1254            // largely just records the arguments given from wasmparser into a
1255            // `HashMap` for processing later during inlining.
1256            Payload::InstanceSection(s) => {
1257                self.validator.instance_section(&s)?;
1258                for instance in s {
1259                    let init = match instance? {
1260                        wasmparser::Instance::Instantiate { module_index, args } => {
1261                            let index = ModuleIndex::from_u32(module_index);
1262                            self.instantiate_module(index, &args)
1263                        }
1264                        wasmparser::Instance::FromExports(exports) => {
1265                            self.instantiate_module_from_exports(&exports)
1266                        }
1267                    };
1268                    self.result.initializers.push(init);
1269                }
1270            }
1271            Payload::ComponentInstanceSection(s) => {
1272                let mut index = self.validator.types(0).unwrap().component_instance_count();
1273                self.validator.component_instance_section(&s)?;
1274                for instance in s {
1275                    let types = self.validator.types(0).unwrap();
1276                    let ty = types.component_instance_at(index);
1277                    let init = match instance? {
1278                        wasmparser::ComponentInstance::Instantiate {
1279                            component_index,
1280                            args,
1281                        } => {
1282                            let index = ComponentIndex::from_u32(component_index);
1283                            self.instantiate_component(index, &args, ty)?
1284                        }
1285                        wasmparser::ComponentInstance::FromExports(exports) => {
1286                            self.instantiate_component_from_exports(&exports, ty)?
1287                        }
1288                    };
1289                    self.result.initializers.push(init);
1290                    index += 1;
1291                }
1292            }
1293
1294            // Exports don't actually fill out the `initializers` array but
1295            // instead fill out the one other field in a `Translation`, the
1296            // `exports` field (as one might imagine). This for now simply
1297            // records the index of what's exported and that's tracked further
1298            // later during inlining.
1299            Payload::ComponentExportSection(s) => {
1300                self.validator.component_export_section(&s)?;
1301                for export in s {
1302                    let export = export?;
1303                    let item = self.kind_to_item(export.kind, export.index)?;
1304                    let prev = self.result.exports.insert(export.name.0, item);
1305                    assert!(prev.is_none());
1306                    self.result
1307                        .initializers
1308                        .push(LocalInitializer::Export(item));
1309                }
1310            }
1311
1312            Payload::ComponentStartSection { start, range } => {
1313                self.validator.component_start_section(&start, &range)?;
1314                unimplemented!("component start section");
1315            }
1316
1317            // Aliases of instance exports (either core or component) will be
1318            // recorded as an initializer of the appropriate type with outer
1319            // aliases handled specially via upvars and type processing.
1320            Payload::ComponentAliasSection(s) => {
1321                self.validator.component_alias_section(&s)?;
1322                for alias in s {
1323                    let init = match alias? {
1324                        wasmparser::ComponentAlias::InstanceExport {
1325                            kind: _,
1326                            instance_index,
1327                            name,
1328                        } => {
1329                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1330                            LocalInitializer::AliasComponentExport(instance, name)
1331                        }
1332                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1333                            self.alias_component_outer(kind, count, index);
1334                            continue;
1335                        }
1336                        wasmparser::ComponentAlias::CoreInstanceExport {
1337                            kind,
1338                            instance_index,
1339                            name,
1340                        } => {
1341                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1342                            self.alias_module_instance_export(kind, instance, name)
1343                        }
1344                    };
1345                    self.result.initializers.push(init);
1346                }
1347            }
1348
1349            // All custom sections are ignored by Wasmtime at this time.
1350            //
1351            // FIXME(WebAssembly/component-model#14): probably want to specify
1352            // and parse a `name` section here.
1353            Payload::CustomSection { .. } => {}
1354
1355            // Anything else is either not reachable since we never enable the
1356            // feature in Wasmtime or we do enable it and it's a bug we don't
1357            // implement it, so let validation take care of most errors here and
1358            // if it gets past validation provide a helpful error message to
1359            // debug.
1360            other => {
1361                self.validator.payload(&other)?;
1362                panic!("unimplemented section {other:?}");
1363            }
1364        }
1365
1366        Ok(Action::KeepGoing)
1367    }
1368
1369    fn instantiate_module(
1370        &mut self,
1371        module: ModuleIndex,
1372        raw_args: &[wasmparser::InstantiationArg<'data>],
1373    ) -> LocalInitializer<'data> {
1374        let mut args = HashMap::with_capacity(raw_args.len());
1375        for arg in raw_args {
1376            match arg.kind {
1377                wasmparser::InstantiationArgKind::Instance => {
1378                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1379                    args.insert(arg.name, idx);
1380                }
1381            }
1382        }
1383        LocalInitializer::ModuleInstantiate(module, args)
1384    }
1385
1386    /// Creates a synthetic module from the list of items currently in the
1387    /// module and their given names.
1388    fn instantiate_module_from_exports(
1389        &mut self,
1390        exports: &[wasmparser::Export<'data>],
1391    ) -> LocalInitializer<'data> {
1392        let mut map = HashMap::with_capacity(exports.len());
1393        for export in exports {
1394            let idx = match export.kind {
1395                wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1396                    let index = FuncIndex::from_u32(export.index);
1397                    EntityIndex::Function(index)
1398                }
1399                wasmparser::ExternalKind::Table => {
1400                    let index = TableIndex::from_u32(export.index);
1401                    EntityIndex::Table(index)
1402                }
1403                wasmparser::ExternalKind::Memory => {
1404                    let index = MemoryIndex::from_u32(export.index);
1405                    EntityIndex::Memory(index)
1406                }
1407                wasmparser::ExternalKind::Global => {
1408                    let index = GlobalIndex::from_u32(export.index);
1409                    EntityIndex::Global(index)
1410                }
1411                wasmparser::ExternalKind::Tag => {
1412                    let index = TagIndex::from_u32(export.index);
1413                    EntityIndex::Tag(index)
1414                }
1415            };
1416            map.insert(export.name, idx);
1417        }
1418        LocalInitializer::ModuleSynthetic(map)
1419    }
1420
1421    fn instantiate_component(
1422        &mut self,
1423        component: ComponentIndex,
1424        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1425        ty: ComponentInstanceTypeId,
1426    ) -> Result<LocalInitializer<'data>> {
1427        let mut args = HashMap::with_capacity(raw_args.len());
1428        for arg in raw_args {
1429            let idx = self.kind_to_item(arg.kind, arg.index)?;
1430            args.insert(arg.name, idx);
1431        }
1432
1433        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1434    }
1435
1436    /// Creates a synthetic module from the list of items currently in the
1437    /// module and their given names.
1438    fn instantiate_component_from_exports(
1439        &mut self,
1440        exports: &[wasmparser::ComponentExport<'data>],
1441        ty: ComponentInstanceTypeId,
1442    ) -> Result<LocalInitializer<'data>> {
1443        let mut map = HashMap::with_capacity(exports.len());
1444        for export in exports {
1445            let idx = self.kind_to_item(export.kind, export.index)?;
1446            map.insert(export.name.0, idx);
1447        }
1448
1449        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1450    }
1451
1452    fn kind_to_item(
1453        &mut self,
1454        kind: wasmparser::ComponentExternalKind,
1455        index: u32,
1456    ) -> Result<ComponentItem> {
1457        Ok(match kind {
1458            wasmparser::ComponentExternalKind::Func => {
1459                let index = ComponentFuncIndex::from_u32(index);
1460                ComponentItem::Func(index)
1461            }
1462            wasmparser::ComponentExternalKind::Module => {
1463                let index = ModuleIndex::from_u32(index);
1464                ComponentItem::Module(index)
1465            }
1466            wasmparser::ComponentExternalKind::Instance => {
1467                let index = ComponentInstanceIndex::from_u32(index);
1468                ComponentItem::ComponentInstance(index)
1469            }
1470            wasmparser::ComponentExternalKind::Component => {
1471                let index = ComponentIndex::from_u32(index);
1472                ComponentItem::Component(index)
1473            }
1474            wasmparser::ComponentExternalKind::Value => {
1475                unimplemented!("component values");
1476            }
1477            wasmparser::ComponentExternalKind::Type => {
1478                let types = self.validator.types(0).unwrap();
1479                let ty = types.component_any_type_at(index);
1480                ComponentItem::Type(ty)
1481            }
1482        })
1483    }
1484
1485    fn alias_module_instance_export(
1486        &mut self,
1487        kind: wasmparser::ExternalKind,
1488        instance: ModuleInstanceIndex,
1489        name: &'data str,
1490    ) -> LocalInitializer<'data> {
1491        match kind {
1492            wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1493                LocalInitializer::AliasExportFunc(instance, name)
1494            }
1495            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1496            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1497            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1498            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1499        }
1500    }
1501
1502    fn alias_component_outer(
1503        &mut self,
1504        kind: wasmparser::ComponentOuterAliasKind,
1505        count: u32,
1506        index: u32,
1507    ) {
1508        match kind {
1509            wasmparser::ComponentOuterAliasKind::CoreType
1510            | wasmparser::ComponentOuterAliasKind::Type => {}
1511
1512            // For more information about the implementation of outer aliases
1513            // see the documentation of `LexicalScope`. Otherwise though the
1514            // main idea here is that the data to close over starts as `Local`
1515            // and then transitions to `Upvar` as its inserted into the parents
1516            // in order from target we're aliasing back to the current
1517            // component.
1518            wasmparser::ComponentOuterAliasKind::CoreModule => {
1519                let index = ModuleIndex::from_u32(index);
1520                let mut module = ClosedOverModule::Local(index);
1521                let depth = self.lexical_scopes.len() - (count as usize);
1522                for frame in self.lexical_scopes[depth..].iter_mut() {
1523                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1524                }
1525
1526                // If the `module` is still `Local` then the `depth` was 0 and
1527                // it's an alias into our own space. Otherwise it's switched to
1528                // an upvar and will index into the upvar space. Either way
1529                // it's just plumbed directly into the initializer.
1530                self.result
1531                    .initializers
1532                    .push(LocalInitializer::AliasModule(module));
1533            }
1534            wasmparser::ComponentOuterAliasKind::Component => {
1535                let index = ComponentIndex::from_u32(index);
1536                let mut component = ClosedOverComponent::Local(index);
1537                let depth = self.lexical_scopes.len() - (count as usize);
1538                for frame in self.lexical_scopes[depth..].iter_mut() {
1539                    component =
1540                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1541                }
1542
1543                self.result
1544                    .initializers
1545                    .push(LocalInitializer::AliasComponent(component));
1546            }
1547        }
1548    }
1549
1550    fn canonical_options(
1551        &mut self,
1552        opts: &[wasmparser::CanonicalOption],
1553        core_func_index: u32,
1554    ) -> WasmResult<LocalCanonicalOptions> {
1555        let core_type = self.core_func_signature(core_func_index)?;
1556
1557        let mut string_encoding = StringEncoding::Utf8;
1558        let mut post_return = None;
1559        let mut async_ = false;
1560        let mut callback = None;
1561        let mut memory = None;
1562        let mut realloc = None;
1563        let mut gc = false;
1564
1565        for opt in opts {
1566            match opt {
1567                wasmparser::CanonicalOption::UTF8 => {
1568                    string_encoding = StringEncoding::Utf8;
1569                }
1570                wasmparser::CanonicalOption::UTF16 => {
1571                    string_encoding = StringEncoding::Utf16;
1572                }
1573                wasmparser::CanonicalOption::CompactUTF16 => {
1574                    string_encoding = StringEncoding::CompactUtf16;
1575                }
1576                wasmparser::CanonicalOption::Memory(idx) => {
1577                    let idx = MemoryIndex::from_u32(*idx);
1578                    memory = Some(idx);
1579                }
1580                wasmparser::CanonicalOption::Realloc(idx) => {
1581                    let idx = FuncIndex::from_u32(*idx);
1582                    realloc = Some(idx);
1583                }
1584                wasmparser::CanonicalOption::PostReturn(idx) => {
1585                    let idx = FuncIndex::from_u32(*idx);
1586                    post_return = Some(idx);
1587                }
1588                wasmparser::CanonicalOption::Async => async_ = true,
1589                wasmparser::CanonicalOption::Callback(idx) => {
1590                    let idx = FuncIndex::from_u32(*idx);
1591                    callback = Some(idx);
1592                }
1593                wasmparser::CanonicalOption::CoreType(idx) => {
1594                    if cfg!(debug_assertions) {
1595                        let types = self.validator.types(0).unwrap();
1596                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1597                        let interned = self
1598                            .types
1599                            .module_types_builder()
1600                            .intern_type(types, core_ty_id)?;
1601                        debug_assert_eq!(interned, core_type);
1602                    }
1603                }
1604                wasmparser::CanonicalOption::Gc => {
1605                    gc = true;
1606                }
1607            }
1608        }
1609
1610        Ok(LocalCanonicalOptions {
1611            string_encoding,
1612            post_return,
1613            cancellable: false,
1614            async_,
1615            callback,
1616            core_type,
1617            data_model: if gc {
1618                LocalDataModel::Gc {}
1619            } else {
1620                LocalDataModel::LinearMemory { memory, realloc }
1621            },
1622        })
1623    }
1624
1625    /// Get the interned type index for the `index`th core function.
1626    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1627        let types = self.validator.types(0).unwrap();
1628        let id = types.core_function_at(index);
1629        self.types.module_types_builder().intern_type(types, id)
1630    }
1631
1632    fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1633        self.lexical_scopes.is_empty()
1634            && self
1635                .unsafe_intrinsics_import
1636                .is_some_and(|name| import == name)
1637    }
1638
1639    fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1640        let types = &self.validator.types(0).unwrap();
1641
1642        let ComponentEntityType::Instance(instance_ty) = ty else {
1643            bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1644        };
1645        let instance_ty = &types[instance_ty];
1646
1647        ensure!(
1648            instance_ty.defined_resources.is_empty(),
1649            "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1650        );
1651        ensure!(
1652            instance_ty.explicit_resources.is_empty(),
1653            "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1654        );
1655
1656        for (name, ty) in &instance_ty.exports {
1657            let ComponentEntityType::Func(func_ty) = ty else {
1658                bail!(
1659                    "bad unsafe intrinsics import: imported instance `{import}` must \
1660                     only export functions"
1661                )
1662            };
1663            let func_ty = &types[*func_ty];
1664
1665            fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1666                use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1667                match (a, b) {
1668                    (InterfaceType::U8, C::Primitive(P::U8)) => true,
1669                    (InterfaceType::U8, _) => false,
1670
1671                    (InterfaceType::U16, C::Primitive(P::U16)) => true,
1672                    (InterfaceType::U16, _) => false,
1673
1674                    (InterfaceType::U32, C::Primitive(P::U32)) => true,
1675                    (InterfaceType::U32, _) => false,
1676
1677                    (InterfaceType::U64, C::Primitive(P::U64)) => true,
1678                    (InterfaceType::U64, _) => false,
1679
1680                    (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1681                }
1682            }
1683
1684            fn check_types<'a>(
1685                expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1686                actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1687                kind: &str,
1688                import: &str,
1689                name: &str,
1690            ) -> Result<()> {
1691                let expected_len = expected.len();
1692                let actual_len = actual.len();
1693                ensure!(
1694                    expected_len == actual_len,
1695                    "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1696                     {expected_len} {kind}, found {actual_len}"
1697                );
1698
1699                for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1700                    ensure!(
1701                        ty_eq(expected_ty, actual_ty),
1702                        "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1703                         `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1704                    );
1705                }
1706                Ok(())
1707            }
1708
1709            let intrinsic = UnsafeIntrinsic::from_str(name)
1710                .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1711
1712            check_types(
1713                intrinsic.component_params().iter(),
1714                func_ty.params.iter().map(|(_name, ty)| ty),
1715                "parameters",
1716                &import,
1717                &name,
1718            )?;
1719            check_types(
1720                intrinsic.component_results().iter(),
1721                func_ty.result.iter(),
1722                "results",
1723                &import,
1724                &name,
1725            )?;
1726        }
1727
1728        Ok(())
1729    }
1730}
1731
1732impl Translation<'_> {
1733    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1734        self.types.as_ref().unwrap().as_ref()
1735    }
1736}
1737
1738/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1739/// to disallow access to mutable access to the builder before the inlining
1740/// pass.
1741///
1742/// Type information in this translation pass must be preserved at the
1743/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1744/// own type system. Only during inlining are types fully assigned because
1745/// that's when resource types become available as it's known which instance
1746/// defines which resource, or more concretely the same component instantiated
1747/// twice will produce two unique resource types unlike one as seen by
1748/// wasmparser within the component.
1749mod pre_inlining {
1750    use super::*;
1751
1752    pub struct PreInliningComponentTypes<'a> {
1753        types: &'a mut ComponentTypesBuilder,
1754    }
1755
1756    impl<'a> PreInliningComponentTypes<'a> {
1757        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1758            Self { types }
1759        }
1760
1761        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1762            self.types.module_types_builder_mut()
1763        }
1764
1765        pub fn types(&self) -> &ComponentTypesBuilder {
1766            self.types
1767        }
1768
1769        // NB: this should in theory only be used for the `inline` phase of
1770        // translation.
1771        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1772            self.types
1773        }
1774    }
1775
1776    impl TypeConvert for PreInliningComponentTypes<'_> {
1777        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1778            self.types.lookup_heap_type(index)
1779        }
1780
1781        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1782            self.types.lookup_type_index(index)
1783        }
1784    }
1785}
1786use pre_inlining::PreInliningComponentTypes;