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