Skip to main content

wasmtime_environ/component/
translate.rs

1use crate::Abi;
2use crate::component::dfg::AbstractInstantiations;
3use crate::component::*;
4use crate::prelude::*;
5use crate::{
6    EngineOrModuleTypeIndex, EntityIndex, FuncKey, ModuleEnvironment, ModuleInternedTypeIndex,
7    ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex, Tunables, TypeConvert,
8    WasmHeapType, WasmResult, WasmValType,
9};
10use core::str::FromStr;
11use cranelift_entity::SecondaryMap;
12use cranelift_entity::packed_option::PackedOption;
13use indexmap::IndexMap;
14use std::collections::HashMap;
15use std::mem;
16use wasmparser::component_types::{
17    AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
18    ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
19};
20use wasmparser::types::Types;
21use wasmparser::{Chunk, ComponentExternName, Encoding, Parser, Payload, Validator};
22
23mod adapt;
24pub use self::adapt::*;
25mod inline;
26
27/// Structure used to translate a component and parse it.
28pub struct Translator<'a, 'data> {
29    /// The current component being translated.
30    ///
31    /// This will get swapped out as translation traverses the body of a
32    /// component and a sub-component is entered or left.
33    result: Translation<'data>,
34
35    /// Current state of parsing a binary component. Note that like `result`
36    /// this will change as the component is traversed.
37    parser: Parser,
38
39    /// Stack of lexical scopes that are in-progress but not finished yet.
40    ///
41    /// This is pushed to whenever a component is entered and popped from
42    /// whenever a component is left. Each lexical scope also contains
43    /// information about the variables that it is currently required to close
44    /// over which is threaded into the current in-progress translation of
45    /// the sub-component which pushed a scope here.
46    lexical_scopes: Vec<LexicalScope<'data>>,
47
48    /// The validator in use to verify that the raw input binary is a valid
49    /// component.
50    validator: &'a mut Validator,
51
52    /// Type information shared for the entire component.
53    ///
54    /// This builder is also used for all core wasm modules found to intern
55    /// signatures across all modules.
56    types: PreInliningComponentTypes<'a>,
57
58    /// The compiler configuration provided by the embedder.
59    tunables: &'a Tunables,
60
61    /// Auxiliary location to push generated adapter modules onto.
62    scope_vec: &'data ScopeVec<u8>,
63
64    /// Completely translated core wasm modules that have been found so far.
65    ///
66    /// Note that this translation only involves learning about type
67    /// information and functions are not actually compiled here.
68    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
69
70    /// Completely translated components that have been found so far.
71    ///
72    /// As frames are popped from `lexical_scopes` their completed component
73    /// will be pushed onto this list.
74    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
75
76    /// The top-level import name for Wasmtime's unsafe intrinsics, if any.
77    unsafe_intrinsics_import: Option<&'a str>,
78}
79
80/// Representation of the syntactic scope of a component meaning where it is
81/// and what its state is at in the binary format.
82///
83/// These scopes are pushed and popped when a sub-component starts being
84/// parsed and finishes being parsed. The main purpose of this frame is to
85/// have a `ClosedOverVars` field which encapsulates data that is inherited
86/// from the scope specified into the component being translated just beneath
87/// it.
88///
89/// This structure exists to implement outer aliases to components and modules.
90/// When a component or module is closed over then that means it needs to be
91/// inherited in a sense to the component which actually had the alias. This is
92/// achieved with a deceptively simple scheme where each parent of the
93/// component with the alias will inherit the component from the desired
94/// location.
95///
96/// For example with a component structure that looks like:
97///
98/// ```wasm
99/// (component $A
100///     (core module $M)
101///     (component $B
102///         (component $C
103///             (alias outer $A $M (core module))
104///         )
105///     )
106/// )
107/// ```
108///
109/// here the `C` component is closing over `M` located in the root component
110/// `A`. When `C` is being translated the `lexical_scopes` field will look like
111/// `[A, B]`. When the alias is encountered (for module index 0) this will
112/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
113/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
114/// inserted into `closure_args` in `B`'s frame. This produces yet another
115/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
116/// via `LocalInitializer::AliasModuleUpvar` with the last index.
117///
118/// All of these upvar indices and such are interpreted in the "inline" phase
119/// of compilation and not at runtime. This means that when `A` is being
120/// instantiated one of its initializers will be
121/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
122/// variables captured for `B` are listed as local module 0, or `M`. This list
123/// is then preserved in the definition of the component `B` and later reused
124/// by `C` again to finally get access to the closed over component.
125///
126/// Effectively the scopes are managed hierarchically where a reference to an
127/// outer variable automatically injects references into all parents up to
128/// where the reference is. This variable scopes are the processed during
129/// inlining where a component definition is a reference to the static
130/// component information (`Translation`) plus closed over variables
131/// (`ComponentClosure` during inlining).
132struct LexicalScope<'data> {
133    /// Current state of translating the `translation` below.
134    parser: Parser,
135    /// Current state of the component's translation as found so far.
136    translation: Translation<'data>,
137    /// List of captures that `translation` will need to process to create the
138    /// sub-component which is directly beneath this lexical scope.
139    closure_args: ClosedOverVars,
140}
141
142/// A "local" translation of a component.
143///
144/// This structure is used as a sort of in-progress translation of a component.
145/// This is not `Component` which is the final form as consumed by Wasmtime
146/// at runtime. Instead this is a fairly simple representation of a component
147/// where almost everything is ordered as a list of initializers. The binary
148/// format is translated to a list of initializers here which is later processed
149/// during "inlining" to produce a final component with the final set of
150/// initializers.
151#[derive(Default)]
152struct Translation<'data> {
153    /// Instructions which form this component.
154    ///
155    /// There is one initializer for all members of each index space, and all
156    /// index spaces are incrementally built here as the initializer list is
157    /// processed.
158    initializers: Vec<LocalInitializer<'data>>,
159
160    /// The list of exports from this component, as pairs of names and an
161    /// index into an index space of what's being exported.
162    exports: IndexMap<&'data str, (ComponentItem, 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                    CoreDef::Trampoline(_) => continue,
627
628                    // This import is a compile-time builtin intrinsic, we
629                    // should inline its implementation during function
630                    // translation.
631                    CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i),
632
633                    // This imported function is an export from another
634                    // instance, a perfect candidate for becoming an inlinable
635                    // direct call!
636                    CoreDef::Export(export) => {
637                        let Some(arg_module) = &instance_to_module[export.instance].expand() else {
638                            // Instance of a dynamic module that is not part of
639                            // this component, not a statically-known module
640                            // inside this component. We have to do an indirect
641                            // call.
642                            continue;
643                        };
644
645                        let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
646                        else {
647                            unreachable!("function imports must be functions")
648                        };
649
650                        let Some(arg_module_def_func) = self.static_modules[*arg_module]
651                            .module
652                            .defined_func_index(*arg_func)
653                        else {
654                            // TODO: we should ideally follow re-export chains
655                            // to bottom out the instantiation argument in
656                            // either a definition or an import at the root
657                            // component boundary. In practice, this pattern is
658                            // rare, so following these chains is left for the
659                            // Future.
660                            continue;
661                        };
662
663                        FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func)
664                    }
665                };
666
667                assert!(
668                    self.static_modules[module].known_imported_functions[imported_func].is_none()
669                );
670                self.static_modules[module].known_imported_functions[imported_func] =
671                    Some(known_func);
672            }
673        }
674    }
675
676    fn translate_payload(
677        &mut self,
678        payload: Payload<'data>,
679        component: &'data [u8],
680    ) -> Result<Action> {
681        match payload {
682            Payload::Version {
683                num,
684                encoding,
685                range,
686            } => {
687                self.validator.version(num, encoding, &range)?;
688
689                match encoding {
690                    Encoding::Component => {}
691                    Encoding::Module => {
692                        bail!("attempted to parse a wasm module with a component parser");
693                    }
694                }
695            }
696
697            Payload::End(offset) => {
698                assert!(self.result.types.is_none());
699                self.result.types = Some(self.validator.end(offset)?);
700
701                // Exit the current lexical scope. If there is no parent (no
702                // frame currently on the stack) then translation is finished.
703                // Otherwise that means that a nested component has been
704                // completed and is recorded as such.
705                let LexicalScope {
706                    parser,
707                    translation,
708                    closure_args,
709                } = match self.lexical_scopes.pop() {
710                    Some(frame) => frame,
711                    None => return Ok(Action::Done),
712                };
713                self.parser = parser;
714                let component = mem::replace(&mut self.result, translation);
715                let static_idx = self.static_components.push(component);
716                self.result
717                    .initializers
718                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
719            }
720
721            // When we see a type section the types are validated and then
722            // translated into Wasmtime's representation. Each active type
723            // definition is recorded in the `ComponentTypesBuilder` tables, or
724            // this component's active scope.
725            //
726            // Note that the push/pop of the component types scope happens above
727            // in `Version` and `End` since multiple type sections can appear
728            // within a component.
729            Payload::ComponentTypeSection(s) => {
730                let mut component_type_index =
731                    self.validator.types(0).unwrap().component_type_count();
732                self.validator.component_type_section(&s)?;
733
734                // Look for resource types and if a local resource is defined
735                // then an initializer is added to define that resource type and
736                // reference its destructor.
737                let types = self.validator.types(0).unwrap();
738                for ty in s {
739                    match ty? {
740                        wasmparser::ComponentType::Resource { rep, dtor } => {
741                            let rep = self.types.convert_valtype(rep)?;
742                            let id = types
743                                .component_any_type_at(component_type_index)
744                                .unwrap_resource();
745                            let dtor = dtor.map(FuncIndex::from_u32);
746                            self.result
747                                .initializers
748                                .push(LocalInitializer::Resource(id, rep, dtor));
749                        }
750
751                        // no extra processing needed
752                        wasmparser::ComponentType::Defined(_)
753                        | wasmparser::ComponentType::Func(_)
754                        | wasmparser::ComponentType::Instance(_)
755                        | wasmparser::ComponentType::Component(_) => {}
756                    }
757
758                    component_type_index += 1;
759                }
760            }
761            Payload::CoreTypeSection(s) => {
762                self.validator.core_type_section(&s)?;
763            }
764
765            // Processing the import section at this point is relatively simple
766            // which is to simply record the name of the import and the type
767            // information associated with it.
768            Payload::ComponentImportSection(s) => {
769                self.validator.component_import_section(&s)?;
770                for import in s {
771                    let import = import?;
772                    let types = self.validator.types(0).unwrap();
773                    let ty = types
774                        .component_item_for_import(import.name.name)
775                        .unwrap()
776                        .ty;
777
778                    if self.is_unsafe_intrinsics_import(import.name.name) {
779                        self.check_unsafe_intrinsics_import(import.name.name, ty)?;
780                        self.result
781                            .initializers
782                            .push(LocalInitializer::IntrinsicsImport);
783                    } else {
784                        self.result
785                            .initializers
786                            .push(LocalInitializer::Import(import.name, ty));
787                    }
788                }
789            }
790
791            // Entries in the canonical section will get initializers recorded
792            // with the listed options for lifting/lowering.
793            Payload::ComponentCanonicalSection(s) => {
794                let types = self.validator.types(0).unwrap();
795                let mut core_func_index = types.function_count();
796                self.validator.component_canonical_section(&s)?;
797                for func in s {
798                    let init = match func? {
799                        wasmparser::CanonicalFunction::Lift {
800                            type_index,
801                            core_func_index,
802                            options,
803                        } => {
804                            let ty = self
805                                .validator
806                                .types(0)
807                                .unwrap()
808                                .component_any_type_at(type_index)
809                                .unwrap_func();
810
811                            let func = FuncIndex::from_u32(core_func_index);
812                            let options = self.canonical_options(&options, core_func_index)?;
813                            LocalInitializer::Lift(ty, func, options)
814                        }
815                        wasmparser::CanonicalFunction::Lower {
816                            func_index,
817                            options,
818                        } => {
819                            let lower_ty = self
820                                .validator
821                                .types(0)
822                                .unwrap()
823                                .component_function_at(func_index);
824                            let func = ComponentFuncIndex::from_u32(func_index);
825                            let options = self.canonical_options(&options, core_func_index)?;
826                            core_func_index += 1;
827                            LocalInitializer::Lower {
828                                func,
829                                options,
830                                lower_ty,
831                            }
832                        }
833                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
834                            let resource = self
835                                .validator
836                                .types(0)
837                                .unwrap()
838                                .component_any_type_at(resource)
839                                .unwrap_resource();
840                            let ty = self.core_func_signature(core_func_index)?;
841                            core_func_index += 1;
842                            LocalInitializer::ResourceNew(resource, ty)
843                        }
844                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
845                            let resource = self
846                                .validator
847                                .types(0)
848                                .unwrap()
849                                .component_any_type_at(resource)
850                                .unwrap_resource();
851                            let ty = self.core_func_signature(core_func_index)?;
852                            core_func_index += 1;
853                            LocalInitializer::ResourceDrop(resource, ty)
854                        }
855                        wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
856                            let _ = resource;
857                            bail!("support for `resource.drop async` not implemented yet")
858                        }
859                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
860                            let resource = self
861                                .validator
862                                .types(0)
863                                .unwrap()
864                                .component_any_type_at(resource)
865                                .unwrap_resource();
866                            let ty = self.core_func_signature(core_func_index)?;
867                            core_func_index += 1;
868                            LocalInitializer::ResourceRep(resource, ty)
869                        }
870                        wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
871                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
872                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
873                            bail!("unsupported intrinsic")
874                        }
875                        wasmparser::CanonicalFunction::BackpressureInc => {
876                            let core_type = self.core_func_signature(core_func_index)?;
877                            core_func_index += 1;
878                            LocalInitializer::BackpressureInc { func: core_type }
879                        }
880                        wasmparser::CanonicalFunction::BackpressureDec => {
881                            let core_type = self.core_func_signature(core_func_index)?;
882                            core_func_index += 1;
883                            LocalInitializer::BackpressureDec { func: core_type }
884                        }
885
886                        wasmparser::CanonicalFunction::TaskReturn { result, options } => {
887                            let result = result.map(|ty| match ty {
888                                wasmparser::ComponentValType::Primitive(ty) => {
889                                    ComponentValType::Primitive(ty)
890                                }
891                                wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
892                                    self.validator
893                                        .types(0)
894                                        .unwrap()
895                                        .component_defined_type_at(ty),
896                                ),
897                            });
898                            let options = self.canonical_options(&options, core_func_index)?;
899                            core_func_index += 1;
900                            LocalInitializer::TaskReturn { result, options }
901                        }
902                        wasmparser::CanonicalFunction::TaskCancel => {
903                            let func = self.core_func_signature(core_func_index)?;
904                            core_func_index += 1;
905                            LocalInitializer::TaskCancel { func }
906                        }
907                        wasmparser::CanonicalFunction::WaitableSetNew => {
908                            let func = self.core_func_signature(core_func_index)?;
909                            core_func_index += 1;
910                            LocalInitializer::WaitableSetNew { func }
911                        }
912                        wasmparser::CanonicalFunction::WaitableSetWait {
913                            cancellable,
914                            memory,
915                        } => {
916                            let core_type = self.core_func_signature(core_func_index)?;
917                            core_func_index += 1;
918                            LocalInitializer::WaitableSetWait {
919                                options: LocalCanonicalOptions {
920                                    core_type,
921                                    cancellable,
922                                    async_: false,
923                                    data_model: LocalDataModel::LinearMemory {
924                                        memory: Some(MemoryIndex::from_u32(memory)),
925                                        realloc: None,
926                                    },
927                                    post_return: None,
928                                    callback: None,
929                                    string_encoding: StringEncoding::Utf8,
930                                },
931                            }
932                        }
933                        wasmparser::CanonicalFunction::WaitableSetPoll {
934                            cancellable,
935                            memory,
936                        } => {
937                            let core_type = self.core_func_signature(core_func_index)?;
938                            core_func_index += 1;
939                            LocalInitializer::WaitableSetPoll {
940                                options: LocalCanonicalOptions {
941                                    core_type,
942                                    async_: false,
943                                    cancellable,
944                                    data_model: LocalDataModel::LinearMemory {
945                                        memory: Some(MemoryIndex::from_u32(memory)),
946                                        realloc: None,
947                                    },
948                                    post_return: None,
949                                    callback: None,
950                                    string_encoding: StringEncoding::Utf8,
951                                },
952                            }
953                        }
954                        wasmparser::CanonicalFunction::WaitableSetDrop => {
955                            let func = self.core_func_signature(core_func_index)?;
956                            core_func_index += 1;
957                            LocalInitializer::WaitableSetDrop { func }
958                        }
959                        wasmparser::CanonicalFunction::WaitableJoin => {
960                            let func = self.core_func_signature(core_func_index)?;
961                            core_func_index += 1;
962                            LocalInitializer::WaitableJoin { func }
963                        }
964                        wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
965                            let func = self.core_func_signature(core_func_index)?;
966                            core_func_index += 1;
967                            LocalInitializer::ThreadYield { func, cancellable }
968                        }
969                        wasmparser::CanonicalFunction::SubtaskDrop => {
970                            let func = self.core_func_signature(core_func_index)?;
971                            core_func_index += 1;
972                            LocalInitializer::SubtaskDrop { func }
973                        }
974                        wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
975                            let func = self.core_func_signature(core_func_index)?;
976                            core_func_index += 1;
977                            LocalInitializer::SubtaskCancel { func, async_ }
978                        }
979                        wasmparser::CanonicalFunction::StreamNew { ty } => {
980                            let ty = self
981                                .validator
982                                .types(0)
983                                .unwrap()
984                                .component_defined_type_at(ty);
985                            let func = self.core_func_signature(core_func_index)?;
986                            core_func_index += 1;
987                            LocalInitializer::StreamNew { ty, func }
988                        }
989                        wasmparser::CanonicalFunction::StreamRead { ty, options } => {
990                            let ty = self
991                                .validator
992                                .types(0)
993                                .unwrap()
994                                .component_defined_type_at(ty);
995                            let options = self.canonical_options(&options, core_func_index)?;
996                            core_func_index += 1;
997                            LocalInitializer::StreamRead { ty, options }
998                        }
999                        wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
1000                            let ty = self
1001                                .validator
1002                                .types(0)
1003                                .unwrap()
1004                                .component_defined_type_at(ty);
1005                            let options = self.canonical_options(&options, core_func_index)?;
1006                            core_func_index += 1;
1007                            LocalInitializer::StreamWrite { ty, options }
1008                        }
1009                        wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1010                            let ty = self
1011                                .validator
1012                                .types(0)
1013                                .unwrap()
1014                                .component_defined_type_at(ty);
1015                            let func = self.core_func_signature(core_func_index)?;
1016                            core_func_index += 1;
1017                            LocalInitializer::StreamCancelRead { ty, func, async_ }
1018                        }
1019                        wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1020                            let ty = self
1021                                .validator
1022                                .types(0)
1023                                .unwrap()
1024                                .component_defined_type_at(ty);
1025                            let func = self.core_func_signature(core_func_index)?;
1026                            core_func_index += 1;
1027                            LocalInitializer::StreamCancelWrite { ty, func, async_ }
1028                        }
1029                        wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1030                            let ty = self
1031                                .validator
1032                                .types(0)
1033                                .unwrap()
1034                                .component_defined_type_at(ty);
1035                            let func = self.core_func_signature(core_func_index)?;
1036                            core_func_index += 1;
1037                            LocalInitializer::StreamDropReadable { ty, func }
1038                        }
1039                        wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1040                            let ty = self
1041                                .validator
1042                                .types(0)
1043                                .unwrap()
1044                                .component_defined_type_at(ty);
1045                            let func = self.core_func_signature(core_func_index)?;
1046                            core_func_index += 1;
1047                            LocalInitializer::StreamDropWritable { ty, func }
1048                        }
1049                        wasmparser::CanonicalFunction::FutureNew { ty } => {
1050                            let ty = self
1051                                .validator
1052                                .types(0)
1053                                .unwrap()
1054                                .component_defined_type_at(ty);
1055                            let func = self.core_func_signature(core_func_index)?;
1056                            core_func_index += 1;
1057                            LocalInitializer::FutureNew { ty, func }
1058                        }
1059                        wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1060                            let ty = self
1061                                .validator
1062                                .types(0)
1063                                .unwrap()
1064                                .component_defined_type_at(ty);
1065                            let options = self.canonical_options(&options, core_func_index)?;
1066                            core_func_index += 1;
1067                            LocalInitializer::FutureRead { ty, options }
1068                        }
1069                        wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1070                            let ty = self
1071                                .validator
1072                                .types(0)
1073                                .unwrap()
1074                                .component_defined_type_at(ty);
1075                            let options = self.canonical_options(&options, core_func_index)?;
1076                            core_func_index += 1;
1077                            LocalInitializer::FutureWrite { ty, options }
1078                        }
1079                        wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1080                            let ty = self
1081                                .validator
1082                                .types(0)
1083                                .unwrap()
1084                                .component_defined_type_at(ty);
1085                            let func = self.core_func_signature(core_func_index)?;
1086                            core_func_index += 1;
1087                            LocalInitializer::FutureCancelRead { ty, func, async_ }
1088                        }
1089                        wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1090                            let ty = self
1091                                .validator
1092                                .types(0)
1093                                .unwrap()
1094                                .component_defined_type_at(ty);
1095                            let func = self.core_func_signature(core_func_index)?;
1096                            core_func_index += 1;
1097                            LocalInitializer::FutureCancelWrite { ty, func, async_ }
1098                        }
1099                        wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1100                            let ty = self
1101                                .validator
1102                                .types(0)
1103                                .unwrap()
1104                                .component_defined_type_at(ty);
1105                            let func = self.core_func_signature(core_func_index)?;
1106                            core_func_index += 1;
1107                            LocalInitializer::FutureDropReadable { ty, func }
1108                        }
1109                        wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1110                            let ty = self
1111                                .validator
1112                                .types(0)
1113                                .unwrap()
1114                                .component_defined_type_at(ty);
1115                            let func = self.core_func_signature(core_func_index)?;
1116                            core_func_index += 1;
1117                            LocalInitializer::FutureDropWritable { ty, func }
1118                        }
1119                        wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1120                            let options = self.canonical_options(&options, core_func_index)?;
1121                            core_func_index += 1;
1122                            LocalInitializer::ErrorContextNew { options }
1123                        }
1124                        wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1125                            let options = self.canonical_options(&options, core_func_index)?;
1126                            core_func_index += 1;
1127                            LocalInitializer::ErrorContextDebugMessage { options }
1128                        }
1129                        wasmparser::CanonicalFunction::ErrorContextDrop => {
1130                            let func = self.core_func_signature(core_func_index)?;
1131                            core_func_index += 1;
1132                            LocalInitializer::ErrorContextDrop { func }
1133                        }
1134                        wasmparser::CanonicalFunction::ContextGet { slot, ty } => {
1135                            if ty != wasmparser::ValType::I32 {
1136                                bail!("unsupported context.get type: {ty:?}");
1137                            }
1138                            let func = self.core_func_signature(core_func_index)?;
1139                            core_func_index += 1;
1140                            LocalInitializer::ContextGet { i: slot, func }
1141                        }
1142                        wasmparser::CanonicalFunction::ContextSet { slot, ty } => {
1143                            if ty != wasmparser::ValType::I32 {
1144                                bail!("unsupported context.set type: {ty:?}");
1145                            }
1146                            let func = self.core_func_signature(core_func_index)?;
1147                            core_func_index += 1;
1148                            LocalInitializer::ContextSet { i: slot, func }
1149                        }
1150                        wasmparser::CanonicalFunction::ThreadIndex => {
1151                            let func = self.core_func_signature(core_func_index)?;
1152                            core_func_index += 1;
1153                            LocalInitializer::ThreadIndex { func }
1154                        }
1155                        wasmparser::CanonicalFunction::ThreadNewIndirect {
1156                            func_ty_index,
1157                            table_index,
1158                        } => {
1159                            let func = self.core_func_signature(core_func_index)?;
1160                            core_func_index += 1;
1161                            LocalInitializer::ThreadNewIndirect {
1162                                func,
1163                                start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1164                                start_func_table_index: TableIndex::from_u32(table_index),
1165                            }
1166                        }
1167                        wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1168                            let func = self.core_func_signature(core_func_index)?;
1169                            core_func_index += 1;
1170                            LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1171                        }
1172                        wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1173                            let func = self.core_func_signature(core_func_index)?;
1174                            core_func_index += 1;
1175                            LocalInitializer::ThreadSuspend { func, cancellable }
1176                        }
1177                        wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1178                            let func = self.core_func_signature(core_func_index)?;
1179                            core_func_index += 1;
1180                            LocalInitializer::ThreadSuspendTo { func, cancellable }
1181                        }
1182                        wasmparser::CanonicalFunction::ThreadUnsuspend => {
1183                            let func = self.core_func_signature(core_func_index)?;
1184                            core_func_index += 1;
1185                            LocalInitializer::ThreadUnsuspend { func }
1186                        }
1187                        wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1188                            let func = self.core_func_signature(core_func_index)?;
1189                            core_func_index += 1;
1190                            LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1191                        }
1192                    };
1193                    self.result.initializers.push(init);
1194                }
1195            }
1196
1197            // Core wasm modules are translated inline directly here with the
1198            // `ModuleEnvironment` from core wasm compilation. This will return
1199            // to the caller the size of the module so it knows how many bytes
1200            // of the input are skipped.
1201            //
1202            // Note that this is just initial type translation of the core wasm
1203            // module and actual function compilation is deferred until this
1204            // entire process has completed.
1205            Payload::ModuleSection {
1206                parser,
1207                unchecked_range,
1208            } => {
1209                let index = self.validator.types(0).unwrap().module_count();
1210                self.validator.module_section(&unchecked_range)?;
1211                let static_module_index = self.static_modules.next_key();
1212                let mut translation = ModuleEnvironment::new(
1213                    self.tunables,
1214                    self.validator,
1215                    self.types.module_types_builder(),
1216                    static_module_index,
1217                )
1218                .translate(
1219                    parser,
1220                    component
1221                        .get(unchecked_range.start..unchecked_range.end)
1222                        .ok_or_else(|| {
1223                            format_err!(
1224                                "section range {}..{} is out of bounds (bound = {})",
1225                                unchecked_range.start,
1226                                unchecked_range.end,
1227                                component.len()
1228                            )
1229                            .context("wasm component contains an invalid module section")
1230                        })?,
1231                )?;
1232
1233                translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1234                let static_module_index2 = self.static_modules.push(translation);
1235                assert_eq!(static_module_index, static_module_index2);
1236                let types = self.validator.types(0).unwrap();
1237                let ty = types.module_at(index);
1238                self.result
1239                    .initializers
1240                    .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1241                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1242            }
1243
1244            // When a sub-component is found then the current translation state
1245            // is pushed onto the `lexical_scopes` stack. This will subsequently
1246            // get popped as part of `Payload::End` processing above.
1247            //
1248            // Note that the set of closure args for this new lexical scope
1249            // starts empty since it will only get populated if translation of
1250            // the nested component ends up aliasing some outer module or
1251            // component.
1252            Payload::ComponentSection {
1253                parser,
1254                unchecked_range,
1255            } => {
1256                self.validator.component_section(&unchecked_range)?;
1257                self.lexical_scopes.push(LexicalScope {
1258                    parser: mem::replace(&mut self.parser, parser),
1259                    translation: mem::take(&mut self.result),
1260                    closure_args: ClosedOverVars::default(),
1261                });
1262            }
1263
1264            // Both core wasm instances and component instances record
1265            // initializers of what form of instantiation is performed which
1266            // largely just records the arguments given from wasmparser into a
1267            // `HashMap` for processing later during inlining.
1268            Payload::InstanceSection(s) => {
1269                self.validator.instance_section(&s)?;
1270                for instance in s {
1271                    let init = match instance? {
1272                        wasmparser::Instance::Instantiate { module_index, args } => {
1273                            let index = ModuleIndex::from_u32(module_index);
1274                            self.instantiate_module(index, &args)
1275                        }
1276                        wasmparser::Instance::FromExports(exports) => {
1277                            self.instantiate_module_from_exports(&exports)
1278                        }
1279                    };
1280                    self.result.initializers.push(init);
1281                }
1282            }
1283            Payload::ComponentInstanceSection(s) => {
1284                let mut index = self.validator.types(0).unwrap().component_instance_count();
1285                self.validator.component_instance_section(&s)?;
1286                for instance in s {
1287                    let types = self.validator.types(0).unwrap();
1288                    let ty = types.component_instance_at(index);
1289                    let init = match instance? {
1290                        wasmparser::ComponentInstance::Instantiate {
1291                            component_index,
1292                            args,
1293                        } => {
1294                            let index = ComponentIndex::from_u32(component_index);
1295                            self.instantiate_component(index, &args, ty)?
1296                        }
1297                        wasmparser::ComponentInstance::FromExports(exports) => {
1298                            self.instantiate_component_from_exports(&exports, ty)?
1299                        }
1300                    };
1301                    self.result.initializers.push(init);
1302                    index += 1;
1303                }
1304            }
1305
1306            // Exports don't actually fill out the `initializers` array but
1307            // instead fill out the one other field in a `Translation`, the
1308            // `exports` field (as one might imagine). This for now simply
1309            // records the index of what's exported and that's tracked further
1310            // later during inlining.
1311            Payload::ComponentExportSection(s) => {
1312                self.validator.component_export_section(&s)?;
1313                for export in s {
1314                    let export = export?;
1315                    let item = self.kind_to_item(export.kind, export.index)?;
1316                    let prev = self
1317                        .result
1318                        .exports
1319                        .insert(export.name.name, (item, export.name));
1320                    assert!(prev.is_none());
1321                    self.result
1322                        .initializers
1323                        .push(LocalInitializer::Export(item));
1324                }
1325            }
1326
1327            Payload::ComponentStartSection { start, range } => {
1328                self.validator.component_start_section(&start, &range)?;
1329                unimplemented!("component start section");
1330            }
1331
1332            // Aliases of instance exports (either core or component) will be
1333            // recorded as an initializer of the appropriate type with outer
1334            // aliases handled specially via upvars and type processing.
1335            Payload::ComponentAliasSection(s) => {
1336                self.validator.component_alias_section(&s)?;
1337                for alias in s {
1338                    let init = match alias? {
1339                        wasmparser::ComponentAlias::InstanceExport {
1340                            kind: _,
1341                            instance_index,
1342                            name,
1343                        } => {
1344                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1345                            LocalInitializer::AliasComponentExport(instance, name)
1346                        }
1347                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1348                            self.alias_component_outer(kind, count, index);
1349                            continue;
1350                        }
1351                        wasmparser::ComponentAlias::CoreInstanceExport {
1352                            kind,
1353                            instance_index,
1354                            name,
1355                        } => {
1356                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1357                            self.alias_module_instance_export(kind, instance, name)
1358                        }
1359                    };
1360                    self.result.initializers.push(init);
1361                }
1362            }
1363
1364            // All custom sections are ignored by Wasmtime at this time.
1365            //
1366            // FIXME(WebAssembly/component-model#14): probably want to specify
1367            // and parse a `name` section here.
1368            Payload::CustomSection { .. } => {}
1369
1370            // Anything else is either not reachable since we never enable the
1371            // feature in Wasmtime or we do enable it and it's a bug we don't
1372            // implement it, so let validation take care of most errors here and
1373            // if it gets past validation provide a helpful error message to
1374            // debug.
1375            other => {
1376                self.validator.payload(&other)?;
1377                panic!("unimplemented section {other:?}");
1378            }
1379        }
1380
1381        Ok(Action::KeepGoing)
1382    }
1383
1384    fn instantiate_module(
1385        &mut self,
1386        module: ModuleIndex,
1387        raw_args: &[wasmparser::InstantiationArg<'data>],
1388    ) -> LocalInitializer<'data> {
1389        let mut args = HashMap::with_capacity(raw_args.len());
1390        for arg in raw_args {
1391            match arg.kind {
1392                wasmparser::InstantiationArgKind::Instance => {
1393                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1394                    args.insert(arg.name, idx);
1395                }
1396            }
1397        }
1398        LocalInitializer::ModuleInstantiate(module, args)
1399    }
1400
1401    /// Creates a synthetic module from the list of items currently in the
1402    /// module and their given names.
1403    fn instantiate_module_from_exports(
1404        &mut self,
1405        exports: &[wasmparser::Export<'data>],
1406    ) -> LocalInitializer<'data> {
1407        let mut map = HashMap::with_capacity(exports.len());
1408        for export in exports {
1409            let idx = match export.kind {
1410                wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1411                    let index = FuncIndex::from_u32(export.index);
1412                    EntityIndex::Function(index)
1413                }
1414                wasmparser::ExternalKind::Table => {
1415                    let index = TableIndex::from_u32(export.index);
1416                    EntityIndex::Table(index)
1417                }
1418                wasmparser::ExternalKind::Memory => {
1419                    let index = MemoryIndex::from_u32(export.index);
1420                    EntityIndex::Memory(index)
1421                }
1422                wasmparser::ExternalKind::Global => {
1423                    let index = GlobalIndex::from_u32(export.index);
1424                    EntityIndex::Global(index)
1425                }
1426                wasmparser::ExternalKind::Tag => {
1427                    let index = TagIndex::from_u32(export.index);
1428                    EntityIndex::Tag(index)
1429                }
1430            };
1431            map.insert(export.name, idx);
1432        }
1433        LocalInitializer::ModuleSynthetic(map)
1434    }
1435
1436    fn instantiate_component(
1437        &mut self,
1438        component: ComponentIndex,
1439        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1440        ty: ComponentInstanceTypeId,
1441    ) -> Result<LocalInitializer<'data>> {
1442        let mut args = HashMap::with_capacity(raw_args.len());
1443        for arg in raw_args {
1444            let idx = self.kind_to_item(arg.kind, arg.index)?;
1445            args.insert(arg.name, idx);
1446        }
1447
1448        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1449    }
1450
1451    /// Creates a synthetic module from the list of items currently in the
1452    /// module and their given names.
1453    fn instantiate_component_from_exports(
1454        &mut self,
1455        exports: &[wasmparser::ComponentExport<'data>],
1456        ty: ComponentInstanceTypeId,
1457    ) -> Result<LocalInitializer<'data>> {
1458        let mut map = HashMap::with_capacity(exports.len());
1459        for export in exports {
1460            let idx = self.kind_to_item(export.kind, export.index)?;
1461            map.insert(export.name.name, (idx, export.name));
1462        }
1463
1464        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1465    }
1466
1467    fn kind_to_item(
1468        &mut self,
1469        kind: wasmparser::ComponentExternalKind,
1470        index: u32,
1471    ) -> Result<ComponentItem> {
1472        Ok(match kind {
1473            wasmparser::ComponentExternalKind::Func => {
1474                let index = ComponentFuncIndex::from_u32(index);
1475                ComponentItem::Func(index)
1476            }
1477            wasmparser::ComponentExternalKind::Module => {
1478                let index = ModuleIndex::from_u32(index);
1479                ComponentItem::Module(index)
1480            }
1481            wasmparser::ComponentExternalKind::Instance => {
1482                let index = ComponentInstanceIndex::from_u32(index);
1483                ComponentItem::ComponentInstance(index)
1484            }
1485            wasmparser::ComponentExternalKind::Component => {
1486                let index = ComponentIndex::from_u32(index);
1487                ComponentItem::Component(index)
1488            }
1489            wasmparser::ComponentExternalKind::Value => {
1490                unimplemented!("component values");
1491            }
1492            wasmparser::ComponentExternalKind::Type => {
1493                let types = self.validator.types(0).unwrap();
1494                let ty = types.component_any_type_at(index);
1495                ComponentItem::Type(ty)
1496            }
1497        })
1498    }
1499
1500    fn alias_module_instance_export(
1501        &mut self,
1502        kind: wasmparser::ExternalKind,
1503        instance: ModuleInstanceIndex,
1504        name: &'data str,
1505    ) -> LocalInitializer<'data> {
1506        match kind {
1507            wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1508                LocalInitializer::AliasExportFunc(instance, name)
1509            }
1510            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1511            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1512            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1513            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1514        }
1515    }
1516
1517    fn alias_component_outer(
1518        &mut self,
1519        kind: wasmparser::ComponentOuterAliasKind,
1520        count: u32,
1521        index: u32,
1522    ) {
1523        match kind {
1524            wasmparser::ComponentOuterAliasKind::CoreType
1525            | wasmparser::ComponentOuterAliasKind::Type => {}
1526
1527            // For more information about the implementation of outer aliases
1528            // see the documentation of `LexicalScope`. Otherwise though the
1529            // main idea here is that the data to close over starts as `Local`
1530            // and then transitions to `Upvar` as its inserted into the parents
1531            // in order from target we're aliasing back to the current
1532            // component.
1533            wasmparser::ComponentOuterAliasKind::CoreModule => {
1534                let index = ModuleIndex::from_u32(index);
1535                let mut module = ClosedOverModule::Local(index);
1536                let depth = self.lexical_scopes.len() - (count as usize);
1537                for frame in self.lexical_scopes[depth..].iter_mut() {
1538                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1539                }
1540
1541                // If the `module` is still `Local` then the `depth` was 0 and
1542                // it's an alias into our own space. Otherwise it's switched to
1543                // an upvar and will index into the upvar space. Either way
1544                // it's just plumbed directly into the initializer.
1545                self.result
1546                    .initializers
1547                    .push(LocalInitializer::AliasModule(module));
1548            }
1549            wasmparser::ComponentOuterAliasKind::Component => {
1550                let index = ComponentIndex::from_u32(index);
1551                let mut component = ClosedOverComponent::Local(index);
1552                let depth = self.lexical_scopes.len() - (count as usize);
1553                for frame in self.lexical_scopes[depth..].iter_mut() {
1554                    component =
1555                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1556                }
1557
1558                self.result
1559                    .initializers
1560                    .push(LocalInitializer::AliasComponent(component));
1561            }
1562        }
1563    }
1564
1565    fn canonical_options(
1566        &mut self,
1567        opts: &[wasmparser::CanonicalOption],
1568        core_func_index: u32,
1569    ) -> WasmResult<LocalCanonicalOptions> {
1570        let core_type = self.core_func_signature(core_func_index)?;
1571
1572        let mut string_encoding = StringEncoding::Utf8;
1573        let mut post_return = None;
1574        let mut async_ = false;
1575        let mut callback = None;
1576        let mut memory = None;
1577        let mut realloc = None;
1578        let mut gc = false;
1579
1580        for opt in opts {
1581            match opt {
1582                wasmparser::CanonicalOption::UTF8 => {
1583                    string_encoding = StringEncoding::Utf8;
1584                }
1585                wasmparser::CanonicalOption::UTF16 => {
1586                    string_encoding = StringEncoding::Utf16;
1587                }
1588                wasmparser::CanonicalOption::CompactUTF16 => {
1589                    string_encoding = StringEncoding::CompactUtf16;
1590                }
1591                wasmparser::CanonicalOption::Memory(idx) => {
1592                    let idx = MemoryIndex::from_u32(*idx);
1593                    memory = Some(idx);
1594                }
1595                wasmparser::CanonicalOption::Realloc(idx) => {
1596                    let idx = FuncIndex::from_u32(*idx);
1597                    realloc = Some(idx);
1598                }
1599                wasmparser::CanonicalOption::PostReturn(idx) => {
1600                    let idx = FuncIndex::from_u32(*idx);
1601                    post_return = Some(idx);
1602                }
1603                wasmparser::CanonicalOption::Async => async_ = true,
1604                wasmparser::CanonicalOption::Callback(idx) => {
1605                    let idx = FuncIndex::from_u32(*idx);
1606                    callback = Some(idx);
1607                }
1608                wasmparser::CanonicalOption::CoreType(idx) => {
1609                    if cfg!(debug_assertions) {
1610                        let types = self.validator.types(0).unwrap();
1611                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1612                        let interned = self
1613                            .types
1614                            .module_types_builder()
1615                            .intern_type(types, core_ty_id)?;
1616                        debug_assert_eq!(interned, core_type);
1617                    }
1618                }
1619                wasmparser::CanonicalOption::Gc => {
1620                    gc = true;
1621                }
1622            }
1623        }
1624
1625        Ok(LocalCanonicalOptions {
1626            string_encoding,
1627            post_return,
1628            cancellable: false,
1629            async_,
1630            callback,
1631            core_type,
1632            data_model: if gc {
1633                LocalDataModel::Gc {}
1634            } else {
1635                LocalDataModel::LinearMemory { memory, realloc }
1636            },
1637        })
1638    }
1639
1640    /// Get the interned type index for the `index`th core function.
1641    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1642        let types = self.validator.types(0).unwrap();
1643        let id = types.core_function_at(index);
1644        self.types.module_types_builder().intern_type(types, id)
1645    }
1646
1647    fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1648        self.lexical_scopes.is_empty()
1649            && self
1650                .unsafe_intrinsics_import
1651                .is_some_and(|name| import == name)
1652    }
1653
1654    fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1655        let types = &self.validator.types(0).unwrap();
1656
1657        let ComponentEntityType::Instance(instance_ty) = ty else {
1658            bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1659        };
1660        let instance_ty = &types[instance_ty];
1661
1662        ensure!(
1663            instance_ty.defined_resources.is_empty(),
1664            "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1665        );
1666        ensure!(
1667            instance_ty.explicit_resources.is_empty(),
1668            "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1669        );
1670
1671        for (name, ty) in &instance_ty.exports {
1672            let ComponentEntityType::Func(func_ty) = ty.ty else {
1673                bail!(
1674                    "bad unsafe intrinsics import: imported instance `{import}` must \
1675                     only export functions"
1676                )
1677            };
1678            let func_ty = &types[func_ty];
1679
1680            fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1681                use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1682                match (a, b) {
1683                    (InterfaceType::U8, C::Primitive(P::U8)) => true,
1684                    (InterfaceType::U8, _) => false,
1685
1686                    (InterfaceType::U16, C::Primitive(P::U16)) => true,
1687                    (InterfaceType::U16, _) => false,
1688
1689                    (InterfaceType::U32, C::Primitive(P::U32)) => true,
1690                    (InterfaceType::U32, _) => false,
1691
1692                    (InterfaceType::U64, C::Primitive(P::U64)) => true,
1693                    (InterfaceType::U64, _) => false,
1694
1695                    (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1696                }
1697            }
1698
1699            fn check_types<'a>(
1700                expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1701                actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1702                kind: &str,
1703                import: &str,
1704                name: &str,
1705            ) -> Result<()> {
1706                let expected_len = expected.len();
1707                let actual_len = actual.len();
1708                ensure!(
1709                    expected_len == actual_len,
1710                    "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1711                     {expected_len} {kind}, found {actual_len}"
1712                );
1713
1714                for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1715                    ensure!(
1716                        ty_eq(expected_ty, actual_ty),
1717                        "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1718                         `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1719                    );
1720                }
1721                Ok(())
1722            }
1723
1724            let intrinsic = UnsafeIntrinsic::from_str(name)
1725                .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1726
1727            check_types(
1728                intrinsic.component_params().iter(),
1729                func_ty.params.iter().map(|(_name, ty)| ty),
1730                "parameters",
1731                &import,
1732                &name,
1733            )?;
1734            check_types(
1735                intrinsic.component_results().iter(),
1736                func_ty.result.iter(),
1737                "results",
1738                &import,
1739                &name,
1740            )?;
1741        }
1742
1743        Ok(())
1744    }
1745}
1746
1747impl Translation<'_> {
1748    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1749        self.types.as_ref().unwrap().as_ref()
1750    }
1751}
1752
1753/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1754/// to disallow access to mutable access to the builder before the inlining
1755/// pass.
1756///
1757/// Type information in this translation pass must be preserved at the
1758/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1759/// own type system. Only during inlining are types fully assigned because
1760/// that's when resource types become available as it's known which instance
1761/// defines which resource, or more concretely the same component instantiated
1762/// twice will produce two unique resource types unlike one as seen by
1763/// wasmparser within the component.
1764mod pre_inlining {
1765    use super::*;
1766
1767    pub struct PreInliningComponentTypes<'a> {
1768        types: &'a mut ComponentTypesBuilder,
1769    }
1770
1771    impl<'a> PreInliningComponentTypes<'a> {
1772        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1773            Self { types }
1774        }
1775
1776        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1777            self.types.module_types_builder_mut()
1778        }
1779
1780        pub fn types(&self) -> &ComponentTypesBuilder {
1781            self.types
1782        }
1783
1784        // NB: this should in theory only be used for the `inline` phase of
1785        // translation.
1786        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1787            self.types
1788        }
1789    }
1790
1791    impl TypeConvert for PreInliningComponentTypes<'_> {
1792        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1793            self.types.lookup_heap_type(index)
1794        }
1795
1796        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1797            self.types.lookup_type_index(index)
1798        }
1799    }
1800}
1801use pre_inlining::PreInliningComponentTypes;