wasmtime_environ/component/
translate.rs

1use crate::component::*;
2use crate::prelude::*;
3use crate::Module;
4use crate::ScopeVec;
5use crate::{
6    EntityIndex, ModuleEnvironment, ModuleTranslation, ModuleTypesBuilder, PrimaryMap, Tunables,
7    TypeConvert, WasmHeapType, WasmValType,
8};
9use anyhow::anyhow;
10use anyhow::{bail, Result};
11use indexmap::IndexMap;
12use std::collections::HashMap;
13use std::mem;
14use wasmparser::types::{
15    AliasableResourceId, ComponentCoreModuleTypeId, ComponentEntityType, ComponentFuncTypeId,
16    ComponentInstanceTypeId, Types,
17};
18use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
19use wasmtime_types::ModuleInternedTypeIndex;
20use wasmtime_types::WasmResult;
21
22mod adapt;
23pub use self::adapt::*;
24mod inline;
25
26/// Structure used to translate a component and parse it.
27pub struct Translator<'a, 'data> {
28    /// The current component being translated.
29    ///
30    /// This will get swapped out as translation traverses the body of a
31    /// component and a sub-component is entered or left.
32    result: Translation<'data>,
33
34    /// Current state of parsing a binary component. Note that like `result`
35    /// this will change as the component is traversed.
36    parser: Parser,
37
38    /// Stack of lexical scopes that are in-progress but not finished yet.
39    ///
40    /// This is pushed to whenever a component is entered and popped from
41    /// whenever a component is left. Each lexical scope also contains
42    /// information about the variables that it is currently required to close
43    /// over which is threaded into the current in-progress translation of
44    /// the sub-component which pushed a scope here.
45    lexical_scopes: Vec<LexicalScope<'data>>,
46
47    /// The validator in use to verify that the raw input binary is a valid
48    /// component.
49    validator: &'a mut Validator,
50
51    /// Type information shared for the entire component.
52    ///
53    /// This builder is also used for all core wasm modules found to intern
54    /// signatures across all modules.
55    types: PreInliningComponentTypes<'a>,
56
57    /// The compiler configuration provided by the embedder.
58    tunables: &'a Tunables,
59
60    /// Auxiliary location to push generated adapter modules onto.
61    scope_vec: &'data ScopeVec<u8>,
62
63    /// Completely translated core wasm modules that have been found so far.
64    ///
65    /// Note that this translation only involves learning about type
66    /// information and functions are not actually compiled here.
67    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
68
69    /// Completely translated components that have been found so far.
70    ///
71    /// As frames are popped from `lexical_scopes` their completed component
72    /// will be pushed onto this list.
73    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
74}
75
76/// Representation of the syntactic scope of a component meaning where it is
77/// and what its state is at in the binary format.
78///
79/// These scopes are pushed and popped when a sub-component starts being
80/// parsed and finishes being parsed. The main purpose of this frame is to
81/// have a `ClosedOverVars` field which encapsulates data that is inherited
82/// from the scope specified into the component being translated just beneath
83/// it.
84///
85/// This structure exists to implement outer aliases to components and modules.
86/// When a component or module is closed over then that means it needs to be
87/// inherited in a sense to the component which actually had the alias. This is
88/// achieved with a deceptively simple scheme where each parent of the
89/// component with the alias will inherit the component from the desired
90/// location.
91///
92/// For example with a component structure that looks like:
93///
94/// ```wasm
95/// (component $A
96///     (core module $M)
97///     (component $B
98///         (component $C
99///             (alias outer $A $M (core module))
100///         )
101///     )
102/// )
103/// ```
104///
105/// here the `C` component is closing over `M` located in the root component
106/// `A`. When `C` is being translated the `lexical_scopes` field will look like
107/// `[A, B]`. When the alias is encountered (for module index 0) this will
108/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
109/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
110/// inserted into `closure_args` in `B`'s frame. This produces yet another
111/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
112/// via `LocalInitializer::AliasModuleUpvar` with the last index.
113///
114/// All of these upvar indices and such are interpreted in the "inline" phase
115/// of compilation and not at runtime. This means that when `A` is being
116/// instantiated one of its initializers will be
117/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
118/// variables captured for `B` are listed as local module 0, or `M`. This list
119/// is then preserved in the definition of the component `B` and later reused
120/// by `C` again to finally get access to the closed over component.
121///
122/// Effectively the scopes are managed hierarchically where a reference to an
123/// outer variable automatically injects references into all parents up to
124/// where the reference is. This variable scopes are the processed during
125/// inlining where a component definition is a reference to the static
126/// component information (`Translation`) plus closed over variables
127/// (`ComponentClosure` during inlining).
128struct LexicalScope<'data> {
129    /// Current state of translating the `translation` below.
130    parser: Parser,
131    /// Current state of the component's translation as found so far.
132    translation: Translation<'data>,
133    /// List of captures that `translation` will need to process to create the
134    /// sub-component which is directly beneath this lexical scope.
135    closure_args: ClosedOverVars,
136}
137
138/// A "local" translation of a component.
139///
140/// This structure is used as a sort of in-progress translation of a component.
141/// This is not `Component` which is the final form as consumed by Wasmtime
142/// at runtime. Instead this is a fairly simple representation of a component
143/// where almost everything is ordered as a list of initializers. The binary
144/// format is translated to a list of initializers here which is later processed
145/// during "inlining" to produce a final component with the final set of
146/// initializers.
147#[derive(Default)]
148struct Translation<'data> {
149    /// Instructions which form this component.
150    ///
151    /// There is one initializer for all members of each index space, and all
152    /// index spaces are incrementally built here as the initializer list is
153    /// processed.
154    initializers: Vec<LocalInitializer<'data>>,
155
156    /// The list of exports from this component, as pairs of names and an
157    /// index into an index space of what's being exported.
158    exports: IndexMap<&'data str, ComponentItem>,
159
160    /// Type information produced by `wasmparser` for this component.
161    ///
162    /// This type information is available after the translation of the entire
163    /// component has finished, e.g. for the `inline` pass, but beforehand this
164    /// is set to `None`.
165    types: Option<Types>,
166}
167
168// NB: the type information contained in `LocalInitializer` should always point
169// to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
170// fully determined due to resources until instantiations are known which is
171// tracked during the inlining phase. This means that all type information below
172// is straight from `wasmparser`'s passes.
173#[allow(missing_docs)]
174enum LocalInitializer<'data> {
175    // imports
176    Import(ComponentImportName<'data>, ComponentEntityType),
177
178    // canonical function sections
179    Lower {
180        func: ComponentFuncIndex,
181        lower_ty: ComponentFuncTypeId,
182        canonical_abi: ModuleInternedTypeIndex,
183        options: LocalCanonicalOptions,
184    },
185    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
186
187    // resources
188    Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
189    ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
190    ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
191    ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
192
193    // core wasm modules
194    ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
195
196    // core wasm module instances
197    ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
198    ModuleSynthetic(HashMap<&'data str, EntityIndex>),
199
200    // components
201    ComponentStatic(StaticComponentIndex, ClosedOverVars),
202
203    // component instances
204    ComponentInstantiate(
205        ComponentIndex,
206        HashMap<&'data str, ComponentItem>,
207        ComponentInstanceTypeId,
208    ),
209    ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
210
211    // alias section
212    AliasExportFunc(ModuleInstanceIndex, &'data str),
213    AliasExportTable(ModuleInstanceIndex, &'data str),
214    AliasExportGlobal(ModuleInstanceIndex, &'data str),
215    AliasExportMemory(ModuleInstanceIndex, &'data str),
216    AliasComponentExport(ComponentInstanceIndex, &'data str),
217    AliasModule(ClosedOverModule),
218    AliasComponent(ClosedOverComponent),
219
220    // export section
221    Export(ComponentItem),
222}
223
224/// The "closure environment" of components themselves.
225///
226/// For more information see `LexicalScope`.
227#[derive(Default)]
228struct ClosedOverVars {
229    components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
230    modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
231}
232
233/// Description how a component is closed over when the closure variables for
234/// a component are being created.
235///
236/// For more information see `LexicalScope`.
237enum ClosedOverComponent {
238    /// A closed over component is coming from the local component's index
239    /// space, meaning a previously defined component is being captured.
240    Local(ComponentIndex),
241    /// A closed over component is coming from our own component's list of
242    /// upvars. This list was passed to us by our enclosing component, which
243    /// will eventually have bottomed out in closing over a `Local` component
244    /// index for some parent component.
245    Upvar(ComponentUpvarIndex),
246}
247
248/// Same as `ClosedOverComponent`, but for modules.
249enum ClosedOverModule {
250    Local(ModuleIndex),
251    Upvar(ModuleUpvarIndex),
252}
253
254/// Representation of canonical ABI options.
255struct LocalCanonicalOptions {
256    string_encoding: StringEncoding,
257    memory: Option<MemoryIndex>,
258    realloc: Option<FuncIndex>,
259    post_return: Option<FuncIndex>,
260}
261
262enum Action {
263    KeepGoing,
264    Skip(usize),
265    Done,
266}
267
268impl<'a, 'data> Translator<'a, 'data> {
269    /// Creates a new translation state ready to translate a component.
270    pub fn new(
271        tunables: &'a Tunables,
272        validator: &'a mut Validator,
273        types: &'a mut ComponentTypesBuilder,
274        scope_vec: &'data ScopeVec<u8>,
275    ) -> Self {
276        let mut parser = Parser::new(0);
277        parser.set_features(*validator.features());
278        Self {
279            result: Translation::default(),
280            tunables,
281            validator,
282            types: PreInliningComponentTypes::new(types),
283            parser,
284            lexical_scopes: Vec::new(),
285            static_components: Default::default(),
286            static_modules: Default::default(),
287            scope_vec,
288        }
289    }
290
291    /// Translates the binary `component`.
292    ///
293    /// This is the workhorse of compilation which will parse all of
294    /// `component` and create type information for Wasmtime and such. The
295    /// `component` does not have to be valid and it will be validated during
296    /// compilation.
297    ///
298    /// The result of this function is a tuple of the final component's
299    /// description plus a list of core wasm modules found within the
300    /// component. The component's description actually erases internal
301    /// components, instances, etc, as much as it can. Instead `Component`
302    /// retains a flat list of initializers (no nesting) which was created
303    /// as part of compilation from the nested structure of the original
304    /// component.
305    ///
306    /// The list of core wasm modules found is provided to allow compiling
307    /// modules externally in parallel. Additionally initializers in
308    /// `Component` may refer to the modules in the map returned by index.
309    ///
310    /// # Errors
311    ///
312    /// This function will return an error if the `component` provided is
313    /// invalid.
314    pub fn translate(
315        mut self,
316        component: &'data [u8],
317    ) -> Result<(
318        ComponentTranslation,
319        PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
320    )> {
321        // First up wasmparser is used to actually perform the translation and
322        // validation of this component. This will produce a list of core wasm
323        // modules in addition to components which are found during the
324        // translation process. When doing this only a `Translation` is created
325        // which is a simple representation of a component.
326        let mut remaining = component;
327        loop {
328            let payload = match self.parser.parse(remaining, true)? {
329                Chunk::Parsed { payload, consumed } => {
330                    remaining = &remaining[consumed..];
331                    payload
332                }
333                Chunk::NeedMoreData(_) => unreachable!(),
334            };
335
336            match self.translate_payload(payload, component)? {
337                Action::KeepGoing => {}
338                Action::Skip(n) => remaining = &remaining[n..],
339                Action::Done => break,
340            }
341        }
342        assert!(remaining.is_empty());
343        assert!(self.lexical_scopes.is_empty());
344
345        // ... after translation initially finishes the next pass is performed
346        // which we're calling "inlining". This will "instantiate" the root
347        // component, following nested component instantiations, creating a
348        // global list of initializers along the way. This phase uses the simple
349        // initializers in each component to track dataflow of host imports and
350        // internal references to items throughout a component at compile-time.
351        // The produce initializers in the final `Component` are intended to be
352        // much simpler than the original component and more efficient for
353        // Wasmtime to process at runtime as well (e.g. no string lookups as
354        // most everything is done through indices instead).
355        let mut component = inline::run(
356            self.types.types_mut_for_inlining(),
357            &self.result,
358            &self.static_modules,
359            &self.static_components,
360        )?;
361        self.partition_adapter_modules(&mut component);
362        let translation =
363            component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
364        Ok((translation, self.static_modules))
365    }
366
367    fn translate_payload(
368        &mut self,
369        payload: Payload<'data>,
370        component: &'data [u8],
371    ) -> Result<Action> {
372        match payload {
373            Payload::Version {
374                num,
375                encoding,
376                range,
377            } => {
378                self.validator.version(num, encoding, &range)?;
379
380                match encoding {
381                    Encoding::Component => {}
382                    Encoding::Module => {
383                        bail!("attempted to parse a wasm module with a component parser");
384                    }
385                }
386            }
387
388            Payload::End(offset) => {
389                assert!(self.result.types.is_none());
390                self.result.types = Some(self.validator.end(offset)?);
391
392                // Exit the current lexical scope. If there is no parent (no
393                // frame currently on the stack) then translation is finished.
394                // Otherwise that means that a nested component has been
395                // completed and is recorded as such.
396                let LexicalScope {
397                    parser,
398                    translation,
399                    closure_args,
400                } = match self.lexical_scopes.pop() {
401                    Some(frame) => frame,
402                    None => return Ok(Action::Done),
403                };
404                self.parser = parser;
405                let component = mem::replace(&mut self.result, translation);
406                let static_idx = self.static_components.push(component);
407                self.result
408                    .initializers
409                    .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
410            }
411
412            // When we see a type section the types are validated and then
413            // translated into Wasmtime's representation. Each active type
414            // definition is recorded in the `ComponentTypesBuilder` tables, or
415            // this component's active scope.
416            //
417            // Note that the push/pop of the component types scope happens above
418            // in `Version` and `End` since multiple type sections can appear
419            // within a component.
420            Payload::ComponentTypeSection(s) => {
421                let mut component_type_index =
422                    self.validator.types(0).unwrap().component_type_count();
423                self.validator.component_type_section(&s)?;
424
425                // Look for resource types and if a local resource is defined
426                // then an initializer is added to define that resource type and
427                // reference its destructor.
428                let types = self.validator.types(0).unwrap();
429                for ty in s {
430                    match ty? {
431                        wasmparser::ComponentType::Resource { rep, dtor } => {
432                            let rep = self.types.convert_valtype(rep);
433                            let id = types
434                                .component_any_type_at(component_type_index)
435                                .unwrap_resource();
436                            let dtor = dtor.map(FuncIndex::from_u32);
437                            self.result
438                                .initializers
439                                .push(LocalInitializer::Resource(id, rep, dtor));
440                        }
441
442                        // no extra processing needed
443                        wasmparser::ComponentType::Defined(_)
444                        | wasmparser::ComponentType::Func(_)
445                        | wasmparser::ComponentType::Instance(_)
446                        | wasmparser::ComponentType::Component(_) => {}
447                    }
448
449                    component_type_index += 1;
450                }
451            }
452            Payload::CoreTypeSection(s) => {
453                self.validator.core_type_section(&s)?;
454            }
455
456            // Processing the import section at this point is relatively simple
457            // which is to simply record the name of the import and the type
458            // information associated with it.
459            Payload::ComponentImportSection(s) => {
460                self.validator.component_import_section(&s)?;
461                for import in s {
462                    let import = import?;
463                    let types = self.validator.types(0).unwrap();
464                    let ty = types
465                        .component_entity_type_of_import(import.name.0)
466                        .unwrap();
467                    self.result
468                        .initializers
469                        .push(LocalInitializer::Import(import.name, ty));
470                }
471            }
472
473            // Entries in the canonical section will get initializers recorded
474            // with the listed options for lifting/lowering.
475            Payload::ComponentCanonicalSection(s) => {
476                let mut core_func_index = self.validator.types(0).unwrap().function_count();
477                self.validator.component_canonical_section(&s)?;
478                for func in s {
479                    let types = self.validator.types(0).unwrap();
480                    let init = match func? {
481                        wasmparser::CanonicalFunction::Lift {
482                            type_index,
483                            core_func_index,
484                            options,
485                        } => {
486                            let ty = types.component_any_type_at(type_index).unwrap_func();
487                            let func = FuncIndex::from_u32(core_func_index);
488                            let options = self.canonical_options(&options);
489                            LocalInitializer::Lift(ty, func, options)
490                        }
491                        wasmparser::CanonicalFunction::Lower {
492                            func_index,
493                            options,
494                        } => {
495                            let lower_ty = types.component_function_at(func_index);
496                            let func = ComponentFuncIndex::from_u32(func_index);
497                            let options = self.canonical_options(&options);
498                            let canonical_abi = self.core_func_signature(core_func_index)?;
499
500                            core_func_index += 1;
501                            LocalInitializer::Lower {
502                                func,
503                                options,
504                                canonical_abi,
505                                lower_ty,
506                            }
507                        }
508                        wasmparser::CanonicalFunction::ResourceNew { resource } => {
509                            let resource = types.component_any_type_at(resource).unwrap_resource();
510                            let ty = self.core_func_signature(core_func_index)?;
511                            core_func_index += 1;
512                            LocalInitializer::ResourceNew(resource, ty)
513                        }
514                        wasmparser::CanonicalFunction::ResourceDrop { resource } => {
515                            let resource = types.component_any_type_at(resource).unwrap_resource();
516                            let ty = self.core_func_signature(core_func_index)?;
517                            core_func_index += 1;
518                            LocalInitializer::ResourceDrop(resource, ty)
519                        }
520                        wasmparser::CanonicalFunction::ResourceRep { resource } => {
521                            let resource = types.component_any_type_at(resource).unwrap_resource();
522                            let ty = self.core_func_signature(core_func_index)?;
523                            core_func_index += 1;
524                            LocalInitializer::ResourceRep(resource, ty)
525                        }
526                    };
527                    self.result.initializers.push(init);
528                }
529            }
530
531            // Core wasm modules are translated inline directly here with the
532            // `ModuleEnvironment` from core wasm compilation. This will return
533            // to the caller the size of the module so it knows how many bytes
534            // of the input are skipped.
535            //
536            // Note that this is just initial type translation of the core wasm
537            // module and actual function compilation is deferred until this
538            // entire process has completed.
539            Payload::ModuleSection {
540                parser,
541                unchecked_range,
542            } => {
543                let index = self.validator.types(0).unwrap().module_count();
544                self.validator.module_section(&unchecked_range)?;
545                let translation = ModuleEnvironment::new(
546                    self.tunables,
547                    self.validator,
548                    self.types.module_types_builder(),
549                )
550                .translate(
551                    parser,
552                    component
553                        .get(unchecked_range.start..unchecked_range.end)
554                        .ok_or_else(|| {
555                            anyhow!(
556                                "section range {}..{} is out of bounds (bound = {})",
557                                unchecked_range.start,
558                                unchecked_range.end,
559                                component.len()
560                            )
561                            .context("wasm component contains an invalid module section")
562                        })?,
563                )?;
564                let static_idx = self.static_modules.push(translation);
565                let types = self.validator.types(0).unwrap();
566                let ty = types.module_at(index);
567                self.result
568                    .initializers
569                    .push(LocalInitializer::ModuleStatic(static_idx, ty));
570                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
571            }
572
573            // When a sub-component is found then the current translation state
574            // is pushed onto the `lexical_scopes` stack. This will subsequently
575            // get popped as part of `Payload::End` processing above.
576            //
577            // Note that the set of closure args for this new lexical scope
578            // starts empty since it will only get populated if translation of
579            // the nested component ends up aliasing some outer module or
580            // component.
581            Payload::ComponentSection {
582                parser,
583                unchecked_range,
584            } => {
585                self.validator.component_section(&unchecked_range)?;
586                self.lexical_scopes.push(LexicalScope {
587                    parser: mem::replace(&mut self.parser, parser),
588                    translation: mem::take(&mut self.result),
589                    closure_args: ClosedOverVars::default(),
590                });
591            }
592
593            // Both core wasm instances and component instances record
594            // initializers of what form of instantiation is performed which
595            // largely just records the arguments given from wasmparser into a
596            // `HashMap` for processing later during inlining.
597            Payload::InstanceSection(s) => {
598                self.validator.instance_section(&s)?;
599                for instance in s {
600                    let init = match instance? {
601                        wasmparser::Instance::Instantiate { module_index, args } => {
602                            let index = ModuleIndex::from_u32(module_index);
603                            self.instantiate_module(index, &args)
604                        }
605                        wasmparser::Instance::FromExports(exports) => {
606                            self.instantiate_module_from_exports(&exports)
607                        }
608                    };
609                    self.result.initializers.push(init);
610                }
611            }
612            Payload::ComponentInstanceSection(s) => {
613                let mut index = self.validator.types(0).unwrap().component_instance_count();
614                self.validator.component_instance_section(&s)?;
615                for instance in s {
616                    let types = self.validator.types(0).unwrap();
617                    let ty = types.component_instance_at(index);
618                    let init = match instance? {
619                        wasmparser::ComponentInstance::Instantiate {
620                            component_index,
621                            args,
622                        } => {
623                            let index = ComponentIndex::from_u32(component_index);
624                            self.instantiate_component(index, &args, ty)?
625                        }
626                        wasmparser::ComponentInstance::FromExports(exports) => {
627                            self.instantiate_component_from_exports(&exports, ty)?
628                        }
629                    };
630                    self.result.initializers.push(init);
631                    index += 1;
632                }
633            }
634
635            // Exports don't actually fill out the `initializers` array but
636            // instead fill out the one other field in a `Translation`, the
637            // `exports` field (as one might imagine). This for now simply
638            // records the index of what's exported and that's tracked further
639            // later during inlining.
640            Payload::ComponentExportSection(s) => {
641                self.validator.component_export_section(&s)?;
642                for export in s {
643                    let export = export?;
644                    let item = self.kind_to_item(export.kind, export.index)?;
645                    let prev = self.result.exports.insert(export.name.0, item);
646                    assert!(prev.is_none());
647                    self.result
648                        .initializers
649                        .push(LocalInitializer::Export(item));
650                }
651            }
652
653            Payload::ComponentStartSection { start, range } => {
654                self.validator.component_start_section(&start, &range)?;
655                unimplemented!("component start section");
656            }
657
658            // Aliases of instance exports (either core or component) will be
659            // recorded as an initializer of the appropriate type with outer
660            // aliases handled specially via upvars and type processing.
661            Payload::ComponentAliasSection(s) => {
662                self.validator.component_alias_section(&s)?;
663                for alias in s {
664                    let init = match alias? {
665                        wasmparser::ComponentAlias::InstanceExport {
666                            kind: _,
667                            instance_index,
668                            name,
669                        } => {
670                            let instance = ComponentInstanceIndex::from_u32(instance_index);
671                            LocalInitializer::AliasComponentExport(instance, name)
672                        }
673                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
674                            self.alias_component_outer(kind, count, index);
675                            continue;
676                        }
677                        wasmparser::ComponentAlias::CoreInstanceExport {
678                            kind,
679                            instance_index,
680                            name,
681                        } => {
682                            let instance = ModuleInstanceIndex::from_u32(instance_index);
683                            self.alias_module_instance_export(kind, instance, name)
684                        }
685                    };
686                    self.result.initializers.push(init);
687                }
688            }
689
690            // All custom sections are ignored by Wasmtime at this time.
691            //
692            // FIXME(WebAssembly/component-model#14): probably want to specify
693            // and parse a `name` section here.
694            Payload::CustomSection { .. } => {}
695
696            // Anything else is either not reachable since we never enable the
697            // feature in Wasmtime or we do enable it and it's a bug we don't
698            // implement it, so let validation take care of most errors here and
699            // if it gets past validation provide a helpful error message to
700            // debug.
701            other => {
702                self.validator.payload(&other)?;
703                panic!("unimplemented section {other:?}");
704            }
705        }
706
707        Ok(Action::KeepGoing)
708    }
709
710    fn instantiate_module(
711        &mut self,
712        module: ModuleIndex,
713        raw_args: &[wasmparser::InstantiationArg<'data>],
714    ) -> LocalInitializer<'data> {
715        let mut args = HashMap::with_capacity(raw_args.len());
716        for arg in raw_args {
717            match arg.kind {
718                wasmparser::InstantiationArgKind::Instance => {
719                    let idx = ModuleInstanceIndex::from_u32(arg.index);
720                    args.insert(arg.name, idx);
721                }
722            }
723        }
724        LocalInitializer::ModuleInstantiate(module, args)
725    }
726
727    /// Creates a synthetic module from the list of items currently in the
728    /// module and their given names.
729    fn instantiate_module_from_exports(
730        &mut self,
731        exports: &[wasmparser::Export<'data>],
732    ) -> LocalInitializer<'data> {
733        let mut map = HashMap::with_capacity(exports.len());
734        for export in exports {
735            let idx = match export.kind {
736                wasmparser::ExternalKind::Func => {
737                    let index = FuncIndex::from_u32(export.index);
738                    EntityIndex::Function(index)
739                }
740                wasmparser::ExternalKind::Table => {
741                    let index = TableIndex::from_u32(export.index);
742                    EntityIndex::Table(index)
743                }
744                wasmparser::ExternalKind::Memory => {
745                    let index = MemoryIndex::from_u32(export.index);
746                    EntityIndex::Memory(index)
747                }
748                wasmparser::ExternalKind::Global => {
749                    let index = GlobalIndex::from_u32(export.index);
750                    EntityIndex::Global(index)
751                }
752
753                // doesn't get past validation
754                wasmparser::ExternalKind::Tag => unimplemented!("wasm exceptions"),
755            };
756            map.insert(export.name, idx);
757        }
758        LocalInitializer::ModuleSynthetic(map)
759    }
760
761    fn instantiate_component(
762        &mut self,
763        component: ComponentIndex,
764        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
765        ty: ComponentInstanceTypeId,
766    ) -> Result<LocalInitializer<'data>> {
767        let mut args = HashMap::with_capacity(raw_args.len());
768        for arg in raw_args {
769            let idx = self.kind_to_item(arg.kind, arg.index)?;
770            args.insert(arg.name, idx);
771        }
772
773        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
774    }
775
776    /// Creates a synthetic module from the list of items currently in the
777    /// module and their given names.
778    fn instantiate_component_from_exports(
779        &mut self,
780        exports: &[wasmparser::ComponentExport<'data>],
781        ty: ComponentInstanceTypeId,
782    ) -> Result<LocalInitializer<'data>> {
783        let mut map = HashMap::with_capacity(exports.len());
784        for export in exports {
785            let idx = self.kind_to_item(export.kind, export.index)?;
786            map.insert(export.name.0, idx);
787        }
788
789        Ok(LocalInitializer::ComponentSynthetic(map, ty))
790    }
791
792    fn kind_to_item(
793        &mut self,
794        kind: wasmparser::ComponentExternalKind,
795        index: u32,
796    ) -> Result<ComponentItem> {
797        Ok(match kind {
798            wasmparser::ComponentExternalKind::Func => {
799                let index = ComponentFuncIndex::from_u32(index);
800                ComponentItem::Func(index)
801            }
802            wasmparser::ComponentExternalKind::Module => {
803                let index = ModuleIndex::from_u32(index);
804                ComponentItem::Module(index)
805            }
806            wasmparser::ComponentExternalKind::Instance => {
807                let index = ComponentInstanceIndex::from_u32(index);
808                ComponentItem::ComponentInstance(index)
809            }
810            wasmparser::ComponentExternalKind::Component => {
811                let index = ComponentIndex::from_u32(index);
812                ComponentItem::Component(index)
813            }
814            wasmparser::ComponentExternalKind::Value => {
815                unimplemented!("component values");
816            }
817            wasmparser::ComponentExternalKind::Type => {
818                let types = self.validator.types(0).unwrap();
819                let ty = types.component_any_type_at(index);
820                ComponentItem::Type(ty)
821            }
822        })
823    }
824
825    fn alias_module_instance_export(
826        &mut self,
827        kind: wasmparser::ExternalKind,
828        instance: ModuleInstanceIndex,
829        name: &'data str,
830    ) -> LocalInitializer<'data> {
831        match kind {
832            wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
833            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
834            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
835            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
836            wasmparser::ExternalKind::Tag => {
837                unimplemented!("wasm exceptions");
838            }
839        }
840    }
841
842    fn alias_component_outer(
843        &mut self,
844        kind: wasmparser::ComponentOuterAliasKind,
845        count: u32,
846        index: u32,
847    ) {
848        match kind {
849            wasmparser::ComponentOuterAliasKind::CoreType
850            | wasmparser::ComponentOuterAliasKind::Type => {}
851
852            // For more information about the implementation of outer aliases
853            // see the documentation of `LexicalScope`. Otherwise though the
854            // main idea here is that the data to close over starts as `Local`
855            // and then transitions to `Upvar` as its inserted into the parents
856            // in order from target we're aliasing back to the current
857            // component.
858            wasmparser::ComponentOuterAliasKind::CoreModule => {
859                let index = ModuleIndex::from_u32(index);
860                let mut module = ClosedOverModule::Local(index);
861                let depth = self.lexical_scopes.len() - (count as usize);
862                for frame in self.lexical_scopes[depth..].iter_mut() {
863                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
864                }
865
866                // If the `module` is still `Local` then the `depth` was 0 and
867                // it's an alias into our own space. Otherwise it's switched to
868                // an upvar and will index into the upvar space. Either way
869                // it's just plumbed directly into the initializer.
870                self.result
871                    .initializers
872                    .push(LocalInitializer::AliasModule(module));
873            }
874            wasmparser::ComponentOuterAliasKind::Component => {
875                let index = ComponentIndex::from_u32(index);
876                let mut component = ClosedOverComponent::Local(index);
877                let depth = self.lexical_scopes.len() - (count as usize);
878                for frame in self.lexical_scopes[depth..].iter_mut() {
879                    component =
880                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
881                }
882
883                self.result
884                    .initializers
885                    .push(LocalInitializer::AliasComponent(component));
886            }
887        }
888    }
889
890    fn canonical_options(&self, opts: &[wasmparser::CanonicalOption]) -> LocalCanonicalOptions {
891        let mut ret = LocalCanonicalOptions {
892            string_encoding: StringEncoding::Utf8,
893            memory: None,
894            realloc: None,
895            post_return: None,
896        };
897        for opt in opts {
898            match opt {
899                wasmparser::CanonicalOption::UTF8 => {
900                    ret.string_encoding = StringEncoding::Utf8;
901                }
902                wasmparser::CanonicalOption::UTF16 => {
903                    ret.string_encoding = StringEncoding::Utf16;
904                }
905                wasmparser::CanonicalOption::CompactUTF16 => {
906                    ret.string_encoding = StringEncoding::CompactUtf16;
907                }
908                wasmparser::CanonicalOption::Memory(idx) => {
909                    let idx = MemoryIndex::from_u32(*idx);
910                    ret.memory = Some(idx);
911                }
912                wasmparser::CanonicalOption::Realloc(idx) => {
913                    let idx = FuncIndex::from_u32(*idx);
914                    ret.realloc = Some(idx);
915                }
916                wasmparser::CanonicalOption::PostReturn(idx) => {
917                    let idx = FuncIndex::from_u32(*idx);
918                    ret.post_return = Some(idx);
919                }
920            }
921        }
922        return ret;
923    }
924
925    /// Get the interned type index for the `index`th core function.
926    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
927        let types = self.validator.types(0).unwrap();
928        let id = types.core_function_at(index);
929        let module = Module::default();
930        self.types
931            .module_types_builder()
932            .intern_type(&module, types, id)
933    }
934}
935
936impl Translation<'_> {
937    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
938        self.types.as_ref().unwrap().as_ref()
939    }
940}
941
942/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
943/// to disallow access to mutable access to the builder before the inlining
944/// pass.
945///
946/// Type information in this translation pass must be preserved at the
947/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
948/// own type system. Only during inlining are types fully assigned because
949/// that's when resource types become available as it's known which instance
950/// defines which resource, or more concretely the same component instantiated
951/// twice will produce two unique resource types unlike one as seen by
952/// wasmparser within the component.
953mod pre_inlining {
954    use super::*;
955
956    pub struct PreInliningComponentTypes<'a> {
957        types: &'a mut ComponentTypesBuilder,
958    }
959
960    impl<'a> PreInliningComponentTypes<'a> {
961        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
962            Self { types }
963        }
964
965        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
966            self.types.module_types_builder_mut()
967        }
968
969        pub fn types(&self) -> &ComponentTypesBuilder {
970            self.types
971        }
972
973        // NB: this should in theory only be used for the `inline` phase of
974        // translation.
975        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
976            self.types
977        }
978    }
979
980    impl TypeConvert for PreInliningComponentTypes<'_> {
981        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
982            self.types.lookup_heap_type(index)
983        }
984
985        fn lookup_type_index(
986            &self,
987            index: wasmparser::UnpackedIndex,
988        ) -> wasmtime_types::EngineOrModuleTypeIndex {
989            self.types.lookup_type_index(index)
990        }
991    }
992}
993use pre_inlining::PreInliningComponentTypes;