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