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