wasmtime_environ/component/
translate.rs

1use crate::ScopeVec;
2use crate::component::*;
3use crate::prelude::*;
4use crate::{
5    EngineOrModuleTypeIndex, EntityIndex, ModuleEnvironment, ModuleInternedTypeIndex,
6    ModuleTranslation, ModuleTypesBuilder, PrimaryMap, TagIndex, Tunables, TypeConvert,
7    WasmHeapType, WasmResult, WasmValType,
8};
9use anyhow::anyhow;
10use anyhow::{Result, bail};
11use indexmap::IndexMap;
12use std::collections::HashMap;
13use std::mem;
14use wasmparser::component_types::{
15    AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
16    ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
17};
18use wasmparser::types::Types;
19use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
20
21mod adapt;
22pub use self::adapt::*;
23mod inline;
24
25/// Structure used to translate a component and parse it.
26pub struct Translator<'a, 'data> {
27    /// The current component being translated.
28    ///
29    /// This will get swapped out as translation traverses the body of a
30    /// component and a sub-component is entered or left.
31    result: Translation<'data>,
32
33    /// Current state of parsing a binary component. Note that like `result`
34    /// this will change as the component is traversed.
35    parser: Parser,
36
37    /// Stack of lexical scopes that are in-progress but not finished yet.
38    ///
39    /// This is pushed to whenever a component is entered and popped from
40    /// whenever a component is left. Each lexical scope also contains
41    /// information about the variables that it is currently required to close
42    /// over which is threaded into the current in-progress translation of
43    /// the sub-component which pushed a scope here.
44    lexical_scopes: Vec<LexicalScope<'data>>,
45
46    /// The validator in use to verify that the raw input binary is a valid
47    /// component.
48    validator: &'a mut Validator,
49
50    /// Type information shared for the entire component.
51    ///
52    /// This builder is also used for all core wasm modules found to intern
53    /// signatures across all modules.
54    types: PreInliningComponentTypes<'a>,
55
56    /// The compiler configuration provided by the embedder.
57    tunables: &'a Tunables,
58
59    /// Auxiliary location to push generated adapter modules onto.
60    scope_vec: &'data ScopeVec<u8>,
61
62    /// Completely translated core wasm modules that have been found so far.
63    ///
64    /// Note that this translation only involves learning about type
65    /// information and functions are not actually compiled here.
66    static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
67
68    /// Completely translated components that have been found so far.
69    ///
70    /// As frames are popped from `lexical_scopes` their completed component
71    /// will be pushed onto this list.
72    static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
73}
74
75/// Representation of the syntactic scope of a component meaning where it is
76/// and what its state is at in the binary format.
77///
78/// These scopes are pushed and popped when a sub-component starts being
79/// parsed and finishes being parsed. The main purpose of this frame is to
80/// have a `ClosedOverVars` field which encapsulates data that is inherited
81/// from the scope specified into the component being translated just beneath
82/// it.
83///
84/// This structure exists to implement outer aliases to components and modules.
85/// When a component or module is closed over then that means it needs to be
86/// inherited in a sense to the component which actually had the alias. This is
87/// achieved with a deceptively simple scheme where each parent of the
88/// component with the alias will inherit the component from the desired
89/// location.
90///
91/// For example with a component structure that looks like:
92///
93/// ```wasm
94/// (component $A
95///     (core module $M)
96///     (component $B
97///         (component $C
98///             (alias outer $A $M (core module))
99///         )
100///     )
101/// )
102/// ```
103///
104/// here the `C` component is closing over `M` located in the root component
105/// `A`. When `C` is being translated the `lexical_scopes` field will look like
106/// `[A, B]`. When the alias is encountered (for module index 0) this will
107/// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
108/// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
109/// inserted into `closure_args` in `B`'s frame. This produces yet another
110/// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
111/// via `LocalInitializer::AliasModuleUpvar` with the last index.
112///
113/// All of these upvar indices and such are interpreted in the "inline" phase
114/// of compilation and not at runtime. This means that when `A` is being
115/// instantiated one of its initializers will be
116/// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
117/// variables captured for `B` are listed as local module 0, or `M`. This list
118/// is then preserved in the definition of the component `B` and later reused
119/// by `C` again to finally get access to the closed over component.
120///
121/// Effectively the scopes are managed hierarchically where a reference to an
122/// outer variable automatically injects references into all parents up to
123/// where the reference is. This variable scopes are the processed during
124/// inlining where a component definition is a reference to the static
125/// component information (`Translation`) plus closed over variables
126/// (`ComponentClosure` during inlining).
127struct LexicalScope<'data> {
128    /// Current state of translating the `translation` below.
129    parser: Parser,
130    /// Current state of the component's translation as found so far.
131    translation: Translation<'data>,
132    /// List of captures that `translation` will need to process to create the
133    /// sub-component which is directly beneath this lexical scope.
134    closure_args: ClosedOverVars,
135}
136
137/// A "local" translation of a component.
138///
139/// This structure is used as a sort of in-progress translation of a component.
140/// This is not `Component` which is the final form as consumed by Wasmtime
141/// at runtime. Instead this is a fairly simple representation of a component
142/// where almost everything is ordered as a list of initializers. The binary
143/// format is translated to a list of initializers here which is later processed
144/// during "inlining" to produce a final component with the final set of
145/// initializers.
146#[derive(Default)]
147struct Translation<'data> {
148    /// Instructions which form this component.
149    ///
150    /// There is one initializer for all members of each index space, and all
151    /// index spaces are incrementally built here as the initializer list is
152    /// processed.
153    initializers: Vec<LocalInitializer<'data>>,
154
155    /// The list of exports from this component, as pairs of names and an
156    /// index into an index space of what's being exported.
157    exports: IndexMap<&'data str, ComponentItem>,
158
159    /// Type information produced by `wasmparser` for this component.
160    ///
161    /// This type information is available after the translation of the entire
162    /// component has finished, e.g. for the `inline` pass, but beforehand this
163    /// is set to `None`.
164    types: Option<Types>,
165}
166
167// NB: the type information contained in `LocalInitializer` should always point
168// to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
169// fully determined due to resources until instantiations are known which is
170// tracked during the inlining phase. This means that all type information below
171// is straight from `wasmparser`'s passes.
172enum LocalInitializer<'data> {
173    // imports
174    Import(ComponentImportName<'data>, ComponentEntityType),
175
176    // canonical function sections
177    Lower {
178        func: ComponentFuncIndex,
179        lower_ty: ComponentFuncTypeId,
180        canonical_abi: ModuleInternedTypeIndex,
181        options: LocalCanonicalOptions,
182    },
183    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
184
185    // resources
186    Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
187    ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
188    ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
189    ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
190
191    BackpressureSet {
192        func: ModuleInternedTypeIndex,
193    },
194    TaskReturn {
195        func: ModuleInternedTypeIndex,
196        result: Option<ComponentValType>,
197        options: LocalCanonicalOptions,
198    },
199    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::TaskCancel
816                        | wasmparser::CanonicalFunction::SubtaskCancel { .. }
817                        | wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
818                        | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
819                        | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
820                            bail!("unsupported intrinsic")
821                        }
822                    };
823                    self.result.initializers.push(init);
824                }
825            }
826
827            // Core wasm modules are translated inline directly here with the
828            // `ModuleEnvironment` from core wasm compilation. This will return
829            // to the caller the size of the module so it knows how many bytes
830            // of the input are skipped.
831            //
832            // Note that this is just initial type translation of the core wasm
833            // module and actual function compilation is deferred until this
834            // entire process has completed.
835            Payload::ModuleSection {
836                parser,
837                unchecked_range,
838            } => {
839                let index = self.validator.types(0).unwrap().module_count();
840                self.validator.module_section(&unchecked_range)?;
841                let translation = ModuleEnvironment::new(
842                    self.tunables,
843                    self.validator,
844                    self.types.module_types_builder(),
845                )
846                .translate(
847                    parser,
848                    component
849                        .get(unchecked_range.start..unchecked_range.end)
850                        .ok_or_else(|| {
851                            anyhow!(
852                                "section range {}..{} is out of bounds (bound = {})",
853                                unchecked_range.start,
854                                unchecked_range.end,
855                                component.len()
856                            )
857                            .context("wasm component contains an invalid module section")
858                        })?,
859                )?;
860                let static_idx = self.static_modules.push(translation);
861                let types = self.validator.types(0).unwrap();
862                let ty = types.module_at(index);
863                self.result
864                    .initializers
865                    .push(LocalInitializer::ModuleStatic(static_idx, ty));
866                return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
867            }
868
869            // When a sub-component is found then the current translation state
870            // is pushed onto the `lexical_scopes` stack. This will subsequently
871            // get popped as part of `Payload::End` processing above.
872            //
873            // Note that the set of closure args for this new lexical scope
874            // starts empty since it will only get populated if translation of
875            // the nested component ends up aliasing some outer module or
876            // component.
877            Payload::ComponentSection {
878                parser,
879                unchecked_range,
880            } => {
881                self.validator.component_section(&unchecked_range)?;
882                self.lexical_scopes.push(LexicalScope {
883                    parser: mem::replace(&mut self.parser, parser),
884                    translation: mem::take(&mut self.result),
885                    closure_args: ClosedOverVars::default(),
886                });
887            }
888
889            // Both core wasm instances and component instances record
890            // initializers of what form of instantiation is performed which
891            // largely just records the arguments given from wasmparser into a
892            // `HashMap` for processing later during inlining.
893            Payload::InstanceSection(s) => {
894                self.validator.instance_section(&s)?;
895                for instance in s {
896                    let init = match instance? {
897                        wasmparser::Instance::Instantiate { module_index, args } => {
898                            let index = ModuleIndex::from_u32(module_index);
899                            self.instantiate_module(index, &args)
900                        }
901                        wasmparser::Instance::FromExports(exports) => {
902                            self.instantiate_module_from_exports(&exports)
903                        }
904                    };
905                    self.result.initializers.push(init);
906                }
907            }
908            Payload::ComponentInstanceSection(s) => {
909                let mut index = self.validator.types(0).unwrap().component_instance_count();
910                self.validator.component_instance_section(&s)?;
911                for instance in s {
912                    let types = self.validator.types(0).unwrap();
913                    let ty = types.component_instance_at(index);
914                    let init = match instance? {
915                        wasmparser::ComponentInstance::Instantiate {
916                            component_index,
917                            args,
918                        } => {
919                            let index = ComponentIndex::from_u32(component_index);
920                            self.instantiate_component(index, &args, ty)?
921                        }
922                        wasmparser::ComponentInstance::FromExports(exports) => {
923                            self.instantiate_component_from_exports(&exports, ty)?
924                        }
925                    };
926                    self.result.initializers.push(init);
927                    index += 1;
928                }
929            }
930
931            // Exports don't actually fill out the `initializers` array but
932            // instead fill out the one other field in a `Translation`, the
933            // `exports` field (as one might imagine). This for now simply
934            // records the index of what's exported and that's tracked further
935            // later during inlining.
936            Payload::ComponentExportSection(s) => {
937                self.validator.component_export_section(&s)?;
938                for export in s {
939                    let export = export?;
940                    let item = self.kind_to_item(export.kind, export.index)?;
941                    let prev = self.result.exports.insert(export.name.0, item);
942                    assert!(prev.is_none());
943                    self.result
944                        .initializers
945                        .push(LocalInitializer::Export(item));
946                }
947            }
948
949            Payload::ComponentStartSection { start, range } => {
950                self.validator.component_start_section(&start, &range)?;
951                unimplemented!("component start section");
952            }
953
954            // Aliases of instance exports (either core or component) will be
955            // recorded as an initializer of the appropriate type with outer
956            // aliases handled specially via upvars and type processing.
957            Payload::ComponentAliasSection(s) => {
958                self.validator.component_alias_section(&s)?;
959                for alias in s {
960                    let init = match alias? {
961                        wasmparser::ComponentAlias::InstanceExport {
962                            kind: _,
963                            instance_index,
964                            name,
965                        } => {
966                            let instance = ComponentInstanceIndex::from_u32(instance_index);
967                            LocalInitializer::AliasComponentExport(instance, name)
968                        }
969                        wasmparser::ComponentAlias::Outer { kind, count, index } => {
970                            self.alias_component_outer(kind, count, index);
971                            continue;
972                        }
973                        wasmparser::ComponentAlias::CoreInstanceExport {
974                            kind,
975                            instance_index,
976                            name,
977                        } => {
978                            let instance = ModuleInstanceIndex::from_u32(instance_index);
979                            self.alias_module_instance_export(kind, instance, name)
980                        }
981                    };
982                    self.result.initializers.push(init);
983                }
984            }
985
986            // All custom sections are ignored by Wasmtime at this time.
987            //
988            // FIXME(WebAssembly/component-model#14): probably want to specify
989            // and parse a `name` section here.
990            Payload::CustomSection { .. } => {}
991
992            // Anything else is either not reachable since we never enable the
993            // feature in Wasmtime or we do enable it and it's a bug we don't
994            // implement it, so let validation take care of most errors here and
995            // if it gets past validation provide a helpful error message to
996            // debug.
997            other => {
998                self.validator.payload(&other)?;
999                panic!("unimplemented section {other:?}");
1000            }
1001        }
1002
1003        Ok(Action::KeepGoing)
1004    }
1005
1006    fn instantiate_module(
1007        &mut self,
1008        module: ModuleIndex,
1009        raw_args: &[wasmparser::InstantiationArg<'data>],
1010    ) -> LocalInitializer<'data> {
1011        let mut args = HashMap::with_capacity(raw_args.len());
1012        for arg in raw_args {
1013            match arg.kind {
1014                wasmparser::InstantiationArgKind::Instance => {
1015                    let idx = ModuleInstanceIndex::from_u32(arg.index);
1016                    args.insert(arg.name, idx);
1017                }
1018            }
1019        }
1020        LocalInitializer::ModuleInstantiate(module, args)
1021    }
1022
1023    /// Creates a synthetic module from the list of items currently in the
1024    /// module and their given names.
1025    fn instantiate_module_from_exports(
1026        &mut self,
1027        exports: &[wasmparser::Export<'data>],
1028    ) -> LocalInitializer<'data> {
1029        let mut map = HashMap::with_capacity(exports.len());
1030        for export in exports {
1031            let idx = match export.kind {
1032                wasmparser::ExternalKind::Func => {
1033                    let index = FuncIndex::from_u32(export.index);
1034                    EntityIndex::Function(index)
1035                }
1036                wasmparser::ExternalKind::Table => {
1037                    let index = TableIndex::from_u32(export.index);
1038                    EntityIndex::Table(index)
1039                }
1040                wasmparser::ExternalKind::Memory => {
1041                    let index = MemoryIndex::from_u32(export.index);
1042                    EntityIndex::Memory(index)
1043                }
1044                wasmparser::ExternalKind::Global => {
1045                    let index = GlobalIndex::from_u32(export.index);
1046                    EntityIndex::Global(index)
1047                }
1048                wasmparser::ExternalKind::Tag => {
1049                    let index = TagIndex::from_u32(export.index);
1050                    EntityIndex::Tag(index)
1051                }
1052            };
1053            map.insert(export.name, idx);
1054        }
1055        LocalInitializer::ModuleSynthetic(map)
1056    }
1057
1058    fn instantiate_component(
1059        &mut self,
1060        component: ComponentIndex,
1061        raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1062        ty: ComponentInstanceTypeId,
1063    ) -> Result<LocalInitializer<'data>> {
1064        let mut args = HashMap::with_capacity(raw_args.len());
1065        for arg in raw_args {
1066            let idx = self.kind_to_item(arg.kind, arg.index)?;
1067            args.insert(arg.name, idx);
1068        }
1069
1070        Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1071    }
1072
1073    /// Creates a synthetic module from the list of items currently in the
1074    /// module and their given names.
1075    fn instantiate_component_from_exports(
1076        &mut self,
1077        exports: &[wasmparser::ComponentExport<'data>],
1078        ty: ComponentInstanceTypeId,
1079    ) -> Result<LocalInitializer<'data>> {
1080        let mut map = HashMap::with_capacity(exports.len());
1081        for export in exports {
1082            let idx = self.kind_to_item(export.kind, export.index)?;
1083            map.insert(export.name.0, idx);
1084        }
1085
1086        Ok(LocalInitializer::ComponentSynthetic(map, ty))
1087    }
1088
1089    fn kind_to_item(
1090        &mut self,
1091        kind: wasmparser::ComponentExternalKind,
1092        index: u32,
1093    ) -> Result<ComponentItem> {
1094        Ok(match kind {
1095            wasmparser::ComponentExternalKind::Func => {
1096                let index = ComponentFuncIndex::from_u32(index);
1097                ComponentItem::Func(index)
1098            }
1099            wasmparser::ComponentExternalKind::Module => {
1100                let index = ModuleIndex::from_u32(index);
1101                ComponentItem::Module(index)
1102            }
1103            wasmparser::ComponentExternalKind::Instance => {
1104                let index = ComponentInstanceIndex::from_u32(index);
1105                ComponentItem::ComponentInstance(index)
1106            }
1107            wasmparser::ComponentExternalKind::Component => {
1108                let index = ComponentIndex::from_u32(index);
1109                ComponentItem::Component(index)
1110            }
1111            wasmparser::ComponentExternalKind::Value => {
1112                unimplemented!("component values");
1113            }
1114            wasmparser::ComponentExternalKind::Type => {
1115                let types = self.validator.types(0).unwrap();
1116                let ty = types.component_any_type_at(index);
1117                ComponentItem::Type(ty)
1118            }
1119        })
1120    }
1121
1122    fn alias_module_instance_export(
1123        &mut self,
1124        kind: wasmparser::ExternalKind,
1125        instance: ModuleInstanceIndex,
1126        name: &'data str,
1127    ) -> LocalInitializer<'data> {
1128        match kind {
1129            wasmparser::ExternalKind::Func => LocalInitializer::AliasExportFunc(instance, name),
1130            wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1131            wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1132            wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1133            wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1134        }
1135    }
1136
1137    fn alias_component_outer(
1138        &mut self,
1139        kind: wasmparser::ComponentOuterAliasKind,
1140        count: u32,
1141        index: u32,
1142    ) {
1143        match kind {
1144            wasmparser::ComponentOuterAliasKind::CoreType
1145            | wasmparser::ComponentOuterAliasKind::Type => {}
1146
1147            // For more information about the implementation of outer aliases
1148            // see the documentation of `LexicalScope`. Otherwise though the
1149            // main idea here is that the data to close over starts as `Local`
1150            // and then transitions to `Upvar` as its inserted into the parents
1151            // in order from target we're aliasing back to the current
1152            // component.
1153            wasmparser::ComponentOuterAliasKind::CoreModule => {
1154                let index = ModuleIndex::from_u32(index);
1155                let mut module = ClosedOverModule::Local(index);
1156                let depth = self.lexical_scopes.len() - (count as usize);
1157                for frame in self.lexical_scopes[depth..].iter_mut() {
1158                    module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1159                }
1160
1161                // If the `module` is still `Local` then the `depth` was 0 and
1162                // it's an alias into our own space. Otherwise it's switched to
1163                // an upvar and will index into the upvar space. Either way
1164                // it's just plumbed directly into the initializer.
1165                self.result
1166                    .initializers
1167                    .push(LocalInitializer::AliasModule(module));
1168            }
1169            wasmparser::ComponentOuterAliasKind::Component => {
1170                let index = ComponentIndex::from_u32(index);
1171                let mut component = ClosedOverComponent::Local(index);
1172                let depth = self.lexical_scopes.len() - (count as usize);
1173                for frame in self.lexical_scopes[depth..].iter_mut() {
1174                    component =
1175                        ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1176                }
1177
1178                self.result
1179                    .initializers
1180                    .push(LocalInitializer::AliasComponent(component));
1181            }
1182        }
1183    }
1184
1185    fn canonical_options(&self, opts: &[wasmparser::CanonicalOption]) -> LocalCanonicalOptions {
1186        let mut ret = LocalCanonicalOptions {
1187            string_encoding: StringEncoding::Utf8,
1188            memory: None,
1189            realloc: None,
1190            post_return: None,
1191            async_: false,
1192            callback: None,
1193        };
1194        for opt in opts {
1195            match opt {
1196                wasmparser::CanonicalOption::UTF8 => {
1197                    ret.string_encoding = StringEncoding::Utf8;
1198                }
1199                wasmparser::CanonicalOption::UTF16 => {
1200                    ret.string_encoding = StringEncoding::Utf16;
1201                }
1202                wasmparser::CanonicalOption::CompactUTF16 => {
1203                    ret.string_encoding = StringEncoding::CompactUtf16;
1204                }
1205                wasmparser::CanonicalOption::Memory(idx) => {
1206                    let idx = MemoryIndex::from_u32(*idx);
1207                    ret.memory = Some(idx);
1208                }
1209                wasmparser::CanonicalOption::Realloc(idx) => {
1210                    let idx = FuncIndex::from_u32(*idx);
1211                    ret.realloc = Some(idx);
1212                }
1213                wasmparser::CanonicalOption::PostReturn(idx) => {
1214                    let idx = FuncIndex::from_u32(*idx);
1215                    ret.post_return = Some(idx);
1216                }
1217                wasmparser::CanonicalOption::Async => ret.async_ = true,
1218                wasmparser::CanonicalOption::Callback(idx) => {
1219                    let idx = FuncIndex::from_u32(*idx);
1220                    ret.callback = Some(idx);
1221                }
1222                wasmparser::CanonicalOption::CoreType(_) => todo!(),
1223            }
1224        }
1225        return ret;
1226    }
1227
1228    /// Get the interned type index for the `index`th core function.
1229    fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1230        let types = self.validator.types(0).unwrap();
1231        let id = types.core_function_at(index);
1232        self.types.module_types_builder().intern_type(types, id)
1233    }
1234}
1235
1236impl Translation<'_> {
1237    fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1238        self.types.as_ref().unwrap().as_ref()
1239    }
1240}
1241
1242/// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1243/// to disallow access to mutable access to the builder before the inlining
1244/// pass.
1245///
1246/// Type information in this translation pass must be preserved at the
1247/// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1248/// own type system. Only during inlining are types fully assigned because
1249/// that's when resource types become available as it's known which instance
1250/// defines which resource, or more concretely the same component instantiated
1251/// twice will produce two unique resource types unlike one as seen by
1252/// wasmparser within the component.
1253mod pre_inlining {
1254    use super::*;
1255
1256    pub struct PreInliningComponentTypes<'a> {
1257        types: &'a mut ComponentTypesBuilder,
1258    }
1259
1260    impl<'a> PreInliningComponentTypes<'a> {
1261        pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1262            Self { types }
1263        }
1264
1265        pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1266            self.types.module_types_builder_mut()
1267        }
1268
1269        pub fn types(&self) -> &ComponentTypesBuilder {
1270            self.types
1271        }
1272
1273        // NB: this should in theory only be used for the `inline` phase of
1274        // translation.
1275        pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1276            self.types
1277        }
1278    }
1279
1280    impl TypeConvert for PreInliningComponentTypes<'_> {
1281        fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1282            self.types.lookup_heap_type(index)
1283        }
1284
1285        fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1286            self.types.lookup_type_index(index)
1287        }
1288    }
1289}
1290use pre_inlining::PreInliningComponentTypes;