wasmtime_environ/component/
translate.rs

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