wasmtime_environ/component/
translate.rs

1use crate::ScopeVec;
2use crate::component::*;
3use crate::prelude::*;
4use crate::{
5    EngineOrModuleTypeIndex, EntityIndex, ModuleEnvironment, ModuleInternedTypeIndex,
6    ModuleTranslation, ModuleTypesBuilder, PrimaryMap, TagIndex, Tunables, TypeConvert,
7    WasmHeapType, WasmResult, WasmValType,
8};
9use anyhow::anyhow;
10use anyhow::{Result, bail};
11use indexmap::IndexMap;
12use std::collections::HashMap;
13use std::mem;
14use wasmparser::component_types::{
15    AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
16    ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
17};
18use wasmparser::types::Types;
19use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
20
21mod adapt;
22pub use self::adapt::*;
23mod inline;
24
25/// Structure used to translate a component and parse it.
26pub struct Translator<'a, 'data> {
27    /// The current component being translated.
28    ///
29    /// This will get swapped out as translation traverses the body of a
30    /// component and a sub-component is entered or left.
31    result: Translation<'data>,
32
33    /// Current state of parsing a binary component. Note that like `result`
34    /// this will change as the component is traversed.
35    parser: Parser,
36
37    /// Stack of lexical scopes that are in-progress but not finished yet.
38    ///
39    /// This is pushed to whenever a component is entered and popped from
40    /// whenever a component is left. Each lexical scope also contains
41    /// information about the variables that it is currently required to close
42    /// over which is threaded into the current in-progress translation of
43    /// the sub-component which pushed a scope here.
44    lexical_scopes: Vec<LexicalScope<'data>>,
45
46    /// The validator in use to verify that the raw input binary is a valid
47    /// component.
48    validator: &'a mut Validator,
49
50    /// Type information shared for the entire component.
51    ///
52    /// This builder is also used for all core wasm modules found to intern
53    /// signatures across all modules.
54    types: PreInliningComponentTypes<'a>,
55
56    /// The compiler configuration provided by the embedder.
57    tunables: &'a Tunables,
58
59    /// Auxiliary location to push generated adapter modules onto.
60    scope_vec: &'data ScopeVec<u8>,
61
62    /// Completely translated core wasm modules that have been found so far.
63    ///
64    /// Note that this translation only involves learning about type
65    /// information and functions are not actually compiled here.
66    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
67
68    /// Completely translated components that have been found so far.
69    ///
70    /// As frames are popped from `lexical_scopes` their completed component
71    /// will be pushed onto this list.
72    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
73}
74
75/// Representation of the syntactic scope of a component meaning where it is
76/// and what its state is at in the binary format.
77///
78/// These scopes are pushed and popped when a sub-component starts being
79/// parsed and finishes being parsed. The main purpose of this frame is to
80/// have a `ClosedOverVars` field which encapsulates data that is inherited
81/// from the scope specified into the component being translated just beneath
82/// it.
83///
84/// This structure exists to implement outer aliases to components and modules.
85/// When a component or module is closed over then that means it needs to be
86/// inherited in a sense to the component which actually had the alias. This is
87/// achieved with a deceptively simple scheme where each parent of the
88/// component with the alias will inherit the component from the desired
89/// location.
90///
91/// For example with a component structure that looks like:
92///
93/// ```wasm
94/// (component $A
95///     (core module $M)
96///     (component $B
97///         (component $C
98///             (alias outer $A $M (core module))
99///         )
100///     )
101/// )
102/// ```
103///
104/// here the `C` component is closing over `M` located in the root component
105/// `A`. When `C` is being translated the `lexical_scopes` field will look like
106/// `[A, B]`. When the alias is encountered (for module index 0) this will
107/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
108/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
109/// inserted into `closure_args` in `B`'s frame. This produces yet another
110/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
111/// via `LocalInitializer::AliasModuleUpvar` with the last index.
112///
113/// All of these upvar indices and such are interpreted in the "inline" phase
114/// of compilation and not at runtime. This means that when `A` is being
115/// instantiated one of its initializers will be
116/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
117/// variables captured for `B` are listed as local module 0, or `M`. This list
118/// is then preserved in the definition of the component `B` and later reused
119/// by `C` again to finally get access to the closed over component.
120///
121/// Effectively the scopes are managed hierarchically where a reference to an
122/// outer variable automatically injects references into all parents up to
123/// where the reference is. This variable scopes are the processed during
124/// inlining where a component definition is a reference to the static
125/// component information (`Translation`) plus closed over variables
126/// (`ComponentClosure` during inlining).
127struct LexicalScope<'data> {
128    /// Current state of translating the `translation` below.
129    parser: Parser,
130    /// Current state of the component's translation as found so far.
131    translation: Translation<'data>,
132    /// List of captures that `translation` will need to process to create the
133    /// sub-component which is directly beneath this lexical scope.
134    closure_args: ClosedOverVars,
135}
136
137/// A "local" translation of a component.
138///
139/// This structure is used as a sort of in-progress translation of a component.
140/// This is not `Component` which is the final form as consumed by Wasmtime
141/// at runtime. Instead this is a fairly simple representation of a component
142/// where almost everything is ordered as a list of initializers. The binary
143/// format is translated to a list of initializers here which is later processed
144/// during "inlining" to produce a final component with the final set of
145/// initializers.
146#[derive(Default)]
147struct Translation<'data> {
148    /// Instructions which form this component.
149    ///
150    /// There is one initializer for all members of each index space, and all
151    /// index spaces are incrementally built here as the initializer list is
152    /// processed.
153    initializers: Vec<LocalInitializer<'data>>,
154
155    /// The list of exports from this component, as pairs of names and an
156    /// index into an index space of what's being exported.
157    exports: IndexMap<&'data str, ComponentItem>,
158
159    /// Type information produced by `wasmparser` for this component.
160    ///
161    /// This type information is available after the translation of the entire
162    /// component has finished, e.g. for the `inline` pass, but beforehand this
163    /// is set to `None`.
164    types: Option<Types>,
165}
166
167// NB: the type information contained in `LocalInitializer` should always point
168// to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
169// fully determined due to resources until instantiations are known which is
170// tracked during the inlining phase. This means that all type information below
171// is straight from `wasmparser`'s passes.
172enum LocalInitializer<'data> {
173    // imports
174    Import(ComponentImportName<'data>, ComponentEntityType),
175
176    // canonical function sections
177    Lower {
178        func: ComponentFuncIndex,
179        lower_ty: ComponentFuncTypeId,
180        options: LocalCanonicalOptions,
181    },
182    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
183
184    // resources
185    Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
186    ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
187    ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
188    ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
189
190    BackpressureSet {
191        func: ModuleInternedTypeIndex,
192    },
193    TaskReturn {
194        result: Option<ComponentValType>,
195        options: LocalCanonicalOptions,
196    },
197    TaskCancel {
198        func: ModuleInternedTypeIndex,
199    },
200    WaitableSetNew {
201        func: ModuleInternedTypeIndex,
202    },
203    WaitableSetWait {
204        func: ModuleInternedTypeIndex,
205        async_: bool,
206        memory: MemoryIndex,
207    },
208    WaitableSetPoll {
209        func: ModuleInternedTypeIndex,
210        async_: bool,
211        memory: MemoryIndex,
212    },
213    WaitableSetDrop {
214        func: ModuleInternedTypeIndex,
215    },
216    WaitableJoin {
217        func: ModuleInternedTypeIndex,
218    },
219    Yield {
220        func: ModuleInternedTypeIndex,
221        async_: bool,
222    },
223    SubtaskDrop {
224        func: ModuleInternedTypeIndex,
225    },
226    SubtaskCancel {
227        func: ModuleInternedTypeIndex,
228        async_: bool,
229    },
230    StreamNew {
231        ty: ComponentDefinedTypeId,
232        func: ModuleInternedTypeIndex,
233    },
234    StreamRead {
235        ty: ComponentDefinedTypeId,
236        options: LocalCanonicalOptions,
237    },
238    StreamWrite {
239        ty: ComponentDefinedTypeId,
240        options: LocalCanonicalOptions,
241    },
242    StreamCancelRead {
243        ty: ComponentDefinedTypeId,
244        func: ModuleInternedTypeIndex,
245        async_: bool,
246    },
247    StreamCancelWrite {
248        ty: ComponentDefinedTypeId,
249        func: ModuleInternedTypeIndex,
250        async_: bool,
251    },
252    StreamDropReadable {
253        ty: ComponentDefinedTypeId,
254        func: ModuleInternedTypeIndex,
255    },
256    StreamDropWritable {
257        ty: ComponentDefinedTypeId,
258        func: ModuleInternedTypeIndex,
259    },
260    FutureNew {
261        ty: ComponentDefinedTypeId,
262        func: ModuleInternedTypeIndex,
263    },
264    FutureRead {
265        ty: ComponentDefinedTypeId,
266        options: LocalCanonicalOptions,
267    },
268    FutureWrite {
269        ty: ComponentDefinedTypeId,
270        options: LocalCanonicalOptions,
271    },
272    FutureCancelRead {
273        ty: ComponentDefinedTypeId,
274        func: ModuleInternedTypeIndex,
275        async_: bool,
276    },
277    FutureCancelWrite {
278        ty: ComponentDefinedTypeId,
279        func: ModuleInternedTypeIndex,
280        async_: bool,
281    },
282    FutureDropReadable {
283        ty: ComponentDefinedTypeId,
284        func: ModuleInternedTypeIndex,
285    },
286    FutureDropWritable {
287        ty: ComponentDefinedTypeId,
288        func: ModuleInternedTypeIndex,
289    },
290    ErrorContextNew {
291        options: LocalCanonicalOptions,
292    },
293    ErrorContextDebugMessage {
294        options: LocalCanonicalOptions,
295    },
296    ErrorContextDrop {
297        func: ModuleInternedTypeIndex,
298    },
299    ContextGet {
300        func: ModuleInternedTypeIndex,
301        i: u32,
302    },
303    ContextSet {
304        func: ModuleInternedTypeIndex,
305        i: u32,
306    },
307
308    // core wasm modules
309    ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
310
311    // core wasm module instances
312    ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
313    ModuleSynthetic(HashMap<&'data str, EntityIndex>),
314
315    // components
316    ComponentStatic(StaticComponentIndex, ClosedOverVars),
317
318    // component instances
319    ComponentInstantiate(
320        ComponentIndex,
321        HashMap<&'data str, ComponentItem>,
322        ComponentInstanceTypeId,
323    ),
324    ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
325
326    // alias section
327    AliasExportFunc(ModuleInstanceIndex, &'data str),
328    AliasExportTable(ModuleInstanceIndex, &'data str),
329    AliasExportGlobal(ModuleInstanceIndex, &'data str),
330    AliasExportMemory(ModuleInstanceIndex, &'data str),
331    AliasExportTag(ModuleInstanceIndex, &'data str),
332    AliasComponentExport(ComponentInstanceIndex, &'data str),
333    AliasModule(ClosedOverModule),
334    AliasComponent(ClosedOverComponent),
335
336    // export section
337    Export(ComponentItem),
338}
339
340/// The "closure environment" of components themselves.
341///
342/// For more information see `LexicalScope`.
343#[derive(Default)]
344struct ClosedOverVars {
345    components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
346    modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
347}
348
349/// Description how a component is closed over when the closure variables for
350/// a component are being created.
351///
352/// For more information see `LexicalScope`.
353enum ClosedOverComponent {
354    /// A closed over component is coming from the local component's index
355    /// space, meaning a previously defined component is being captured.
356    Local(ComponentIndex),
357    /// A closed over component is coming from our own component's list of
358    /// upvars. This list was passed to us by our enclosing component, which
359    /// will eventually have bottomed out in closing over a `Local` component
360    /// index for some parent component.
361    Upvar(ComponentUpvarIndex),
362}
363
364/// Same as `ClosedOverComponent`, but for modules.
365enum ClosedOverModule {
366    Local(ModuleIndex),
367    Upvar(ModuleUpvarIndex),
368}
369
370/// The data model for objects that are not unboxed in locals.
371#[derive(Debug, Clone, Hash, Eq, PartialEq)]
372pub enum LocalDataModel {
373    /// Data is stored in GC objects.
374    Gc {},
375
376    /// Data is stored in a linear memory.
377    LinearMemory {
378        /// An optional memory definition supplied.
379        memory: Option<MemoryIndex>,
380        /// An optional definition of `realloc` to used.
381        realloc: Option<FuncIndex>,
382    },
383}
384
385/// Representation of canonical ABI options.
386struct LocalCanonicalOptions {
387    string_encoding: StringEncoding,
388    post_return: Option<FuncIndex>,
389    async_: bool,
390    callback: Option<FuncIndex>,
391    /// The type index of the core GC types signature.
392    core_type: ModuleInternedTypeIndex,
393    data_model: LocalDataModel,
394}
395
396enum Action {
397    KeepGoing,
398    Skip(usize),
399    Done,
400}
401
402impl<'a, 'data> Translator<'a, 'data> {
403    /// Creates a new translation state ready to translate a component.
404    pub fn new(
405        tunables: &'a Tunables,
406        validator: &'a mut Validator,
407        types: &'a mut ComponentTypesBuilder,
408        scope_vec: &'data ScopeVec<u8>,
409    ) -> Self {
410        let mut parser = Parser::new(0);
411        parser.set_features(*validator.features());
412        Self {
413            result: Translation::default(),
414            tunables,
415            validator,
416            types: PreInliningComponentTypes::new(types),
417            parser,
418            lexical_scopes: Vec::new(),
419            static_components: Default::default(),
420            static_modules: Default::default(),
421            scope_vec,
422        }
423    }
424
425    /// Translates the binary `component`.
426    ///
427    /// This is the workhorse of compilation which will parse all of
428    /// `component` and create type information for Wasmtime and such. The
429    /// `component` does not have to be valid and it will be validated during
430    /// compilation.
431    ///
432    /// The result of this function is a tuple of the final component's
433    /// description plus a list of core wasm modules found within the
434    /// component. The component's description actually erases internal
435    /// components, instances, etc, as much as it can. Instead `Component`
436    /// retains a flat list of initializers (no nesting) which was created
437    /// as part of compilation from the nested structure of the original
438    /// component.
439    ///
440    /// The list of core wasm modules found is provided to allow compiling
441    /// modules externally in parallel. Additionally initializers in
442    /// `Component` may refer to the modules in the map returned by index.
443    ///
444    /// # Errors
445    ///
446    /// This function will return an error if the `component` provided is
447    /// invalid.
448    pub fn translate(
449        mut self,
450        component: &'data [u8],
451    ) -> Result<(
452        ComponentTranslation,
453        PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
454    )> {
455        // First up wasmparser is used to actually perform the translation and
456        // validation of this component. This will produce a list of core wasm
457        // modules in addition to components which are found during the
458        // translation process. When doing this only a `Translation` is created
459        // which is a simple representation of a component.
460        let mut remaining = component;
461        loop {
462            let payload = match self.parser.parse(remaining, true)? {
463                Chunk::Parsed { payload, consumed } => {
464                    remaining = &remaining[consumed..];
465                    payload
466                }
467                Chunk::NeedMoreData(_) => unreachable!(),
468            };
469
470            match self.translate_payload(payload, component)? {
471                Action::KeepGoing => {}
472                Action::Skip(n) => remaining = &remaining[n..],
473                Action::Done => break,
474            }
475        }
476        assert!(remaining.is_empty());
477        assert!(self.lexical_scopes.is_empty());
478
479        // ... after translation initially finishes the next pass is performed
480        // which we're calling "inlining". This will "instantiate" the root
481        // component, following nested component instantiations, creating a
482        // global list of initializers along the way. This phase uses the simple
483        // initializers in each component to track dataflow of host imports and
484        // internal references to items throughout a component at compile-time.
485        // The produce initializers in the final `Component` are intended to be
486        // much simpler than the original component and more efficient for
487        // Wasmtime to process at runtime as well (e.g. no string lookups as
488        // most everything is done through indices instead).
489        let mut component = inline::run(
490            self.types.types_mut_for_inlining(),
491            &self.result,
492            &self.static_modules,
493            &self.static_components,
494        )?;
495        self.partition_adapter_modules(&mut component);
496        let translation =
497            component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
498        Ok((translation, self.static_modules))
499    }
500
501    fn translate_payload(
502        &mut self,
503        payload: Payload<'data>,
504        component: &'data [u8],
505    ) -> Result<Action> {
506        match payload {
507            Payload::Version {
508                num,
509                encoding,
510                range,
511            } => {
512                self.validator.version(num, encoding, &range)?;
513
514                match encoding {
515                    Encoding::Component => {}
516                    Encoding::Module => {
517                        bail!("attempted to parse a wasm module with a component parser");
518                    }
519                }
520            }
521
522            Payload::End(offset) => {
523                assert!(self.result.types.is_none());
524                self.result.types = Some(self.validator.end(offset)?);
525
526                // Exit the current lexical scope. If there is no parent (no
527                // frame currently on the stack) then translation is finished.
528                // Otherwise that means that a nested component has been
529                // completed and is recorded as such.
530                let LexicalScope {
531                    parser,
532                    translation,
533                    closure_args,
534                } = match self.lexical_scopes.pop() {
535                    Some(frame) => frame,
536                    None => return Ok(Action::Done),
537                };
538                self.parser = parser;
539                let component = mem::replace(&mut self.result, translation);
540                let static_idx = self.static_components.push(component);
541                self.result
542                    .initializers
543                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
544            }
545
546            // When we see a type section the types are validated and then
547            // translated into Wasmtime's representation. Each active type
548            // definition is recorded in the `ComponentTypesBuilder` tables, or
549            // this component's active scope.
550            //
551            // Note that the push/pop of the component types scope happens above
552            // in `Version` and `End` since multiple type sections can appear
553            // within a component.
554            Payload::ComponentTypeSection(s) => {
555                let mut component_type_index =
556                    self.validator.types(0).unwrap().component_type_count();
557                self.validator.component_type_section(&s)?;
558
559                // Look for resource types and if a local resource is defined
560                // then an initializer is added to define that resource type and
561                // reference its destructor.
562                let types = self.validator.types(0).unwrap();
563                for ty in s {
564                    match ty? {
565                        wasmparser::ComponentType::Resource { rep, dtor } => {
566                            let rep = self.types.convert_valtype(rep)?;
567                            let id = types
568                                .component_any_type_at(component_type_index)
569                                .unwrap_resource();
570                            let dtor = dtor.map(FuncIndex::from_u32);
571                            self.result
572                                .initializers
573                                .push(LocalInitializer::Resource(id, rep, dtor));
574                        }
575
576                        // no extra processing needed
577                        wasmparser::ComponentType::Defined(_)
578                        | wasmparser::ComponentType::Func(_)
579                        | wasmparser::ComponentType::Instance(_)
580                        | wasmparser::ComponentType::Component(_) => {}
581                    }
582
583                    component_type_index += 1;
584                }
585            }
586            Payload::CoreTypeSection(s) => {
587                self.validator.core_type_section(&s)?;
588            }
589
590            // Processing the import section at this point is relatively simple
591            // which is to simply record the name of the import and the type
592            // information associated with it.
593            Payload::ComponentImportSection(s) => {
594                self.validator.component_import_section(&s)?;
595                for import in s {
596                    let import = import?;
597                    let types = self.validator.types(0).unwrap();
598                    let ty = types
599                        .component_entity_type_of_import(import.name.0)
600                        .unwrap();
601                    self.result
602                        .initializers
603                        .push(LocalInitializer::Import(import.name, ty));
604                }
605            }
606
607            // Entries in the canonical section will get initializers recorded
608            // with the listed options for lifting/lowering.
609            Payload::ComponentCanonicalSection(s) => {
610                let types = self.validator.types(0).unwrap();
611                let mut core_func_index = types.function_count();
612                self.validator.component_canonical_section(&s)?;
613                for func in s {
614                    let init = match func? {
615                        wasmparser::CanonicalFunction::Lift {
616                            type_index,
617                            core_func_index,
618                            options,
619                        } => {
620                            let ty = self
621                                .validator
622                                .types(0)
623                                .unwrap()
624                                .component_any_type_at(type_index)
625                                .unwrap_func();
626
627                            let func = FuncIndex::from_u32(core_func_index);
628                            let options = self.canonical_options(&options, core_func_index)?;
629                            LocalInitializer::Lift(ty, func, options)
630                        }
631                        wasmparser::CanonicalFunction::Lower {
632                            func_index,
633                            options,
634                        } => {
635                            let lower_ty = self
636                                .validator
637                                .types(0)
638                                .unwrap()
639                                .component_function_at(func_index);
640                            let func = ComponentFuncIndex::from_u32(func_index);
641                            let options = self.canonical_options(&options, core_func_index)?;
642                            core_func_index += 1;
643                            LocalInitializer::Lower {
644                                func,
645                                options,
646                                lower_ty,
647                            }
648                        }
649                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
650                            let resource = self
651                                .validator
652                                .types(0)
653                                .unwrap()
654                                .component_any_type_at(resource)
655                                .unwrap_resource();
656                            let ty = self.core_func_signature(core_func_index)?;
657                            core_func_index += 1;
658                            LocalInitializer::ResourceNew(resource, ty)
659                        }
660                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
661                            let resource = self
662                                .validator
663                                .types(0)
664                                .unwrap()
665                                .component_any_type_at(resource)
666                                .unwrap_resource();
667                            let ty = self.core_func_signature(core_func_index)?;
668                            core_func_index += 1;
669                            LocalInitializer::ResourceDrop(resource, ty)
670                        }
671                        wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
672                            let _ = resource;
673                            bail!("support for `resource.drop async` not implemented yet")
674                        }
675                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
676                            let resource = self
677                                .validator
678                                .types(0)
679                                .unwrap()
680                                .component_any_type_at(resource)
681                                .unwrap_resource();
682                            let ty = self.core_func_signature(core_func_index)?;
683                            core_func_index += 1;
684                            LocalInitializer::ResourceRep(resource, ty)
685                        }
686                        wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
687                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
688                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
689                            bail!("unsupported intrinsic")
690                        }
691                        wasmparser::CanonicalFunction::BackpressureSet => {
692                            let core_type = self.core_func_signature(core_func_index)?;
693                            core_func_index += 1;
694                            LocalInitializer::BackpressureSet { func: core_type }
695                        }
696                        wasmparser::CanonicalFunction::TaskReturn { result, options } => {
697                            let result = result.map(|ty| match ty {
698                                wasmparser::ComponentValType::Primitive(ty) => {
699                                    ComponentValType::Primitive(ty)
700                                }
701                                wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
702                                    self.validator
703                                        .types(0)
704                                        .unwrap()
705                                        .component_defined_type_at(ty),
706                                ),
707                            });
708                            let options = self.canonical_options(&options, core_func_index)?;
709                            core_func_index += 1;
710                            LocalInitializer::TaskReturn { result, options }
711                        }
712                        wasmparser::CanonicalFunction::TaskCancel => {
713                            let func = self.core_func_signature(core_func_index)?;
714                            core_func_index += 1;
715                            LocalInitializer::TaskCancel { func }
716                        }
717                        wasmparser::CanonicalFunction::WaitableSetNew => {
718                            let func = self.core_func_signature(core_func_index)?;
719                            core_func_index += 1;
720                            LocalInitializer::WaitableSetNew { func }
721                        }
722                        wasmparser::CanonicalFunction::WaitableSetWait { async_, memory } => {
723                            let func = self.core_func_signature(core_func_index)?;
724                            core_func_index += 1;
725                            LocalInitializer::WaitableSetWait {
726                                func,
727                                async_,
728                                memory: MemoryIndex::from_u32(memory),
729                            }
730                        }
731                        wasmparser::CanonicalFunction::WaitableSetPoll { async_, memory } => {
732                            let func = self.core_func_signature(core_func_index)?;
733                            core_func_index += 1;
734                            LocalInitializer::WaitableSetPoll {
735                                func,
736                                async_,
737                                memory: MemoryIndex::from_u32(memory),
738                            }
739                        }
740                        wasmparser::CanonicalFunction::WaitableSetDrop => {
741                            let func = self.core_func_signature(core_func_index)?;
742                            core_func_index += 1;
743                            LocalInitializer::WaitableSetDrop { func }
744                        }
745                        wasmparser::CanonicalFunction::WaitableJoin => {
746                            let func = self.core_func_signature(core_func_index)?;
747                            core_func_index += 1;
748                            LocalInitializer::WaitableJoin { func }
749                        }
750                        wasmparser::CanonicalFunction::Yield { async_ } => {
751                            let func = self.core_func_signature(core_func_index)?;
752                            core_func_index += 1;
753                            LocalInitializer::Yield { func, async_ }
754                        }
755                        wasmparser::CanonicalFunction::SubtaskDrop => {
756                            let func = self.core_func_signature(core_func_index)?;
757                            core_func_index += 1;
758                            LocalInitializer::SubtaskDrop { func }
759                        }
760                        wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
761                            let func = self.core_func_signature(core_func_index)?;
762                            core_func_index += 1;
763                            LocalInitializer::SubtaskCancel { func, async_ }
764                        }
765                        wasmparser::CanonicalFunction::StreamNew { ty } => {
766                            let ty = self
767                                .validator
768                                .types(0)
769                                .unwrap()
770                                .component_defined_type_at(ty);
771                            let func = self.core_func_signature(core_func_index)?;
772                            core_func_index += 1;
773                            LocalInitializer::StreamNew { ty, func }
774                        }
775                        wasmparser::CanonicalFunction::StreamRead { ty, options } => {
776                            let ty = self
777                                .validator
778                                .types(0)
779                                .unwrap()
780                                .component_defined_type_at(ty);
781                            let options = self.canonical_options(&options, core_func_index)?;
782                            core_func_index += 1;
783                            LocalInitializer::StreamRead { ty, options }
784                        }
785                        wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
786                            let ty = self
787                                .validator
788                                .types(0)
789                                .unwrap()
790                                .component_defined_type_at(ty);
791                            let options = self.canonical_options(&options, core_func_index)?;
792                            core_func_index += 1;
793                            LocalInitializer::StreamWrite { ty, options }
794                        }
795                        wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
796                            let ty = self
797                                .validator
798                                .types(0)
799                                .unwrap()
800                                .component_defined_type_at(ty);
801                            let func = self.core_func_signature(core_func_index)?;
802                            core_func_index += 1;
803                            LocalInitializer::StreamCancelRead { ty, func, async_ }
804                        }
805                        wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
806                            let ty = self
807                                .validator
808                                .types(0)
809                                .unwrap()
810                                .component_defined_type_at(ty);
811                            let func = self.core_func_signature(core_func_index)?;
812                            core_func_index += 1;
813                            LocalInitializer::StreamCancelWrite { ty, func, async_ }
814                        }
815                        wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
816                            let ty = self
817                                .validator
818                                .types(0)
819                                .unwrap()
820                                .component_defined_type_at(ty);
821                            let func = self.core_func_signature(core_func_index)?;
822                            core_func_index += 1;
823                            LocalInitializer::StreamDropReadable { ty, func }
824                        }
825                        wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
826                            let ty = self
827                                .validator
828                                .types(0)
829                                .unwrap()
830                                .component_defined_type_at(ty);
831                            let func = self.core_func_signature(core_func_index)?;
832                            core_func_index += 1;
833                            LocalInitializer::StreamDropWritable { ty, func }
834                        }
835                        wasmparser::CanonicalFunction::FutureNew { ty } => {
836                            let ty = self
837                                .validator
838                                .types(0)
839                                .unwrap()
840                                .component_defined_type_at(ty);
841                            let func = self.core_func_signature(core_func_index)?;
842                            core_func_index += 1;
843                            LocalInitializer::FutureNew { ty, func }
844                        }
845                        wasmparser::CanonicalFunction::FutureRead { ty, options } => {
846                            let ty = self
847                                .validator
848                                .types(0)
849                                .unwrap()
850                                .component_defined_type_at(ty);
851                            let options = self.canonical_options(&options, core_func_index)?;
852                            core_func_index += 1;
853                            LocalInitializer::FutureRead { ty, options }
854                        }
855                        wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
856                            let ty = self
857                                .validator
858                                .types(0)
859                                .unwrap()
860                                .component_defined_type_at(ty);
861                            let options = self.canonical_options(&options, core_func_index)?;
862                            core_func_index += 1;
863                            LocalInitializer::FutureWrite { ty, options }
864                        }
865                        wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
866                            let ty = self
867                                .validator
868                                .types(0)
869                                .unwrap()
870                                .component_defined_type_at(ty);
871                            let func = self.core_func_signature(core_func_index)?;
872                            core_func_index += 1;
873                            LocalInitializer::FutureCancelRead { ty, func, async_ }
874                        }
875                        wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
876                            let ty = self
877                                .validator
878                                .types(0)
879                                .unwrap()
880                                .component_defined_type_at(ty);
881                            let func = self.core_func_signature(core_func_index)?;
882                            core_func_index += 1;
883                            LocalInitializer::FutureCancelWrite { ty, func, async_ }
884                        }
885                        wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
886                            let ty = self
887                                .validator
888                                .types(0)
889                                .unwrap()
890                                .component_defined_type_at(ty);
891                            let func = self.core_func_signature(core_func_index)?;
892                            core_func_index += 1;
893                            LocalInitializer::FutureDropReadable { ty, func }
894                        }
895                        wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
896                            let ty = self
897                                .validator
898                                .types(0)
899                                .unwrap()
900                                .component_defined_type_at(ty);
901                            let func = self.core_func_signature(core_func_index)?;
902                            core_func_index += 1;
903                            LocalInitializer::FutureDropWritable { ty, func }
904                        }
905                        wasmparser::CanonicalFunction::ErrorContextNew { options } => {
906                            let options = self.canonical_options(&options, core_func_index)?;
907                            core_func_index += 1;
908                            LocalInitializer::ErrorContextNew { options }
909                        }
910                        wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
911                            let options = self.canonical_options(&options, core_func_index)?;
912                            core_func_index += 1;
913                            LocalInitializer::ErrorContextDebugMessage { options }
914                        }
915                        wasmparser::CanonicalFunction::ErrorContextDrop => {
916                            let func = self.core_func_signature(core_func_index)?;
917                            core_func_index += 1;
918                            LocalInitializer::ErrorContextDrop { func }
919                        }
920                        wasmparser::CanonicalFunction::ContextGet(i) => {
921                            let func = self.core_func_signature(core_func_index)?;
922                            core_func_index += 1;
923                            LocalInitializer::ContextGet { i, func }
924                        }
925                        wasmparser::CanonicalFunction::ContextSet(i) => {
926                            let func = self.core_func_signature(core_func_index)?;
927                            core_func_index += 1;
928                            LocalInitializer::ContextSet { i, func }
929                        }
930                    };
931                    self.result.initializers.push(init);
932                }
933            }
934
935            // Core wasm modules are translated inline directly here with the
936            // `ModuleEnvironment` from core wasm compilation. This will return
937            // to the caller the size of the module so it knows how many bytes
938            // of the input are skipped.
939            //
940            // Note that this is just initial type translation of the core wasm
941            // module and actual function compilation is deferred until this
942            // entire process has completed.
943            Payload::ModuleSection {
944                parser,
945                unchecked_range,
946            } => {
947                let index = self.validator.types(0).unwrap().module_count();
948                self.validator.module_section(&unchecked_range)?;
949                let translation = ModuleEnvironment::new(
950                    self.tunables,
951                    self.validator,
952                    self.types.module_types_builder(),
953                )
954                .translate(
955                    parser,
956                    component
957                        .get(unchecked_range.start..unchecked_range.end)
958                        .ok_or_else(|| {
959                            anyhow!(
960                                "section range {}..{} is out of bounds (bound = {})",
961                                unchecked_range.start,
962                                unchecked_range.end,
963                                component.len()
964                            )
965                            .context("wasm component contains an invalid module section")
966                        })?,
967                )?;
968                let static_idx = self.static_modules.push(translation);
969                let types = self.validator.types(0).unwrap();
970                let ty = types.module_at(index);
971                self.result
972                    .initializers
973                    .push(LocalInitializer::ModuleStatic(static_idx, ty));
974                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
975            }
976
977            // When a sub-component is found then the current translation state
978            // is pushed onto the `lexical_scopes` stack. This will subsequently
979            // get popped as part of `Payload::End` processing above.
980            //
981            // Note that the set of closure args for this new lexical scope
982            // starts empty since it will only get populated if translation of
983            // the nested component ends up aliasing some outer module or
984            // component.
985            Payload::ComponentSection {
986                parser,
987                unchecked_range,
988            } => {
989                self.validator.component_section(&unchecked_range)?;
990                self.lexical_scopes.push(LexicalScope {
991                    parser: mem::replace(&mut self.parser, parser),
992                    translation: mem::take(&mut self.result),
993                    closure_args: ClosedOverVars::default(),
994                });
995            }
996
997            // Both core wasm instances and component instances record
998            // initializers of what form of instantiation is performed which
999            // largely just records the arguments given from wasmparser into a
1000            // `HashMap` for processing later during inlining.
1001            Payload::InstanceSection(s) => {
1002                self.validator.instance_section(&s)?;
1003                for instance in s {
1004                    let init = match instance? {
1005                        wasmparser::Instance::Instantiate { module_index, args } => {
1006                            let index = ModuleIndex::from_u32(module_index);
1007                            self.instantiate_module(index, &args)
1008                        }
1009                        wasmparser::Instance::FromExports(exports) => {
1010                            self.instantiate_module_from_exports(&exports)
1011                        }
1012                    };
1013                    self.result.initializers.push(init);
1014                }
1015            }
1016            Payload::ComponentInstanceSection(s) => {
1017                let mut index = self.validator.types(0).unwrap().component_instance_count();
1018                self.validator.component_instance_section(&s)?;
1019                for instance in s {
1020                    let types = self.validator.types(0).unwrap();
1021                    let ty = types.component_instance_at(index);
1022                    let init = match instance? {
1023                        wasmparser::ComponentInstance::Instantiate {
1024                            component_index,
1025                            args,
1026                        } => {
1027                            let index = ComponentIndex::from_u32(component_index);
1028                            self.instantiate_component(index, &args, ty)?
1029                        }
1030                        wasmparser::ComponentInstance::FromExports(exports) => {
1031                            self.instantiate_component_from_exports(&exports, ty)?
1032                        }
1033                    };
1034                    self.result.initializers.push(init);
1035                    index += 1;
1036                }
1037            }
1038
1039            // Exports don't actually fill out the `initializers` array but
1040            // instead fill out the one other field in a `Translation`, the
1041            // `exports` field (as one might imagine). This for now simply
1042            // records the index of what's exported and that's tracked further
1043            // later during inlining.
1044            Payload::ComponentExportSection(s) => {
1045                self.validator.component_export_section(&s)?;
1046                for export in s {
1047                    let export = export?;
1048                    let item = self.kind_to_item(export.kind, export.index)?;
1049                    let prev = self.result.exports.insert(export.name.0, item);
1050                    assert!(prev.is_none());
1051                    self.result
1052                        .initializers
1053                        .push(LocalInitializer::Export(item));
1054                }
1055            }
1056
1057            Payload::ComponentStartSection { start, range } => {
1058                self.validator.component_start_section(&start, &range)?;
1059                unimplemented!("component start section");
1060            }
1061
1062            // Aliases of instance exports (either core or component) will be
1063            // recorded as an initializer of the appropriate type with outer
1064            // aliases handled specially via upvars and type processing.
1065            Payload::ComponentAliasSection(s) => {
1066                self.validator.component_alias_section(&s)?;
1067                for alias in s {
1068                    let init = match alias? {
1069                        wasmparser::ComponentAlias::InstanceExport {
1070                            kind: _,
1071                            instance_index,
1072                            name,
1073                        } => {
1074                            let instance = ComponentInstanceIndex::from_u32(instance_index);
1075                            LocalInitializer::AliasComponentExport(instance, name)
1076                        }
1077                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
1078                            self.alias_component_outer(kind, count, index);
1079                            continue;
1080                        }
1081                        wasmparser::ComponentAlias::CoreInstanceExport {
1082                            kind,
1083                            instance_index,
1084                            name,
1085                        } => {
1086                            let instance = ModuleInstanceIndex::from_u32(instance_index);
1087                            self.alias_module_instance_export(kind, instance, name)
1088                        }
1089                    };
1090                    self.result.initializers.push(init);
1091                }
1092            }
1093
1094            // All custom sections are ignored by Wasmtime at this time.
1095            //
1096            // FIXME(WebAssembly/component-model#14): probably want to specify
1097            // and parse a `name` section here.
1098            Payload::CustomSection { .. } => {}
1099
1100            // Anything else is either not reachable since we never enable the
1101            // feature in Wasmtime or we do enable it and it's a bug we don't
1102            // implement it, so let validation take care of most errors here and
1103            // if it gets past validation provide a helpful error message to
1104            // debug.
1105            other => {
1106                self.validator.payload(&other)?;
1107                panic!("unimplemented section {other:?}");
1108            }
1109        }
1110
1111        Ok(Action::KeepGoing)
1112    }
1113
1114    fn instantiate_module(
1115        &mut self,
1116        module: ModuleIndex,
1117        raw_args: &[wasmparser::InstantiationArg<'data>],
1118    ) -> LocalInitializer<'data> {
1119        let mut args = HashMap::with_capacity(raw_args.len());
1120        for arg in raw_args {
1121            match arg.kind {
1122                wasmparser::InstantiationArgKind::Instance => {
1123                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1124                    args.insert(arg.name, idx);
1125                }
1126            }
1127        }
1128        LocalInitializer::ModuleInstantiate(module, args)
1129    }
1130
1131    /// Creates a synthetic module from the list of items currently in the
1132    /// module and their given names.
1133    fn instantiate_module_from_exports(
1134        &mut self,
1135        exports: &[wasmparser::Export<'data>],
1136    ) -> LocalInitializer<'data> {
1137        let mut map = HashMap::with_capacity(exports.len());
1138        for export in exports {
1139            let idx = match export.kind {
1140                wasmparser::ExternalKind::Func => {
1141                    let index = FuncIndex::from_u32(export.index);
1142                    EntityIndex::Function(index)
1143                }
1144                wasmparser::ExternalKind::Table => {
1145                    let index = TableIndex::from_u32(export.index);
1146                    EntityIndex::Table(index)
1147                }
1148                wasmparser::ExternalKind::Memory => {
1149                    let index = MemoryIndex::from_u32(export.index);
1150                    EntityIndex::Memory(index)
1151                }
1152                wasmparser::ExternalKind::Global => {
1153                    let index = GlobalIndex::from_u32(export.index);
1154                    EntityIndex::Global(index)
1155                }
1156                wasmparser::ExternalKind::Tag => {
1157                    let index = TagIndex::from_u32(export.index);
1158                    EntityIndex::Tag(index)
1159                }
1160            };
1161            map.insert(export.name, idx);
1162        }
1163        LocalInitializer::ModuleSynthetic(map)
1164    }
1165
1166    fn instantiate_component(
1167        &mut self,
1168        component: ComponentIndex,
1169        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1170        ty: ComponentInstanceTypeId,
1171    ) -> Result<LocalInitializer<'data>> {
1172        let mut args = HashMap::with_capacity(raw_args.len());
1173        for arg in raw_args {
1174            let idx = self.kind_to_item(arg.kind, arg.index)?;
1175            args.insert(arg.name, idx);
1176        }
1177
1178        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1179    }
1180
1181    /// Creates a synthetic module from the list of items currently in the
1182    /// module and their given names.
1183    fn instantiate_component_from_exports(
1184        &mut self,
1185        exports: &[wasmparser::ComponentExport<'data>],
1186        ty: ComponentInstanceTypeId,
1187    ) -> Result<LocalInitializer<'data>> {
1188        let mut map = HashMap::with_capacity(exports.len());
1189        for export in exports {
1190            let idx = self.kind_to_item(export.kind, export.index)?;
1191            map.insert(export.name.0, idx);
1192        }
1193
1194        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1195    }
1196
1197    fn kind_to_item(
1198        &mut self,
1199        kind: wasmparser::ComponentExternalKind,
1200        index: u32,
1201    ) -> Result<ComponentItem> {
1202        Ok(match kind {
1203            wasmparser::ComponentExternalKind::Func => {
1204                let index = ComponentFuncIndex::from_u32(index);
1205                ComponentItem::Func(index)
1206            }
1207            wasmparser::ComponentExternalKind::Module => {
1208                let index = ModuleIndex::from_u32(index);
1209                ComponentItem::Module(index)
1210            }
1211            wasmparser::ComponentExternalKind::Instance => {
1212                let index = ComponentInstanceIndex::from_u32(index);
1213                ComponentItem::ComponentInstance(index)
1214            }
1215            wasmparser::ComponentExternalKind::Component => {
1216                let index = ComponentIndex::from_u32(index);
1217                ComponentItem::Component(index)
1218            }
1219            wasmparser::ComponentExternalKind::Value => {
1220                unimplemented!("component values");
1221            }
1222            wasmparser::ComponentExternalKind::Type => {
1223                let types = self.validator.types(0).unwrap();
1224                let ty = types.component_any_type_at(index);
1225                ComponentItem::Type(ty)
1226            }
1227        })
1228    }
1229
1230    fn alias_module_instance_export(
1231        &mut self,
1232        kind: wasmparser::ExternalKind,
1233        instance: ModuleInstanceIndex,
1234        name: &'data str,
1235    ) -> LocalInitializer<'data> {
1236        match kind {
1237            wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1238            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1239            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1240            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1241            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1242        }
1243    }
1244
1245    fn alias_component_outer(
1246        &mut self,
1247        kind: wasmparser::ComponentOuterAliasKind,
1248        count: u32,
1249        index: u32,
1250    ) {
1251        match kind {
1252            wasmparser::ComponentOuterAliasKind::CoreType
1253            | wasmparser::ComponentOuterAliasKind::Type => {}
1254
1255            // For more information about the implementation of outer aliases
1256            // see the documentation of `LexicalScope`. Otherwise though the
1257            // main idea here is that the data to close over starts as `Local`
1258            // and then transitions to `Upvar` as its inserted into the parents
1259            // in order from target we're aliasing back to the current
1260            // component.
1261            wasmparser::ComponentOuterAliasKind::CoreModule => {
1262                let index = ModuleIndex::from_u32(index);
1263                let mut module = ClosedOverModule::Local(index);
1264                let depth = self.lexical_scopes.len() - (count as usize);
1265                for frame in self.lexical_scopes[depth..].iter_mut() {
1266                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1267                }
1268
1269                // If the `module` is still `Local` then the `depth` was 0 and
1270                // it's an alias into our own space. Otherwise it's switched to
1271                // an upvar and will index into the upvar space. Either way
1272                // it's just plumbed directly into the initializer.
1273                self.result
1274                    .initializers
1275                    .push(LocalInitializer::AliasModule(module));
1276            }
1277            wasmparser::ComponentOuterAliasKind::Component => {
1278                let index = ComponentIndex::from_u32(index);
1279                let mut component = ClosedOverComponent::Local(index);
1280                let depth = self.lexical_scopes.len() - (count as usize);
1281                for frame in self.lexical_scopes[depth..].iter_mut() {
1282                    component =
1283                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1284                }
1285
1286                self.result
1287                    .initializers
1288                    .push(LocalInitializer::AliasComponent(component));
1289            }
1290        }
1291    }
1292
1293    fn canonical_options(
1294        &mut self,
1295        opts: &[wasmparser::CanonicalOption],
1296        core_func_index: u32,
1297    ) -> WasmResult<LocalCanonicalOptions> {
1298        let core_type = self.core_func_signature(core_func_index)?;
1299
1300        let mut string_encoding = StringEncoding::Utf8;
1301        let mut post_return = None;
1302        let mut async_ = false;
1303        let mut callback = None;
1304        let mut memory = None;
1305        let mut realloc = None;
1306        let mut gc = false;
1307
1308        for opt in opts {
1309            match opt {
1310                wasmparser::CanonicalOption::UTF8 => {
1311                    string_encoding = StringEncoding::Utf8;
1312                }
1313                wasmparser::CanonicalOption::UTF16 => {
1314                    string_encoding = StringEncoding::Utf16;
1315                }
1316                wasmparser::CanonicalOption::CompactUTF16 => {
1317                    string_encoding = StringEncoding::CompactUtf16;
1318                }
1319                wasmparser::CanonicalOption::Memory(idx) => {
1320                    let idx = MemoryIndex::from_u32(*idx);
1321                    memory = Some(idx);
1322                }
1323                wasmparser::CanonicalOption::Realloc(idx) => {
1324                    let idx = FuncIndex::from_u32(*idx);
1325                    realloc = Some(idx);
1326                }
1327                wasmparser::CanonicalOption::PostReturn(idx) => {
1328                    let idx = FuncIndex::from_u32(*idx);
1329                    post_return = Some(idx);
1330                }
1331                wasmparser::CanonicalOption::Async => async_ = true,
1332                wasmparser::CanonicalOption::Callback(idx) => {
1333                    let idx = FuncIndex::from_u32(*idx);
1334                    callback = Some(idx);
1335                }
1336                wasmparser::CanonicalOption::CoreType(idx) => {
1337                    if cfg!(debug_assertions) {
1338                        let types = self.validator.types(0).unwrap();
1339                        let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1340                        let interned = self
1341                            .types
1342                            .module_types_builder()
1343                            .intern_type(types, core_ty_id)?;
1344                        debug_assert_eq!(interned, core_type);
1345                    }
1346                }
1347                wasmparser::CanonicalOption::Gc => {
1348                    gc = true;
1349                }
1350            }
1351        }
1352
1353        Ok(LocalCanonicalOptions {
1354            string_encoding,
1355            post_return,
1356            async_,
1357            callback,
1358            core_type,
1359            data_model: if gc {
1360                LocalDataModel::Gc {}
1361            } else {
1362                LocalDataModel::LinearMemory { memory, realloc }
1363            },
1364        })
1365    }
1366
1367    /// Get the interned type index for the `index`th core function.
1368    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1369        let types = self.validator.types(0).unwrap();
1370        let id = types.core_function_at(index);
1371        self.types.module_types_builder().intern_type(types, id)
1372    }
1373}
1374
1375impl Translation<'_> {
1376    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1377        self.types.as_ref().unwrap().as_ref()
1378    }
1379}
1380
1381/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1382/// to disallow access to mutable access to the builder before the inlining
1383/// pass.
1384///
1385/// Type information in this translation pass must be preserved at the
1386/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1387/// own type system. Only during inlining are types fully assigned because
1388/// that's when resource types become available as it's known which instance
1389/// defines which resource, or more concretely the same component instantiated
1390/// twice will produce two unique resource types unlike one as seen by
1391/// wasmparser within the component.
1392mod pre_inlining {
1393    use super::*;
1394
1395    pub struct PreInliningComponentTypes<'a> {
1396        types: &'a mut ComponentTypesBuilder,
1397    }
1398
1399    impl<'a> PreInliningComponentTypes<'a> {
1400        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1401            Self { types }
1402        }
1403
1404        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1405            self.types.module_types_builder_mut()
1406        }
1407
1408        pub fn types(&self) -> &ComponentTypesBuilder {
1409            self.types
1410        }
1411
1412        // NB: this should in theory only be used for the `inline` phase of
1413        // translation.
1414        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1415            self.types
1416        }
1417    }
1418
1419    impl TypeConvert for PreInliningComponentTypes<'_> {
1420        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1421            self.types.lookup_heap_type(index)
1422        }
1423
1424        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1425            self.types.lookup_type_index(index)
1426        }
1427    }
1428}
1429use pre_inlining::PreInliningComponentTypes;