wasmtime_environ/component/
translate.rs

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