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