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 mut 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
1223                translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1224                let static_module_index2 = self.static_modules.push(translation);
1225                assert_eq!(static_module_index, static_module_index2);
1226                let types = self.validator.types(0).unwrap();
1227                let ty = types.module_at(index);
1228                self.result
1229                    .initializers
1230                    .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1231                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1232            }
1233
1234            // When a sub-component is found then the current translation state
1235            // is pushed onto the `lexical_scopes` stack. This will subsequently
1236            // get popped as part of `Payload::End` processing above.
1237            //
1238            // Note that the set of closure args for this new lexical scope
1239            // starts empty since it will only get populated if translation of
1240            // the nested component ends up aliasing some outer module or
1241            // component.
1242            Payload::ComponentSection {
1243                parser,
1244                unchecked_range,
1245            } => {
1246                self.validator.component_section(&unchecked_range)?;
1247                self.lexical_scopes.push(LexicalScope {
1248                    parser: mem::replace(&mut self.parser, parser),
1249                    translation: mem::take(&mut self.result),
1250                    closure_args: ClosedOverVars::default(),
1251                });
1252            }
1253
1254            // Both core wasm instances and component instances record
1255            // initializers of what form of instantiation is performed which
1256            // largely just records the arguments given from wasmparser into a
1257            // `HashMap` for processing later during inlining.
1258            Payload::InstanceSection(s) => {
1259                self.validator.instance_section(&s)?;
1260                for instance in s {
1261                    let init = match instance? {
1262                        wasmparser::Instance::Instantiate { module_index, args } => {
1263                            let index = ModuleIndex::from_u32(module_index);
1264                            self.instantiate_module(index, &args)
1265                        }
1266                        wasmparser::Instance::FromExports(exports) => {
1267                            self.instantiate_module_from_exports(&exports)
1268                        }
1269                    };
1270                    self.result.initializers.push(init);
1271                }
1272            }
1273            Payload::ComponentInstanceSection(s) => {
1274                let mut index = self.validator.types(0).unwrap().component_instance_count();
1275                self.validator.component_instance_section(&s)?;
1276                for instance in s {
1277                    let types = self.validator.types(0).unwrap();
1278                    let ty = types.component_instance_at(index);
1279                    let init = match instance? {
1280                        wasmparser::ComponentInstance::Instantiate {
1281                            component_index,
1282                            args,
1283                        } => {
1284                            let index = ComponentIndex::from_u32(component_index);
1285                            self.instantiate_component(index, &args, ty)?
1286                        }
1287                        wasmparser::ComponentInstance::FromExports(exports) => {
1288                            self.instantiate_component_from_exports(&exports, ty)?
1289                        }
1290                    };
1291                    self.result.initializers.push(init);
1292                    index += 1;
1293                }
1294            }
1295
1296            // Exports don't actually fill out the `initializers` array but
1297            // instead fill out the one other field in a `Translation`, the
1298            // `exports` field (as one might imagine). This for now simply
1299            // records the index of what's exported and that's tracked further
1300            // later during inlining.
1301            Payload::ComponentExportSection(s) => {
1302                self.validator.component_export_section(&s)?;
1303                for export in s {
1304                    let export = export?;
1305                    let item = self.kind_to_item(export.kind, export.index)?;
1306                    let prev = self.result.exports.insert(export.name.0, item);
1307                    assert!(prev.is_none());
1308                    self.result
1309                        .initializers
1310                        .push(LocalInitializer::Export(item));
1311                }
1312            }
1313
1314            Payload::ComponentStartSection { start, range } => {
1315                self.validator.component_start_section(&start, &range)?;
1316                unimplemented!("component start section");
1317            }
1318
1319            // Aliases of instance exports (either core or component) will be
1320            // recorded as an initializer of the appropriate type with outer
1321            // aliases handled specially via upvars and type processing.
1322            Payload::ComponentAliasSection(s) => {
1323                self.validator.component_alias_section(&s)?;
1324                for alias in s {
1325                    let init = match alias? {
1326                        wasmparser::ComponentAlias::InstanceExport {
1327                            kind: _,
1328                            instance_index,
1329                            name,
1330                        } => {
1331                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1332                            LocalInitializer::AliasComponentExport(instance, name)
1333                        }
1334                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1335                            self.alias_component_outer(kind, count, index);
1336                            continue;
1337                        }
1338                        wasmparser::ComponentAlias::CoreInstanceExport {
1339                            kind,
1340                            instance_index,
1341                            name,
1342                        } => {
1343                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1344                            self.alias_module_instance_export(kind, instance, name)
1345                        }
1346                    };
1347                    self.result.initializers.push(init);
1348                }
1349            }
1350
1351            // All custom sections are ignored by Wasmtime at this time.
1352            //
1353            // FIXME(WebAssembly/component-model#14): probably want to specify
1354            // and parse a `name` section here.
1355            Payload::CustomSection { .. } => {}
1356
1357            // Anything else is either not reachable since we never enable the
1358            // feature in Wasmtime or we do enable it and it's a bug we don't
1359            // implement it, so let validation take care of most errors here and
1360            // if it gets past validation provide a helpful error message to
1361            // debug.
1362            other => {
1363                self.validator.payload(&other)?;
1364                panic!("unimplemented section {other:?}");
1365            }
1366        }
1367
1368        Ok(Action::KeepGoing)
1369    }
1370
1371    fn instantiate_module(
1372        &mut self,
1373        module: ModuleIndex,
1374        raw_args: &[wasmparser::InstantiationArg<'data>],
1375    ) -> LocalInitializer<'data> {
1376        let mut args = HashMap::with_capacity(raw_args.len());
1377        for arg in raw_args {
1378            match arg.kind {
1379                wasmparser::InstantiationArgKind::Instance => {
1380                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1381                    args.insert(arg.name, idx);
1382                }
1383            }
1384        }
1385        LocalInitializer::ModuleInstantiate(module, args)
1386    }
1387
1388    /// Creates a synthetic module from the list of items currently in the
1389    /// module and their given names.
1390    fn instantiate_module_from_exports(
1391        &mut self,
1392        exports: &[wasmparser::Export<'data>],
1393    ) -> LocalInitializer<'data> {
1394        let mut map = HashMap::with_capacity(exports.len());
1395        for export in exports {
1396            let idx = match export.kind {
1397                wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1398                    let index = FuncIndex::from_u32(export.index);
1399                    EntityIndex::Function(index)
1400                }
1401                wasmparser::ExternalKind::Table => {
1402                    let index = TableIndex::from_u32(export.index);
1403                    EntityIndex::Table(index)
1404                }
1405                wasmparser::ExternalKind::Memory => {
1406                    let index = MemoryIndex::from_u32(export.index);
1407                    EntityIndex::Memory(index)
1408                }
1409                wasmparser::ExternalKind::Global => {
1410                    let index = GlobalIndex::from_u32(export.index);
1411                    EntityIndex::Global(index)
1412                }
1413                wasmparser::ExternalKind::Tag => {
1414                    let index = TagIndex::from_u32(export.index);
1415                    EntityIndex::Tag(index)
1416                }
1417            };
1418            map.insert(export.name, idx);
1419        }
1420        LocalInitializer::ModuleSynthetic(map)
1421    }
1422
1423    fn instantiate_component(
1424        &mut self,
1425        component: ComponentIndex,
1426        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1427        ty: ComponentInstanceTypeId,
1428    ) -> Result<LocalInitializer<'data>> {
1429        let mut args = HashMap::with_capacity(raw_args.len());
1430        for arg in raw_args {
1431            let idx = self.kind_to_item(arg.kind, arg.index)?;
1432            args.insert(arg.name, idx);
1433        }
1434
1435        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1436    }
1437
1438    /// Creates a synthetic module from the list of items currently in the
1439    /// module and their given names.
1440    fn instantiate_component_from_exports(
1441        &mut self,
1442        exports: &[wasmparser::ComponentExport<'data>],
1443        ty: ComponentInstanceTypeId,
1444    ) -> Result<LocalInitializer<'data>> {
1445        let mut map = HashMap::with_capacity(exports.len());
1446        for export in exports {
1447            let idx = self.kind_to_item(export.kind, export.index)?;
1448            map.insert(export.name.0, idx);
1449        }
1450
1451        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1452    }
1453
1454    fn kind_to_item(
1455        &mut self,
1456        kind: wasmparser::ComponentExternalKind,
1457        index: u32,
1458    ) -> Result<ComponentItem> {
1459        Ok(match kind {
1460            wasmparser::ComponentExternalKind::Func => {
1461                let index = ComponentFuncIndex::from_u32(index);
1462                ComponentItem::Func(index)
1463            }
1464            wasmparser::ComponentExternalKind::Module => {
1465                let index = ModuleIndex::from_u32(index);
1466                ComponentItem::Module(index)
1467            }
1468            wasmparser::ComponentExternalKind::Instance => {
1469                let index = ComponentInstanceIndex::from_u32(index);
1470                ComponentItem::ComponentInstance(index)
1471            }
1472            wasmparser::ComponentExternalKind::Component => {
1473                let index = ComponentIndex::from_u32(index);
1474                ComponentItem::Component(index)
1475            }
1476            wasmparser::ComponentExternalKind::Value => {
1477                unimplemented!("component values");
1478            }
1479            wasmparser::ComponentExternalKind::Type => {
1480                let types = self.validator.types(0).unwrap();
1481                let ty = types.component_any_type_at(index);
1482                ComponentItem::Type(ty)
1483            }
1484        })
1485    }
1486
1487    fn alias_module_instance_export(
1488        &mut self,
1489        kind: wasmparser::ExternalKind,
1490        instance: ModuleInstanceIndex,
1491        name: &'data str,
1492    ) -> LocalInitializer<'data> {
1493        match kind {
1494            wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1495                LocalInitializer::AliasExportFunc(instance, name)
1496            }
1497            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1498            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1499            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1500            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1501        }
1502    }
1503
1504    fn alias_component_outer(
1505        &mut self,
1506        kind: wasmparser::ComponentOuterAliasKind,
1507        count: u32,
1508        index: u32,
1509    ) {
1510        match kind {
1511            wasmparser::ComponentOuterAliasKind::CoreType
1512            | wasmparser::ComponentOuterAliasKind::Type => {}
1513
1514            // For more information about the implementation of outer aliases
1515            // see the documentation of `LexicalScope`. Otherwise though the
1516            // main idea here is that the data to close over starts as `Local`
1517            // and then transitions to `Upvar` as its inserted into the parents
1518            // in order from target we're aliasing back to the current
1519            // component.
1520            wasmparser::ComponentOuterAliasKind::CoreModule => {
1521                let index = ModuleIndex::from_u32(index);
1522                let mut module = ClosedOverModule::Local(index);
1523                let depth = self.lexical_scopes.len() - (count as usize);
1524                for frame in self.lexical_scopes[depth..].iter_mut() {
1525                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1526                }
1527
1528                // If the `module` is still `Local` then the `depth` was 0 and
1529                // it's an alias into our own space. Otherwise it's switched to
1530                // an upvar and will index into the upvar space. Either way
1531                // it's just plumbed directly into the initializer.
1532                self.result
1533                    .initializers
1534                    .push(LocalInitializer::AliasModule(module));
1535            }
1536            wasmparser::ComponentOuterAliasKind::Component => {
1537                let index = ComponentIndex::from_u32(index);
1538                let mut component = ClosedOverComponent::Local(index);
1539                let depth = self.lexical_scopes.len() - (count as usize);
1540                for frame in self.lexical_scopes[depth..].iter_mut() {
1541                    component =
1542                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1543                }
1544
1545                self.result
1546                    .initializers
1547                    .push(LocalInitializer::AliasComponent(component));
1548            }
1549        }
1550    }
1551
1552    fn canonical_options(
1553        &mut self,
1554        opts: &[wasmparser::CanonicalOption],
1555        core_func_index: u32,
1556    ) -> WasmResult<LocalCanonicalOptions> {
1557        let core_type = self.core_func_signature(core_func_index)?;
1558
1559        let mut string_encoding = StringEncoding::Utf8;
1560        let mut post_return = None;
1561        let mut async_ = false;
1562        let mut callback = None;
1563        let mut memory = None;
1564        let mut realloc = None;
1565        let mut gc = false;
1566
1567        for opt in opts {
1568            match opt {
1569                wasmparser::CanonicalOption::UTF8 => {
1570                    string_encoding = StringEncoding::Utf8;
1571                }
1572                wasmparser::CanonicalOption::UTF16 => {
1573                    string_encoding = StringEncoding::Utf16;
1574                }
1575                wasmparser::CanonicalOption::CompactUTF16 => {
1576                    string_encoding = StringEncoding::CompactUtf16;
1577                }
1578                wasmparser::CanonicalOption::Memory(idx) => {
1579                    let idx = MemoryIndex::from_u32(*idx);
1580                    memory = Some(idx);
1581                }
1582                wasmparser::CanonicalOption::Realloc(idx) => {
1583                    let idx = FuncIndex::from_u32(*idx);
1584                    realloc = Some(idx);
1585                }
1586                wasmparser::CanonicalOption::PostReturn(idx) => {
1587                    let idx = FuncIndex::from_u32(*idx);
1588                    post_return = Some(idx);
1589                }
1590                wasmparser::CanonicalOption::Async => async_ = true,
1591                wasmparser::CanonicalOption::Callback(idx) => {
1592                    let idx = FuncIndex::from_u32(*idx);
1593                    callback = Some(idx);
1594                }
1595                wasmparser::CanonicalOption::CoreType(idx) => {
1596                    if cfg!(debug_assertions) {
1597                        let types = self.validator.types(0).unwrap();
1598                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1599                        let interned = self
1600                            .types
1601                            .module_types_builder()
1602                            .intern_type(types, core_ty_id)?;
1603                        debug_assert_eq!(interned, core_type);
1604                    }
1605                }
1606                wasmparser::CanonicalOption::Gc => {
1607                    gc = true;
1608                }
1609            }
1610        }
1611
1612        Ok(LocalCanonicalOptions {
1613            string_encoding,
1614            post_return,
1615            cancellable: false,
1616            async_,
1617            callback,
1618            core_type,
1619            data_model: if gc {
1620                LocalDataModel::Gc {}
1621            } else {
1622                LocalDataModel::LinearMemory { memory, realloc }
1623            },
1624        })
1625    }
1626
1627    /// Get the interned type index for the `index`th core function.
1628    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1629        let types = self.validator.types(0).unwrap();
1630        let id = types.core_function_at(index);
1631        self.types.module_types_builder().intern_type(types, id)
1632    }
1633
1634    fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1635        self.lexical_scopes.is_empty()
1636            && self
1637                .unsafe_intrinsics_import
1638                .is_some_and(|name| import == name)
1639    }
1640
1641    fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1642        let types = &self.validator.types(0).unwrap();
1643
1644        let ComponentEntityType::Instance(instance_ty) = ty else {
1645            bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1646        };
1647        let instance_ty = &types[instance_ty];
1648
1649        ensure!(
1650            instance_ty.defined_resources.is_empty(),
1651            "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1652        );
1653        ensure!(
1654            instance_ty.explicit_resources.is_empty(),
1655            "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1656        );
1657
1658        for (name, ty) in &instance_ty.exports {
1659            let ComponentEntityType::Func(func_ty) = ty else {
1660                bail!(
1661                    "bad unsafe intrinsics import: imported instance `{import}` must \
1662                     only export functions"
1663                )
1664            };
1665            let func_ty = &types[*func_ty];
1666
1667            fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1668                use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1669                match (a, b) {
1670                    (InterfaceType::U8, C::Primitive(P::U8)) => true,
1671                    (InterfaceType::U8, _) => false,
1672
1673                    (InterfaceType::U16, C::Primitive(P::U16)) => true,
1674                    (InterfaceType::U16, _) => false,
1675
1676                    (InterfaceType::U32, C::Primitive(P::U32)) => true,
1677                    (InterfaceType::U32, _) => false,
1678
1679                    (InterfaceType::U64, C::Primitive(P::U64)) => true,
1680                    (InterfaceType::U64, _) => false,
1681
1682                    (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1683                }
1684            }
1685
1686            fn check_types<'a>(
1687                expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1688                actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1689                kind: &str,
1690                import: &str,
1691                name: &str,
1692            ) -> Result<()> {
1693                let expected_len = expected.len();
1694                let actual_len = actual.len();
1695                ensure!(
1696                    expected_len == actual_len,
1697                    "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1698                     {expected_len} {kind}, found {actual_len}"
1699                );
1700
1701                for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1702                    ensure!(
1703                        ty_eq(expected_ty, actual_ty),
1704                        "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1705                         `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1706                    );
1707                }
1708                Ok(())
1709            }
1710
1711            let intrinsic = UnsafeIntrinsic::from_str(name)
1712                .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1713
1714            check_types(
1715                intrinsic.component_params().iter(),
1716                func_ty.params.iter().map(|(_name, ty)| ty),
1717                "parameters",
1718                &import,
1719                &name,
1720            )?;
1721            check_types(
1722                intrinsic.component_results().iter(),
1723                func_ty.result.iter(),
1724                "results",
1725                &import,
1726                &name,
1727            )?;
1728        }
1729
1730        Ok(())
1731    }
1732}
1733
1734impl Translation<'_> {
1735    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1736        self.types.as_ref().unwrap().as_ref()
1737    }
1738}
1739
1740/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1741/// to disallow access to mutable access to the builder before the inlining
1742/// pass.
1743///
1744/// Type information in this translation pass must be preserved at the
1745/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1746/// own type system. Only during inlining are types fully assigned because
1747/// that's when resource types become available as it's known which instance
1748/// defines which resource, or more concretely the same component instantiated
1749/// twice will produce two unique resource types unlike one as seen by
1750/// wasmparser within the component.
1751mod pre_inlining {
1752    use super::*;
1753
1754    pub struct PreInliningComponentTypes<'a> {
1755        types: &'a mut ComponentTypesBuilder,
1756    }
1757
1758    impl<'a> PreInliningComponentTypes<'a> {
1759        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1760            Self { types }
1761        }
1762
1763        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1764            self.types.module_types_builder_mut()
1765        }
1766
1767        pub fn types(&self) -> &ComponentTypesBuilder {
1768            self.types
1769        }
1770
1771        // NB: this should in theory only be used for the `inline` phase of
1772        // translation.
1773        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1774            self.types
1775        }
1776    }
1777
1778    impl TypeConvert for PreInliningComponentTypes<'_> {
1779        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1780            self.types.lookup_heap_type(index)
1781        }
1782
1783        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1784            self.types.lookup_type_index(index)
1785        }
1786    }
1787}
1788use pre_inlining::PreInliningComponentTypes;