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