1 use crate::Abi;
2 use crate::component::dfg::AbstractInstantiations;
3 use crate::component::*;
4 use crate::prelude::*;
5 use crate::{
6     EngineOrModuleTypeIndex, EntityIndex, FuncKey, ModuleEnvironment, ModuleInternedTypeIndex,
7     ModuleTranslation, ModuleTypesBuilder, PrimaryMap, ScopeVec, TagIndex, Tunables, TypeConvert,
8     WasmHeapType, WasmResult, WasmValType,
9 };
10 use core::str::FromStr;
11 use cranelift_entity::SecondaryMap;
12 use cranelift_entity::packed_option::PackedOption;
13 use indexmap::IndexMap;
14 use std::collections::HashMap;
15 use std::mem;
16 use wasmparser::component_types::{
17     AliasableResourceId, ComponentCoreModuleTypeId, ComponentDefinedTypeId, ComponentEntityType,
18     ComponentFuncTypeId, ComponentInstanceTypeId, ComponentValType,
19 };
20 use wasmparser::types::Types;
21 use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
22 
23 mod adapt;
24 pub use self::adapt::*;
25 mod inline;
26 
27 /// Structure used to translate a component and parse it.
28 pub struct Translator<'a, 'data> {
29     /// The current component being translated.
30     ///
31     /// This will get swapped out as translation traverses the body of a
32     /// component and a sub-component is entered or left.
33     result: Translation<'data>,
34 
35     /// Current state of parsing a binary component. Note that like `result`
36     /// this will change as the component is traversed.
37     parser: Parser,
38 
39     /// Stack of lexical scopes that are in-progress but not finished yet.
40     ///
41     /// This is pushed to whenever a component is entered and popped from
42     /// whenever a component is left. Each lexical scope also contains
43     /// information about the variables that it is currently required to close
44     /// over which is threaded into the current in-progress translation of
45     /// the sub-component which pushed a scope here.
46     lexical_scopes: Vec<LexicalScope<'data>>,
47 
48     /// The validator in use to verify that the raw input binary is a valid
49     /// component.
50     validator: &'a mut Validator,
51 
52     /// Type information shared for the entire component.
53     ///
54     /// This builder is also used for all core wasm modules found to intern
55     /// signatures across all modules.
56     types: PreInliningComponentTypes<'a>,
57 
58     /// The compiler configuration provided by the embedder.
59     tunables: &'a Tunables,
60 
61     /// Auxiliary location to push generated adapter modules onto.
62     scope_vec: &'data ScopeVec<u8>,
63 
64     /// Completely translated core wasm modules that have been found so far.
65     ///
66     /// Note that this translation only involves learning about type
67     /// information and functions are not actually compiled here.
68     static_modules: PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
69 
70     /// Completely translated components that have been found so far.
71     ///
72     /// As frames are popped from `lexical_scopes` their completed component
73     /// will be pushed onto this list.
74     static_components: PrimaryMap<StaticComponentIndex, Translation<'data>>,
75 
76     /// The top-level import name for Wasmtime's unsafe intrinsics, if any.
77     unsafe_intrinsics_import: Option<&'a str>,
78 }
79 
80 /// Representation of the syntactic scope of a component meaning where it is
81 /// and what its state is at in the binary format.
82 ///
83 /// These scopes are pushed and popped when a sub-component starts being
84 /// parsed and finishes being parsed. The main purpose of this frame is to
85 /// have a `ClosedOverVars` field which encapsulates data that is inherited
86 /// from the scope specified into the component being translated just beneath
87 /// it.
88 ///
89 /// This structure exists to implement outer aliases to components and modules.
90 /// When a component or module is closed over then that means it needs to be
91 /// inherited in a sense to the component which actually had the alias. This is
92 /// achieved with a deceptively simple scheme where each parent of the
93 /// component with the alias will inherit the component from the desired
94 /// location.
95 ///
96 /// For example with a component structure that looks like:
97 ///
98 /// ```wasm
99 /// (component $A
100 ///     (core module $M)
101 ///     (component $B
102 ///         (component $C
103 ///             (alias outer $A $M (core module))
104 ///         )
105 ///     )
106 /// )
107 /// ```
108 ///
109 /// here the `C` component is closing over `M` located in the root component
110 /// `A`. When `C` is being translated the `lexical_scopes` field will look like
111 /// `[A, B]`. When the alias is encountered (for module index 0) this will
112 /// place a `ClosedOverModule::Local(0)` entry into the `closure_args` field of
113 /// `A`'s frame. This will in turn give a `ModuleUpvarIndex` which is then
114 /// inserted into `closure_args` in `B`'s frame. This produces yet another
115 /// `ModuleUpvarIndex` which is finally inserted into `C`'s module index space
116 /// via `LocalInitializer::AliasModuleUpvar` with the last index.
117 ///
118 /// All of these upvar indices and such are interpreted in the "inline" phase
119 /// of compilation and not at runtime. This means that when `A` is being
120 /// instantiated one of its initializers will be
121 /// `LocalInitializer::ComponentStatic`. This starts to create `B` and the
122 /// variables captured for `B` are listed as local module 0, or `M`. This list
123 /// is then preserved in the definition of the component `B` and later reused
124 /// by `C` again to finally get access to the closed over component.
125 ///
126 /// Effectively the scopes are managed hierarchically where a reference to an
127 /// outer variable automatically injects references into all parents up to
128 /// where the reference is. This variable scopes are the processed during
129 /// inlining where a component definition is a reference to the static
130 /// component information (`Translation`) plus closed over variables
131 /// (`ComponentClosure` during inlining).
132 struct LexicalScope<'data> {
133     /// Current state of translating the `translation` below.
134     parser: Parser,
135     /// Current state of the component's translation as found so far.
136     translation: Translation<'data>,
137     /// List of captures that `translation` will need to process to create the
138     /// sub-component which is directly beneath this lexical scope.
139     closure_args: ClosedOverVars,
140 }
141 
142 /// A "local" translation of a component.
143 ///
144 /// This structure is used as a sort of in-progress translation of a component.
145 /// This is not `Component` which is the final form as consumed by Wasmtime
146 /// at runtime. Instead this is a fairly simple representation of a component
147 /// where almost everything is ordered as a list of initializers. The binary
148 /// format is translated to a list of initializers here which is later processed
149 /// during "inlining" to produce a final component with the final set of
150 /// initializers.
151 #[derive(Default)]
152 struct Translation<'data> {
153     /// Instructions which form this component.
154     ///
155     /// There is one initializer for all members of each index space, and all
156     /// index spaces are incrementally built here as the initializer list is
157     /// processed.
158     initializers: Vec<LocalInitializer<'data>>,
159 
160     /// The list of exports from this component, as pairs of names and an
161     /// index into an index space of what's being exported.
162     exports: IndexMap<&'data str, ComponentItem>,
163 
164     /// Type information produced by `wasmparser` for this component.
165     ///
166     /// This type information is available after the translation of the entire
167     /// component has finished, e.g. for the `inline` pass, but beforehand this
168     /// is set to `None`.
169     types: Option<Types>,
170 }
171 
172 // NB: the type information contained in `LocalInitializer` should always point
173 // to `wasmparser`'s type information, not Wasmtime's. Component types cannot be
174 // fully determined due to resources until instantiations are known which is
175 // tracked during the inlining phase. This means that all type information below
176 // is straight from `wasmparser`'s passes.
177 enum LocalInitializer<'data> {
178     // imports
179     Import(ComponentImportName<'data>, ComponentEntityType),
180 
181     // An import of an intrinsic for compile-time builtins.
182     IntrinsicsImport,
183 
184     // canonical function sections
185     Lower {
186         func: ComponentFuncIndex,
187         lower_ty: ComponentFuncTypeId,
188         options: LocalCanonicalOptions,
189     },
190     Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
191 
192     // resources
193     Resource(AliasableResourceId, WasmValType, Option<FuncIndex>),
194     ResourceNew(AliasableResourceId, ModuleInternedTypeIndex),
195     ResourceRep(AliasableResourceId, ModuleInternedTypeIndex),
196     ResourceDrop(AliasableResourceId, ModuleInternedTypeIndex),
197 
198     BackpressureInc {
199         func: ModuleInternedTypeIndex,
200     },
201     BackpressureDec {
202         func: ModuleInternedTypeIndex,
203     },
204     TaskReturn {
205         result: Option<ComponentValType>,
206         options: LocalCanonicalOptions,
207     },
208     TaskCancel {
209         func: ModuleInternedTypeIndex,
210     },
211     WaitableSetNew {
212         func: ModuleInternedTypeIndex,
213     },
214     WaitableSetWait {
215         options: LocalCanonicalOptions,
216     },
217     WaitableSetPoll {
218         options: LocalCanonicalOptions,
219     },
220     WaitableSetDrop {
221         func: ModuleInternedTypeIndex,
222     },
223     WaitableJoin {
224         func: ModuleInternedTypeIndex,
225     },
226     ThreadYield {
227         func: ModuleInternedTypeIndex,
228         cancellable: bool,
229     },
230     SubtaskDrop {
231         func: ModuleInternedTypeIndex,
232     },
233     SubtaskCancel {
234         func: ModuleInternedTypeIndex,
235         async_: bool,
236     },
237     StreamNew {
238         ty: ComponentDefinedTypeId,
239         func: ModuleInternedTypeIndex,
240     },
241     StreamRead {
242         ty: ComponentDefinedTypeId,
243         options: LocalCanonicalOptions,
244     },
245     StreamWrite {
246         ty: ComponentDefinedTypeId,
247         options: LocalCanonicalOptions,
248     },
249     StreamCancelRead {
250         ty: ComponentDefinedTypeId,
251         func: ModuleInternedTypeIndex,
252         async_: bool,
253     },
254     StreamCancelWrite {
255         ty: ComponentDefinedTypeId,
256         func: ModuleInternedTypeIndex,
257         async_: bool,
258     },
259     StreamDropReadable {
260         ty: ComponentDefinedTypeId,
261         func: ModuleInternedTypeIndex,
262     },
263     StreamDropWritable {
264         ty: ComponentDefinedTypeId,
265         func: ModuleInternedTypeIndex,
266     },
267     FutureNew {
268         ty: ComponentDefinedTypeId,
269         func: ModuleInternedTypeIndex,
270     },
271     FutureRead {
272         ty: ComponentDefinedTypeId,
273         options: LocalCanonicalOptions,
274     },
275     FutureWrite {
276         ty: ComponentDefinedTypeId,
277         options: LocalCanonicalOptions,
278     },
279     FutureCancelRead {
280         ty: ComponentDefinedTypeId,
281         func: ModuleInternedTypeIndex,
282         async_: bool,
283     },
284     FutureCancelWrite {
285         ty: ComponentDefinedTypeId,
286         func: ModuleInternedTypeIndex,
287         async_: bool,
288     },
289     FutureDropReadable {
290         ty: ComponentDefinedTypeId,
291         func: ModuleInternedTypeIndex,
292     },
293     FutureDropWritable {
294         ty: ComponentDefinedTypeId,
295         func: ModuleInternedTypeIndex,
296     },
297     ErrorContextNew {
298         options: LocalCanonicalOptions,
299     },
300     ErrorContextDebugMessage {
301         options: LocalCanonicalOptions,
302     },
303     ErrorContextDrop {
304         func: ModuleInternedTypeIndex,
305     },
306     ContextGet {
307         func: ModuleInternedTypeIndex,
308         i: u32,
309     },
310     ContextSet {
311         func: ModuleInternedTypeIndex,
312         i: u32,
313     },
314     ThreadIndex {
315         func: ModuleInternedTypeIndex,
316     },
317     ThreadNewIndirect {
318         func: ModuleInternedTypeIndex,
319         start_func_ty: ComponentTypeIndex,
320         start_func_table_index: TableIndex,
321     },
322     ThreadSuspendToSuspended {
323         func: ModuleInternedTypeIndex,
324         cancellable: bool,
325     },
326     ThreadSuspend {
327         func: ModuleInternedTypeIndex,
328         cancellable: bool,
329     },
330     ThreadSuspendTo {
331         func: ModuleInternedTypeIndex,
332         cancellable: bool,
333     },
334     ThreadUnsuspend {
335         func: ModuleInternedTypeIndex,
336     },
337     ThreadYieldToSuspended {
338         func: ModuleInternedTypeIndex,
339         cancellable: bool,
340     },
341 
342     // core wasm modules
343     ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
344 
345     // core wasm module instances
346     ModuleInstantiate(ModuleIndex, HashMap<&'data str, ModuleInstanceIndex>),
347     ModuleSynthetic(HashMap<&'data str, EntityIndex>),
348 
349     // components
350     ComponentStatic(StaticComponentIndex, ClosedOverVars),
351 
352     // component instances
353     ComponentInstantiate(
354         ComponentIndex,
355         HashMap<&'data str, ComponentItem>,
356         ComponentInstanceTypeId,
357     ),
358     ComponentSynthetic(HashMap<&'data str, ComponentItem>, ComponentInstanceTypeId),
359 
360     // alias section
361     AliasExportFunc(ModuleInstanceIndex, &'data str),
362     AliasExportTable(ModuleInstanceIndex, &'data str),
363     AliasExportGlobal(ModuleInstanceIndex, &'data str),
364     AliasExportMemory(ModuleInstanceIndex, &'data str),
365     AliasExportTag(ModuleInstanceIndex, &'data str),
366     AliasComponentExport(ComponentInstanceIndex, &'data str),
367     AliasModule(ClosedOverModule),
368     AliasComponent(ClosedOverComponent),
369 
370     // export section
371     Export(ComponentItem),
372 }
373 
374 /// The "closure environment" of components themselves.
375 ///
376 /// For more information see `LexicalScope`.
377 #[derive(Default)]
378 struct ClosedOverVars {
379     components: PrimaryMap<ComponentUpvarIndex, ClosedOverComponent>,
380     modules: PrimaryMap<ModuleUpvarIndex, ClosedOverModule>,
381 }
382 
383 /// Description how a component is closed over when the closure variables for
384 /// a component are being created.
385 ///
386 /// For more information see `LexicalScope`.
387 enum ClosedOverComponent {
388     /// A closed over component is coming from the local component's index
389     /// space, meaning a previously defined component is being captured.
390     Local(ComponentIndex),
391     /// A closed over component is coming from our own component's list of
392     /// upvars. This list was passed to us by our enclosing component, which
393     /// will eventually have bottomed out in closing over a `Local` component
394     /// index for some parent component.
395     Upvar(ComponentUpvarIndex),
396 }
397 
398 /// Same as `ClosedOverComponent`, but for modules.
399 enum ClosedOverModule {
400     Local(ModuleIndex),
401     Upvar(ModuleUpvarIndex),
402 }
403 
404 /// The data model for objects that are not unboxed in locals.
405 #[derive(Debug, Clone, Hash, Eq, PartialEq)]
406 pub enum LocalDataModel {
407     /// Data is stored in GC objects.
408     Gc {},
409 
410     /// Data is stored in a linear memory.
411     LinearMemory {
412         /// An optional memory definition supplied.
413         memory: Option<MemoryIndex>,
414         /// An optional definition of `realloc` to used.
415         realloc: Option<FuncIndex>,
416     },
417 }
418 
419 /// Representation of canonical ABI options.
420 struct LocalCanonicalOptions {
421     string_encoding: StringEncoding,
422     post_return: Option<FuncIndex>,
423     async_: bool,
424     cancellable: bool,
425     callback: Option<FuncIndex>,
426     /// The type index of the core GC types signature.
427     core_type: ModuleInternedTypeIndex,
428     data_model: LocalDataModel,
429 }
430 
431 enum Action {
432     KeepGoing,
433     Skip(usize),
434     Done,
435 }
436 
437 impl<'a, 'data> Translator<'a, 'data> {
438     /// Creates a new translation state ready to translate a component.
new( tunables: &'a Tunables, validator: &'a mut Validator, types: &'a mut ComponentTypesBuilder, scope_vec: &'data ScopeVec<u8>, ) -> Self439     pub fn new(
440         tunables: &'a Tunables,
441         validator: &'a mut Validator,
442         types: &'a mut ComponentTypesBuilder,
443         scope_vec: &'data ScopeVec<u8>,
444     ) -> Self {
445         let mut parser = Parser::new(0);
446         parser.set_features(*validator.features());
447         Self {
448             result: Translation::default(),
449             tunables,
450             validator,
451             types: PreInliningComponentTypes::new(types),
452             parser,
453             lexical_scopes: Vec::new(),
454             static_components: Default::default(),
455             static_modules: Default::default(),
456             scope_vec,
457             unsafe_intrinsics_import: None,
458         }
459     }
460 
461     /// Expose Wasmtime's unsafe intrinsics under the given top-level import
462     /// name.
expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self463     pub fn expose_unsafe_intrinsics(&mut self, name: &'a str) -> &mut Self {
464         assert!(self.unsafe_intrinsics_import.is_none());
465         self.unsafe_intrinsics_import = Some(name);
466         self
467     }
468 
469     /// Translates the binary `component`.
470     ///
471     /// This is the workhorse of compilation which will parse all of
472     /// `component` and create type information for Wasmtime and such. The
473     /// `component` does not have to be valid and it will be validated during
474     /// compilation.
475     ///
476     /// The result of this function is a tuple of the final component's
477     /// description plus a list of core wasm modules found within the
478     /// component. The component's description actually erases internal
479     /// components, instances, etc, as much as it can. Instead `Component`
480     /// retains a flat list of initializers (no nesting) which was created
481     /// as part of compilation from the nested structure of the original
482     /// component.
483     ///
484     /// The list of core wasm modules found is provided to allow compiling
485     /// modules externally in parallel. Additionally initializers in
486     /// `Component` may refer to the modules in the map returned by index.
487     ///
488     /// # Errors
489     ///
490     /// This function will return an error if the `component` provided is
491     /// invalid.
translate( mut self, component: &'data [u8], ) -> Result<( ComponentTranslation, PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>, )>492     pub fn translate(
493         mut self,
494         component: &'data [u8],
495     ) -> Result<(
496         ComponentTranslation,
497         PrimaryMap<StaticModuleIndex, ModuleTranslation<'data>>,
498     )> {
499         // First up wasmparser is used to actually perform the translation and
500         // validation of this component. This will produce a list of core wasm
501         // modules in addition to components which are found during the
502         // translation process. When doing this only a `Translation` is created
503         // which is a simple representation of a component.
504         let mut remaining = component;
505         loop {
506             let payload = match self.parser.parse(remaining, true)? {
507                 Chunk::Parsed { payload, consumed } => {
508                     remaining = &remaining[consumed..];
509                     payload
510                 }
511                 Chunk::NeedMoreData(_) => unreachable!(),
512             };
513 
514             match self.translate_payload(payload, component)? {
515                 Action::KeepGoing => {}
516                 Action::Skip(n) => remaining = &remaining[n..],
517                 Action::Done => break,
518             }
519         }
520         assert!(remaining.is_empty());
521         assert!(self.lexical_scopes.is_empty());
522 
523         // ... after translation initially finishes the next pass is performed
524         // which we're calling "inlining". This will "instantiate" the root
525         // component, following nested component instantiations, creating a
526         // global list of initializers along the way. This phase uses the simple
527         // initializers in each component to track dataflow of host imports and
528         // internal references to items throughout a component at compile-time.
529         // The produce initializers in the final `Component` are intended to be
530         // much simpler than the original component and more efficient for
531         // Wasmtime to process at runtime as well (e.g. no string lookups as
532         // most everything is done through indices instead).
533         let mut component = inline::run(
534             self.types.types_mut_for_inlining(),
535             &self.result,
536             &self.static_modules,
537             &self.static_components,
538         )?;
539 
540         self.partition_adapter_modules(&mut component);
541 
542         let translation =
543             component.finish(self.types.types_mut_for_inlining(), self.result.types_ref())?;
544 
545         self.analyze_function_imports(&translation);
546 
547         Ok((translation, self.static_modules))
548     }
549 
analyze_function_imports(&mut self, translation: &ComponentTranslation)550     fn analyze_function_imports(&mut self, translation: &ComponentTranslation) {
551         // First, abstract interpret the initializers to create a map from each
552         // static module to its abstract set of instantiations.
553         let mut instantiations = SecondaryMap::<StaticModuleIndex, AbstractInstantiations>::new();
554         let mut instance_to_module =
555             PrimaryMap::<RuntimeInstanceIndex, PackedOption<StaticModuleIndex>>::new();
556         for init in &translation.component.initializers {
557             match init {
558                 GlobalInitializer::InstantiateModule(instantiation, _) => match instantiation {
559                     InstantiateModule::Static(module, args) => {
560                         instantiations[*module].join(AbstractInstantiations::One(&*args));
561                         instance_to_module.push(Some(*module).into());
562                     }
563                     _ => {
564                         instance_to_module.push(None.into());
565                     }
566                 },
567                 _ => continue,
568             }
569         }
570 
571         // Second, make sure to mark exported modules as instantiated many
572         // times, since they could be linked with who-knows-what at runtime.
573         for item in translation.component.export_items.values() {
574             if let Export::ModuleStatic { index, .. } = item {
575                 instantiations[*index].join(AbstractInstantiations::Many)
576             }
577         }
578 
579         // Finally, iterate over our instantiations and record statically-known
580         // function imports so that they can get translated into direct calls
581         // (and eventually get inlined) rather than indirect calls through the
582         // imports table.
583         for (module, instantiations) in instantiations.iter() {
584             let args = match instantiations {
585                 dfg::AbstractInstantiations::Many | dfg::AbstractInstantiations::None => continue,
586                 dfg::AbstractInstantiations::One(args) => args,
587             };
588 
589             let mut imported_func_counter = 0_u32;
590             for (i, arg) in args.iter().enumerate() {
591                 // Only consider function imports.
592                 let (_, _, crate::types::EntityType::Function(_)) =
593                     self.static_modules[module].module.import(i).unwrap()
594                 else {
595                     continue;
596                 };
597 
598                 let imported_func = FuncIndex::from_u32(imported_func_counter);
599                 imported_func_counter += 1;
600                 debug_assert!(
601                     self.static_modules[module]
602                         .module
603                         .defined_func_index(imported_func)
604                         .is_none()
605                 );
606 
607                 let known_func = match arg {
608                     CoreDef::InstanceFlags(_) => unreachable!("instance flags are not a function"),
609                     CoreDef::TaskMayBlock => unreachable!("task_may_block is not a function"),
610 
611                     // We could in theory inline these trampolines, so it could
612                     // potentially make sense to record that we know this
613                     // imported function is this particular trampoline. However,
614                     // everything else is based around (module,
615                     // defined-function) pairs and these trampolines don't fit
616                     // that paradigm. Also, inlining trampolines gets really
617                     // tricky when we consider the stack pointer, frame pointer,
618                     // and return address note-taking that they do for the
619                     // purposes of stack walking. We could, with enough effort,
620                     // turn them into direct calls even though we probably
621                     // wouldn't ever inline them, but it just doesn't seem worth
622                     // the effort.
623                     CoreDef::Trampoline(_) => continue,
624 
625                     // This import is a compile-time builtin intrinsic, we
626                     // should inline its implementation during function
627                     // translation.
628                     CoreDef::UnsafeIntrinsic(i) => FuncKey::UnsafeIntrinsic(Abi::Wasm, *i),
629 
630                     // This imported function is an export from another
631                     // instance, a perfect candidate for becoming an inlinable
632                     // direct call!
633                     CoreDef::Export(export) => {
634                         let Some(arg_module) = &instance_to_module[export.instance].expand() else {
635                             // Instance of a dynamic module that is not part of
636                             // this component, not a statically-known module
637                             // inside this component. We have to do an indirect
638                             // call.
639                             continue;
640                         };
641 
642                         let ExportItem::Index(EntityIndex::Function(arg_func)) = &export.item
643                         else {
644                             unreachable!("function imports must be functions")
645                         };
646 
647                         let Some(arg_module_def_func) = self.static_modules[*arg_module]
648                             .module
649                             .defined_func_index(*arg_func)
650                         else {
651                             // TODO: we should ideally follow re-export chains
652                             // to bottom out the instantiation argument in
653                             // either a definition or an import at the root
654                             // component boundary. In practice, this pattern is
655                             // rare, so following these chains is left for the
656                             // Future.
657                             continue;
658                         };
659 
660                         FuncKey::DefinedWasmFunction(*arg_module, arg_module_def_func)
661                     }
662                 };
663 
664                 assert!(
665                     self.static_modules[module].known_imported_functions[imported_func].is_none()
666                 );
667                 self.static_modules[module].known_imported_functions[imported_func] =
668                     Some(known_func);
669             }
670         }
671     }
672 
translate_payload( &mut self, payload: Payload<'data>, component: &'data [u8], ) -> Result<Action>673     fn translate_payload(
674         &mut self,
675         payload: Payload<'data>,
676         component: &'data [u8],
677     ) -> Result<Action> {
678         match payload {
679             Payload::Version {
680                 num,
681                 encoding,
682                 range,
683             } => {
684                 self.validator.version(num, encoding, &range)?;
685 
686                 match encoding {
687                     Encoding::Component => {}
688                     Encoding::Module => {
689                         bail!("attempted to parse a wasm module with a component parser");
690                     }
691                 }
692             }
693 
694             Payload::End(offset) => {
695                 assert!(self.result.types.is_none());
696                 self.result.types = Some(self.validator.end(offset)?);
697 
698                 // Exit the current lexical scope. If there is no parent (no
699                 // frame currently on the stack) then translation is finished.
700                 // Otherwise that means that a nested component has been
701                 // completed and is recorded as such.
702                 let LexicalScope {
703                     parser,
704                     translation,
705                     closure_args,
706                 } = match self.lexical_scopes.pop() {
707                     Some(frame) => frame,
708                     None => return Ok(Action::Done),
709                 };
710                 self.parser = parser;
711                 let component = mem::replace(&mut self.result, translation);
712                 let static_idx = self.static_components.push(component);
713                 self.result
714                     .initializers
715                     .push(LocalInitializer::ComponentStatic(static_idx, closure_args));
716             }
717 
718             // When we see a type section the types are validated and then
719             // translated into Wasmtime's representation. Each active type
720             // definition is recorded in the `ComponentTypesBuilder` tables, or
721             // this component's active scope.
722             //
723             // Note that the push/pop of the component types scope happens above
724             // in `Version` and `End` since multiple type sections can appear
725             // within a component.
726             Payload::ComponentTypeSection(s) => {
727                 let mut component_type_index =
728                     self.validator.types(0).unwrap().component_type_count();
729                 self.validator.component_type_section(&s)?;
730 
731                 // Look for resource types and if a local resource is defined
732                 // then an initializer is added to define that resource type and
733                 // reference its destructor.
734                 let types = self.validator.types(0).unwrap();
735                 for ty in s {
736                     match ty? {
737                         wasmparser::ComponentType::Resource { rep, dtor } => {
738                             let rep = self.types.convert_valtype(rep)?;
739                             let id = types
740                                 .component_any_type_at(component_type_index)
741                                 .unwrap_resource();
742                             let dtor = dtor.map(FuncIndex::from_u32);
743                             self.result
744                                 .initializers
745                                 .push(LocalInitializer::Resource(id, rep, dtor));
746                         }
747 
748                         // no extra processing needed
749                         wasmparser::ComponentType::Defined(_)
750                         | wasmparser::ComponentType::Func(_)
751                         | wasmparser::ComponentType::Instance(_)
752                         | wasmparser::ComponentType::Component(_) => {}
753                     }
754 
755                     component_type_index += 1;
756                 }
757             }
758             Payload::CoreTypeSection(s) => {
759                 self.validator.core_type_section(&s)?;
760             }
761 
762             // Processing the import section at this point is relatively simple
763             // which is to simply record the name of the import and the type
764             // information associated with it.
765             Payload::ComponentImportSection(s) => {
766                 self.validator.component_import_section(&s)?;
767                 for import in s {
768                     let import = import?;
769                     let types = self.validator.types(0).unwrap();
770                     let ty = types
771                         .component_entity_type_of_import(import.name.0)
772                         .unwrap();
773 
774                     if self.is_unsafe_intrinsics_import(import.name.0) {
775                         self.check_unsafe_intrinsics_import(import.name.0, ty)?;
776                         self.result
777                             .initializers
778                             .push(LocalInitializer::IntrinsicsImport);
779                     } else {
780                         self.result
781                             .initializers
782                             .push(LocalInitializer::Import(import.name, ty));
783                     }
784                 }
785             }
786 
787             // Entries in the canonical section will get initializers recorded
788             // with the listed options for lifting/lowering.
789             Payload::ComponentCanonicalSection(s) => {
790                 let types = self.validator.types(0).unwrap();
791                 let mut core_func_index = types.function_count();
792                 self.validator.component_canonical_section(&s)?;
793                 for func in s {
794                     let init = match func? {
795                         wasmparser::CanonicalFunction::Lift {
796                             type_index,
797                             core_func_index,
798                             options,
799                         } => {
800                             let ty = self
801                                 .validator
802                                 .types(0)
803                                 .unwrap()
804                                 .component_any_type_at(type_index)
805                                 .unwrap_func();
806 
807                             let func = FuncIndex::from_u32(core_func_index);
808                             let options = self.canonical_options(&options, core_func_index)?;
809                             LocalInitializer::Lift(ty, func, options)
810                         }
811                         wasmparser::CanonicalFunction::Lower {
812                             func_index,
813                             options,
814                         } => {
815                             let lower_ty = self
816                                 .validator
817                                 .types(0)
818                                 .unwrap()
819                                 .component_function_at(func_index);
820                             let func = ComponentFuncIndex::from_u32(func_index);
821                             let options = self.canonical_options(&options, core_func_index)?;
822                             core_func_index += 1;
823                             LocalInitializer::Lower {
824                                 func,
825                                 options,
826                                 lower_ty,
827                             }
828                         }
829                         wasmparser::CanonicalFunction::ResourceNew { resource } => {
830                             let resource = self
831                                 .validator
832                                 .types(0)
833                                 .unwrap()
834                                 .component_any_type_at(resource)
835                                 .unwrap_resource();
836                             let ty = self.core_func_signature(core_func_index)?;
837                             core_func_index += 1;
838                             LocalInitializer::ResourceNew(resource, ty)
839                         }
840                         wasmparser::CanonicalFunction::ResourceDrop { resource } => {
841                             let resource = self
842                                 .validator
843                                 .types(0)
844                                 .unwrap()
845                                 .component_any_type_at(resource)
846                                 .unwrap_resource();
847                             let ty = self.core_func_signature(core_func_index)?;
848                             core_func_index += 1;
849                             LocalInitializer::ResourceDrop(resource, ty)
850                         }
851                         wasmparser::CanonicalFunction::ResourceDropAsync { resource } => {
852                             let _ = resource;
853                             bail!("support for `resource.drop async` not implemented yet")
854                         }
855                         wasmparser::CanonicalFunction::ResourceRep { resource } => {
856                             let resource = self
857                                 .validator
858                                 .types(0)
859                                 .unwrap()
860                                 .component_any_type_at(resource)
861                                 .unwrap_resource();
862                             let ty = self.core_func_signature(core_func_index)?;
863                             core_func_index += 1;
864                             LocalInitializer::ResourceRep(resource, ty)
865                         }
866                         wasmparser::CanonicalFunction::ThreadSpawnRef { .. }
867                         | wasmparser::CanonicalFunction::ThreadSpawnIndirect { .. }
868                         | wasmparser::CanonicalFunction::ThreadAvailableParallelism => {
869                             bail!("unsupported intrinsic")
870                         }
871                         wasmparser::CanonicalFunction::BackpressureInc => {
872                             let core_type = self.core_func_signature(core_func_index)?;
873                             core_func_index += 1;
874                             LocalInitializer::BackpressureInc { func: core_type }
875                         }
876                         wasmparser::CanonicalFunction::BackpressureDec => {
877                             let core_type = self.core_func_signature(core_func_index)?;
878                             core_func_index += 1;
879                             LocalInitializer::BackpressureDec { func: core_type }
880                         }
881 
882                         wasmparser::CanonicalFunction::TaskReturn { result, options } => {
883                             let result = result.map(|ty| match ty {
884                                 wasmparser::ComponentValType::Primitive(ty) => {
885                                     ComponentValType::Primitive(ty)
886                                 }
887                                 wasmparser::ComponentValType::Type(ty) => ComponentValType::Type(
888                                     self.validator
889                                         .types(0)
890                                         .unwrap()
891                                         .component_defined_type_at(ty),
892                                 ),
893                             });
894                             let options = self.canonical_options(&options, core_func_index)?;
895                             core_func_index += 1;
896                             LocalInitializer::TaskReturn { result, options }
897                         }
898                         wasmparser::CanonicalFunction::TaskCancel => {
899                             let func = self.core_func_signature(core_func_index)?;
900                             core_func_index += 1;
901                             LocalInitializer::TaskCancel { func }
902                         }
903                         wasmparser::CanonicalFunction::WaitableSetNew => {
904                             let func = self.core_func_signature(core_func_index)?;
905                             core_func_index += 1;
906                             LocalInitializer::WaitableSetNew { func }
907                         }
908                         wasmparser::CanonicalFunction::WaitableSetWait {
909                             cancellable,
910                             memory,
911                         } => {
912                             let core_type = self.core_func_signature(core_func_index)?;
913                             core_func_index += 1;
914                             LocalInitializer::WaitableSetWait {
915                                 options: LocalCanonicalOptions {
916                                     core_type,
917                                     cancellable,
918                                     async_: false,
919                                     data_model: LocalDataModel::LinearMemory {
920                                         memory: Some(MemoryIndex::from_u32(memory)),
921                                         realloc: None,
922                                     },
923                                     post_return: None,
924                                     callback: None,
925                                     string_encoding: StringEncoding::Utf8,
926                                 },
927                             }
928                         }
929                         wasmparser::CanonicalFunction::WaitableSetPoll {
930                             cancellable,
931                             memory,
932                         } => {
933                             let core_type = self.core_func_signature(core_func_index)?;
934                             core_func_index += 1;
935                             LocalInitializer::WaitableSetPoll {
936                                 options: LocalCanonicalOptions {
937                                     core_type,
938                                     async_: false,
939                                     cancellable,
940                                     data_model: LocalDataModel::LinearMemory {
941                                         memory: Some(MemoryIndex::from_u32(memory)),
942                                         realloc: None,
943                                     },
944                                     post_return: None,
945                                     callback: None,
946                                     string_encoding: StringEncoding::Utf8,
947                                 },
948                             }
949                         }
950                         wasmparser::CanonicalFunction::WaitableSetDrop => {
951                             let func = self.core_func_signature(core_func_index)?;
952                             core_func_index += 1;
953                             LocalInitializer::WaitableSetDrop { func }
954                         }
955                         wasmparser::CanonicalFunction::WaitableJoin => {
956                             let func = self.core_func_signature(core_func_index)?;
957                             core_func_index += 1;
958                             LocalInitializer::WaitableJoin { func }
959                         }
960                         wasmparser::CanonicalFunction::ThreadYield { cancellable } => {
961                             let func = self.core_func_signature(core_func_index)?;
962                             core_func_index += 1;
963                             LocalInitializer::ThreadYield { func, cancellable }
964                         }
965                         wasmparser::CanonicalFunction::SubtaskDrop => {
966                             let func = self.core_func_signature(core_func_index)?;
967                             core_func_index += 1;
968                             LocalInitializer::SubtaskDrop { func }
969                         }
970                         wasmparser::CanonicalFunction::SubtaskCancel { async_ } => {
971                             let func = self.core_func_signature(core_func_index)?;
972                             core_func_index += 1;
973                             LocalInitializer::SubtaskCancel { func, async_ }
974                         }
975                         wasmparser::CanonicalFunction::StreamNew { ty } => {
976                             let ty = self
977                                 .validator
978                                 .types(0)
979                                 .unwrap()
980                                 .component_defined_type_at(ty);
981                             let func = self.core_func_signature(core_func_index)?;
982                             core_func_index += 1;
983                             LocalInitializer::StreamNew { ty, func }
984                         }
985                         wasmparser::CanonicalFunction::StreamRead { ty, options } => {
986                             let ty = self
987                                 .validator
988                                 .types(0)
989                                 .unwrap()
990                                 .component_defined_type_at(ty);
991                             let options = self.canonical_options(&options, core_func_index)?;
992                             core_func_index += 1;
993                             LocalInitializer::StreamRead { ty, options }
994                         }
995                         wasmparser::CanonicalFunction::StreamWrite { ty, options } => {
996                             let ty = self
997                                 .validator
998                                 .types(0)
999                                 .unwrap()
1000                                 .component_defined_type_at(ty);
1001                             let options = self.canonical_options(&options, core_func_index)?;
1002                             core_func_index += 1;
1003                             LocalInitializer::StreamWrite { ty, options }
1004                         }
1005                         wasmparser::CanonicalFunction::StreamCancelRead { ty, async_ } => {
1006                             let ty = self
1007                                 .validator
1008                                 .types(0)
1009                                 .unwrap()
1010                                 .component_defined_type_at(ty);
1011                             let func = self.core_func_signature(core_func_index)?;
1012                             core_func_index += 1;
1013                             LocalInitializer::StreamCancelRead { ty, func, async_ }
1014                         }
1015                         wasmparser::CanonicalFunction::StreamCancelWrite { ty, async_ } => {
1016                             let ty = self
1017                                 .validator
1018                                 .types(0)
1019                                 .unwrap()
1020                                 .component_defined_type_at(ty);
1021                             let func = self.core_func_signature(core_func_index)?;
1022                             core_func_index += 1;
1023                             LocalInitializer::StreamCancelWrite { ty, func, async_ }
1024                         }
1025                         wasmparser::CanonicalFunction::StreamDropReadable { ty } => {
1026                             let ty = self
1027                                 .validator
1028                                 .types(0)
1029                                 .unwrap()
1030                                 .component_defined_type_at(ty);
1031                             let func = self.core_func_signature(core_func_index)?;
1032                             core_func_index += 1;
1033                             LocalInitializer::StreamDropReadable { ty, func }
1034                         }
1035                         wasmparser::CanonicalFunction::StreamDropWritable { ty } => {
1036                             let ty = self
1037                                 .validator
1038                                 .types(0)
1039                                 .unwrap()
1040                                 .component_defined_type_at(ty);
1041                             let func = self.core_func_signature(core_func_index)?;
1042                             core_func_index += 1;
1043                             LocalInitializer::StreamDropWritable { ty, func }
1044                         }
1045                         wasmparser::CanonicalFunction::FutureNew { ty } => {
1046                             let ty = self
1047                                 .validator
1048                                 .types(0)
1049                                 .unwrap()
1050                                 .component_defined_type_at(ty);
1051                             let func = self.core_func_signature(core_func_index)?;
1052                             core_func_index += 1;
1053                             LocalInitializer::FutureNew { ty, func }
1054                         }
1055                         wasmparser::CanonicalFunction::FutureRead { ty, options } => {
1056                             let ty = self
1057                                 .validator
1058                                 .types(0)
1059                                 .unwrap()
1060                                 .component_defined_type_at(ty);
1061                             let options = self.canonical_options(&options, core_func_index)?;
1062                             core_func_index += 1;
1063                             LocalInitializer::FutureRead { ty, options }
1064                         }
1065                         wasmparser::CanonicalFunction::FutureWrite { ty, options } => {
1066                             let ty = self
1067                                 .validator
1068                                 .types(0)
1069                                 .unwrap()
1070                                 .component_defined_type_at(ty);
1071                             let options = self.canonical_options(&options, core_func_index)?;
1072                             core_func_index += 1;
1073                             LocalInitializer::FutureWrite { ty, options }
1074                         }
1075                         wasmparser::CanonicalFunction::FutureCancelRead { ty, async_ } => {
1076                             let ty = self
1077                                 .validator
1078                                 .types(0)
1079                                 .unwrap()
1080                                 .component_defined_type_at(ty);
1081                             let func = self.core_func_signature(core_func_index)?;
1082                             core_func_index += 1;
1083                             LocalInitializer::FutureCancelRead { ty, func, async_ }
1084                         }
1085                         wasmparser::CanonicalFunction::FutureCancelWrite { ty, async_ } => {
1086                             let ty = self
1087                                 .validator
1088                                 .types(0)
1089                                 .unwrap()
1090                                 .component_defined_type_at(ty);
1091                             let func = self.core_func_signature(core_func_index)?;
1092                             core_func_index += 1;
1093                             LocalInitializer::FutureCancelWrite { ty, func, async_ }
1094                         }
1095                         wasmparser::CanonicalFunction::FutureDropReadable { ty } => {
1096                             let ty = self
1097                                 .validator
1098                                 .types(0)
1099                                 .unwrap()
1100                                 .component_defined_type_at(ty);
1101                             let func = self.core_func_signature(core_func_index)?;
1102                             core_func_index += 1;
1103                             LocalInitializer::FutureDropReadable { ty, func }
1104                         }
1105                         wasmparser::CanonicalFunction::FutureDropWritable { ty } => {
1106                             let ty = self
1107                                 .validator
1108                                 .types(0)
1109                                 .unwrap()
1110                                 .component_defined_type_at(ty);
1111                             let func = self.core_func_signature(core_func_index)?;
1112                             core_func_index += 1;
1113                             LocalInitializer::FutureDropWritable { ty, func }
1114                         }
1115                         wasmparser::CanonicalFunction::ErrorContextNew { options } => {
1116                             let options = self.canonical_options(&options, core_func_index)?;
1117                             core_func_index += 1;
1118                             LocalInitializer::ErrorContextNew { options }
1119                         }
1120                         wasmparser::CanonicalFunction::ErrorContextDebugMessage { options } => {
1121                             let options = self.canonical_options(&options, core_func_index)?;
1122                             core_func_index += 1;
1123                             LocalInitializer::ErrorContextDebugMessage { options }
1124                         }
1125                         wasmparser::CanonicalFunction::ErrorContextDrop => {
1126                             let func = self.core_func_signature(core_func_index)?;
1127                             core_func_index += 1;
1128                             LocalInitializer::ErrorContextDrop { func }
1129                         }
1130                         wasmparser::CanonicalFunction::ContextGet(i) => {
1131                             let func = self.core_func_signature(core_func_index)?;
1132                             core_func_index += 1;
1133                             LocalInitializer::ContextGet { i, func }
1134                         }
1135                         wasmparser::CanonicalFunction::ContextSet(i) => {
1136                             let func = self.core_func_signature(core_func_index)?;
1137                             core_func_index += 1;
1138                             LocalInitializer::ContextSet { i, func }
1139                         }
1140                         wasmparser::CanonicalFunction::ThreadIndex => {
1141                             let func = self.core_func_signature(core_func_index)?;
1142                             core_func_index += 1;
1143                             LocalInitializer::ThreadIndex { func }
1144                         }
1145                         wasmparser::CanonicalFunction::ThreadNewIndirect {
1146                             func_ty_index,
1147                             table_index,
1148                         } => {
1149                             let func = self.core_func_signature(core_func_index)?;
1150                             core_func_index += 1;
1151                             LocalInitializer::ThreadNewIndirect {
1152                                 func,
1153                                 start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
1154                                 start_func_table_index: TableIndex::from_u32(table_index),
1155                             }
1156                         }
1157                         wasmparser::CanonicalFunction::ThreadSuspendToSuspended { cancellable } => {
1158                             let func = self.core_func_signature(core_func_index)?;
1159                             core_func_index += 1;
1160                             LocalInitializer::ThreadSuspendToSuspended { func, cancellable }
1161                         }
1162                         wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
1163                             let func = self.core_func_signature(core_func_index)?;
1164                             core_func_index += 1;
1165                             LocalInitializer::ThreadSuspend { func, cancellable }
1166                         }
1167                         wasmparser::CanonicalFunction::ThreadSuspendTo { cancellable } => {
1168                             let func = self.core_func_signature(core_func_index)?;
1169                             core_func_index += 1;
1170                             LocalInitializer::ThreadSuspendTo { func, cancellable }
1171                         }
1172                         wasmparser::CanonicalFunction::ThreadUnsuspend => {
1173                             let func = self.core_func_signature(core_func_index)?;
1174                             core_func_index += 1;
1175                             LocalInitializer::ThreadUnsuspend { func }
1176                         }
1177                         wasmparser::CanonicalFunction::ThreadYieldToSuspended { cancellable } => {
1178                             let func = self.core_func_signature(core_func_index)?;
1179                             core_func_index += 1;
1180                             LocalInitializer::ThreadYieldToSuspended { func, cancellable }
1181                         }
1182                     };
1183                     self.result.initializers.push(init);
1184                 }
1185             }
1186 
1187             // Core wasm modules are translated inline directly here with the
1188             // `ModuleEnvironment` from core wasm compilation. This will return
1189             // to the caller the size of the module so it knows how many bytes
1190             // of the input are skipped.
1191             //
1192             // Note that this is just initial type translation of the core wasm
1193             // module and actual function compilation is deferred until this
1194             // entire process has completed.
1195             Payload::ModuleSection {
1196                 parser,
1197                 unchecked_range,
1198             } => {
1199                 let index = self.validator.types(0).unwrap().module_count();
1200                 self.validator.module_section(&unchecked_range)?;
1201                 let static_module_index = self.static_modules.next_key();
1202                 let mut translation = ModuleEnvironment::new(
1203                     self.tunables,
1204                     self.validator,
1205                     self.types.module_types_builder(),
1206                     static_module_index,
1207                 )
1208                 .translate(
1209                     parser,
1210                     component
1211                         .get(unchecked_range.start..unchecked_range.end)
1212                         .ok_or_else(|| {
1213                             format_err!(
1214                                 "section range {}..{} is out of bounds (bound = {})",
1215                                 unchecked_range.start,
1216                                 unchecked_range.end,
1217                                 component.len()
1218                             )
1219                             .context("wasm component contains an invalid module section")
1220                         })?,
1221                 )?;
1222 
1223                 translation.wasm_module_offset = u64::try_from(unchecked_range.start).unwrap();
1224                 let static_module_index2 = self.static_modules.push(translation);
1225                 assert_eq!(static_module_index, static_module_index2);
1226                 let types = self.validator.types(0).unwrap();
1227                 let ty = types.module_at(index);
1228                 self.result
1229                     .initializers
1230                     .push(LocalInitializer::ModuleStatic(static_module_index, ty));
1231                 return Ok(Action::Skip(unchecked_range.end - unchecked_range.start));
1232             }
1233 
1234             // When a sub-component is found then the current translation state
1235             // is pushed onto the `lexical_scopes` stack. This will subsequently
1236             // get popped as part of `Payload::End` processing above.
1237             //
1238             // Note that the set of closure args for this new lexical scope
1239             // starts empty since it will only get populated if translation of
1240             // the nested component ends up aliasing some outer module or
1241             // component.
1242             Payload::ComponentSection {
1243                 parser,
1244                 unchecked_range,
1245             } => {
1246                 self.validator.component_section(&unchecked_range)?;
1247                 self.lexical_scopes.push(LexicalScope {
1248                     parser: mem::replace(&mut self.parser, parser),
1249                     translation: mem::take(&mut self.result),
1250                     closure_args: ClosedOverVars::default(),
1251                 });
1252             }
1253 
1254             // Both core wasm instances and component instances record
1255             // initializers of what form of instantiation is performed which
1256             // largely just records the arguments given from wasmparser into a
1257             // `HashMap` for processing later during inlining.
1258             Payload::InstanceSection(s) => {
1259                 self.validator.instance_section(&s)?;
1260                 for instance in s {
1261                     let init = match instance? {
1262                         wasmparser::Instance::Instantiate { module_index, args } => {
1263                             let index = ModuleIndex::from_u32(module_index);
1264                             self.instantiate_module(index, &args)
1265                         }
1266                         wasmparser::Instance::FromExports(exports) => {
1267                             self.instantiate_module_from_exports(&exports)
1268                         }
1269                     };
1270                     self.result.initializers.push(init);
1271                 }
1272             }
1273             Payload::ComponentInstanceSection(s) => {
1274                 let mut index = self.validator.types(0).unwrap().component_instance_count();
1275                 self.validator.component_instance_section(&s)?;
1276                 for instance in s {
1277                     let types = self.validator.types(0).unwrap();
1278                     let ty = types.component_instance_at(index);
1279                     let init = match instance? {
1280                         wasmparser::ComponentInstance::Instantiate {
1281                             component_index,
1282                             args,
1283                         } => {
1284                             let index = ComponentIndex::from_u32(component_index);
1285                             self.instantiate_component(index, &args, ty)?
1286                         }
1287                         wasmparser::ComponentInstance::FromExports(exports) => {
1288                             self.instantiate_component_from_exports(&exports, ty)?
1289                         }
1290                     };
1291                     self.result.initializers.push(init);
1292                     index += 1;
1293                 }
1294             }
1295 
1296             // Exports don't actually fill out the `initializers` array but
1297             // instead fill out the one other field in a `Translation`, the
1298             // `exports` field (as one might imagine). This for now simply
1299             // records the index of what's exported and that's tracked further
1300             // later during inlining.
1301             Payload::ComponentExportSection(s) => {
1302                 self.validator.component_export_section(&s)?;
1303                 for export in s {
1304                     let export = export?;
1305                     let item = self.kind_to_item(export.kind, export.index)?;
1306                     let prev = self.result.exports.insert(export.name.0, item);
1307                     assert!(prev.is_none());
1308                     self.result
1309                         .initializers
1310                         .push(LocalInitializer::Export(item));
1311                 }
1312             }
1313 
1314             Payload::ComponentStartSection { start, range } => {
1315                 self.validator.component_start_section(&start, &range)?;
1316                 unimplemented!("component start section");
1317             }
1318 
1319             // Aliases of instance exports (either core or component) will be
1320             // recorded as an initializer of the appropriate type with outer
1321             // aliases handled specially via upvars and type processing.
1322             Payload::ComponentAliasSection(s) => {
1323                 self.validator.component_alias_section(&s)?;
1324                 for alias in s {
1325                     let init = match alias? {
1326                         wasmparser::ComponentAlias::InstanceExport {
1327                             kind: _,
1328                             instance_index,
1329                             name,
1330                         } => {
1331                             let instance = ComponentInstanceIndex::from_u32(instance_index);
1332                             LocalInitializer::AliasComponentExport(instance, name)
1333                         }
1334                         wasmparser::ComponentAlias::Outer { kind, count, index } => {
1335                             self.alias_component_outer(kind, count, index);
1336                             continue;
1337                         }
1338                         wasmparser::ComponentAlias::CoreInstanceExport {
1339                             kind,
1340                             instance_index,
1341                             name,
1342                         } => {
1343                             let instance = ModuleInstanceIndex::from_u32(instance_index);
1344                             self.alias_module_instance_export(kind, instance, name)
1345                         }
1346                     };
1347                     self.result.initializers.push(init);
1348                 }
1349             }
1350 
1351             // All custom sections are ignored by Wasmtime at this time.
1352             //
1353             // FIXME(WebAssembly/component-model#14): probably want to specify
1354             // and parse a `name` section here.
1355             Payload::CustomSection { .. } => {}
1356 
1357             // Anything else is either not reachable since we never enable the
1358             // feature in Wasmtime or we do enable it and it's a bug we don't
1359             // implement it, so let validation take care of most errors here and
1360             // if it gets past validation provide a helpful error message to
1361             // debug.
1362             other => {
1363                 self.validator.payload(&other)?;
1364                 panic!("unimplemented section {other:?}");
1365             }
1366         }
1367 
1368         Ok(Action::KeepGoing)
1369     }
1370 
instantiate_module( &mut self, module: ModuleIndex, raw_args: &[wasmparser::InstantiationArg<'data>], ) -> LocalInitializer<'data>1371     fn instantiate_module(
1372         &mut self,
1373         module: ModuleIndex,
1374         raw_args: &[wasmparser::InstantiationArg<'data>],
1375     ) -> LocalInitializer<'data> {
1376         let mut args = HashMap::with_capacity(raw_args.len());
1377         for arg in raw_args {
1378             match arg.kind {
1379                 wasmparser::InstantiationArgKind::Instance => {
1380                     let idx = ModuleInstanceIndex::from_u32(arg.index);
1381                     args.insert(arg.name, idx);
1382                 }
1383             }
1384         }
1385         LocalInitializer::ModuleInstantiate(module, args)
1386     }
1387 
1388     /// Creates a synthetic module from the list of items currently in the
1389     /// module and their given names.
instantiate_module_from_exports( &mut self, exports: &[wasmparser::Export<'data>], ) -> LocalInitializer<'data>1390     fn instantiate_module_from_exports(
1391         &mut self,
1392         exports: &[wasmparser::Export<'data>],
1393     ) -> LocalInitializer<'data> {
1394         let mut map = HashMap::with_capacity(exports.len());
1395         for export in exports {
1396             let idx = match export.kind {
1397                 wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1398                     let index = FuncIndex::from_u32(export.index);
1399                     EntityIndex::Function(index)
1400                 }
1401                 wasmparser::ExternalKind::Table => {
1402                     let index = TableIndex::from_u32(export.index);
1403                     EntityIndex::Table(index)
1404                 }
1405                 wasmparser::ExternalKind::Memory => {
1406                     let index = MemoryIndex::from_u32(export.index);
1407                     EntityIndex::Memory(index)
1408                 }
1409                 wasmparser::ExternalKind::Global => {
1410                     let index = GlobalIndex::from_u32(export.index);
1411                     EntityIndex::Global(index)
1412                 }
1413                 wasmparser::ExternalKind::Tag => {
1414                     let index = TagIndex::from_u32(export.index);
1415                     EntityIndex::Tag(index)
1416                 }
1417             };
1418             map.insert(export.name, idx);
1419         }
1420         LocalInitializer::ModuleSynthetic(map)
1421     }
1422 
instantiate_component( &mut self, component: ComponentIndex, raw_args: &[wasmparser::ComponentInstantiationArg<'data>], ty: ComponentInstanceTypeId, ) -> Result<LocalInitializer<'data>>1423     fn instantiate_component(
1424         &mut self,
1425         component: ComponentIndex,
1426         raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
1427         ty: ComponentInstanceTypeId,
1428     ) -> Result<LocalInitializer<'data>> {
1429         let mut args = HashMap::with_capacity(raw_args.len());
1430         for arg in raw_args {
1431             let idx = self.kind_to_item(arg.kind, arg.index)?;
1432             args.insert(arg.name, idx);
1433         }
1434 
1435         Ok(LocalInitializer::ComponentInstantiate(component, args, ty))
1436     }
1437 
1438     /// Creates a synthetic module from the list of items currently in the
1439     /// module and their given names.
instantiate_component_from_exports( &mut self, exports: &[wasmparser::ComponentExport<'data>], ty: ComponentInstanceTypeId, ) -> Result<LocalInitializer<'data>>1440     fn instantiate_component_from_exports(
1441         &mut self,
1442         exports: &[wasmparser::ComponentExport<'data>],
1443         ty: ComponentInstanceTypeId,
1444     ) -> Result<LocalInitializer<'data>> {
1445         let mut map = HashMap::with_capacity(exports.len());
1446         for export in exports {
1447             let idx = self.kind_to_item(export.kind, export.index)?;
1448             map.insert(export.name.0, idx);
1449         }
1450 
1451         Ok(LocalInitializer::ComponentSynthetic(map, ty))
1452     }
1453 
kind_to_item( &mut self, kind: wasmparser::ComponentExternalKind, index: u32, ) -> Result<ComponentItem>1454     fn kind_to_item(
1455         &mut self,
1456         kind: wasmparser::ComponentExternalKind,
1457         index: u32,
1458     ) -> Result<ComponentItem> {
1459         Ok(match kind {
1460             wasmparser::ComponentExternalKind::Func => {
1461                 let index = ComponentFuncIndex::from_u32(index);
1462                 ComponentItem::Func(index)
1463             }
1464             wasmparser::ComponentExternalKind::Module => {
1465                 let index = ModuleIndex::from_u32(index);
1466                 ComponentItem::Module(index)
1467             }
1468             wasmparser::ComponentExternalKind::Instance => {
1469                 let index = ComponentInstanceIndex::from_u32(index);
1470                 ComponentItem::ComponentInstance(index)
1471             }
1472             wasmparser::ComponentExternalKind::Component => {
1473                 let index = ComponentIndex::from_u32(index);
1474                 ComponentItem::Component(index)
1475             }
1476             wasmparser::ComponentExternalKind::Value => {
1477                 unimplemented!("component values");
1478             }
1479             wasmparser::ComponentExternalKind::Type => {
1480                 let types = self.validator.types(0).unwrap();
1481                 let ty = types.component_any_type_at(index);
1482                 ComponentItem::Type(ty)
1483             }
1484         })
1485     }
1486 
alias_module_instance_export( &mut self, kind: wasmparser::ExternalKind, instance: ModuleInstanceIndex, name: &'data str, ) -> LocalInitializer<'data>1487     fn alias_module_instance_export(
1488         &mut self,
1489         kind: wasmparser::ExternalKind,
1490         instance: ModuleInstanceIndex,
1491         name: &'data str,
1492     ) -> LocalInitializer<'data> {
1493         match kind {
1494             wasmparser::ExternalKind::Func | wasmparser::ExternalKind::FuncExact => {
1495                 LocalInitializer::AliasExportFunc(instance, name)
1496             }
1497             wasmparser::ExternalKind::Memory => LocalInitializer::AliasExportMemory(instance, name),
1498             wasmparser::ExternalKind::Table => LocalInitializer::AliasExportTable(instance, name),
1499             wasmparser::ExternalKind::Global => LocalInitializer::AliasExportGlobal(instance, name),
1500             wasmparser::ExternalKind::Tag => LocalInitializer::AliasExportTag(instance, name),
1501         }
1502     }
1503 
alias_component_outer( &mut self, kind: wasmparser::ComponentOuterAliasKind, count: u32, index: u32, )1504     fn alias_component_outer(
1505         &mut self,
1506         kind: wasmparser::ComponentOuterAliasKind,
1507         count: u32,
1508         index: u32,
1509     ) {
1510         match kind {
1511             wasmparser::ComponentOuterAliasKind::CoreType
1512             | wasmparser::ComponentOuterAliasKind::Type => {}
1513 
1514             // For more information about the implementation of outer aliases
1515             // see the documentation of `LexicalScope`. Otherwise though the
1516             // main idea here is that the data to close over starts as `Local`
1517             // and then transitions to `Upvar` as its inserted into the parents
1518             // in order from target we're aliasing back to the current
1519             // component.
1520             wasmparser::ComponentOuterAliasKind::CoreModule => {
1521                 let index = ModuleIndex::from_u32(index);
1522                 let mut module = ClosedOverModule::Local(index);
1523                 let depth = self.lexical_scopes.len() - (count as usize);
1524                 for frame in self.lexical_scopes[depth..].iter_mut() {
1525                     module = ClosedOverModule::Upvar(frame.closure_args.modules.push(module));
1526                 }
1527 
1528                 // If the `module` is still `Local` then the `depth` was 0 and
1529                 // it's an alias into our own space. Otherwise it's switched to
1530                 // an upvar and will index into the upvar space. Either way
1531                 // it's just plumbed directly into the initializer.
1532                 self.result
1533                     .initializers
1534                     .push(LocalInitializer::AliasModule(module));
1535             }
1536             wasmparser::ComponentOuterAliasKind::Component => {
1537                 let index = ComponentIndex::from_u32(index);
1538                 let mut component = ClosedOverComponent::Local(index);
1539                 let depth = self.lexical_scopes.len() - (count as usize);
1540                 for frame in self.lexical_scopes[depth..].iter_mut() {
1541                     component =
1542                         ClosedOverComponent::Upvar(frame.closure_args.components.push(component));
1543                 }
1544 
1545                 self.result
1546                     .initializers
1547                     .push(LocalInitializer::AliasComponent(component));
1548             }
1549         }
1550     }
1551 
canonical_options( &mut self, opts: &[wasmparser::CanonicalOption], core_func_index: u32, ) -> WasmResult<LocalCanonicalOptions>1552     fn canonical_options(
1553         &mut self,
1554         opts: &[wasmparser::CanonicalOption],
1555         core_func_index: u32,
1556     ) -> WasmResult<LocalCanonicalOptions> {
1557         let core_type = self.core_func_signature(core_func_index)?;
1558 
1559         let mut string_encoding = StringEncoding::Utf8;
1560         let mut post_return = None;
1561         let mut async_ = false;
1562         let mut callback = None;
1563         let mut memory = None;
1564         let mut realloc = None;
1565         let mut gc = false;
1566 
1567         for opt in opts {
1568             match opt {
1569                 wasmparser::CanonicalOption::UTF8 => {
1570                     string_encoding = StringEncoding::Utf8;
1571                 }
1572                 wasmparser::CanonicalOption::UTF16 => {
1573                     string_encoding = StringEncoding::Utf16;
1574                 }
1575                 wasmparser::CanonicalOption::CompactUTF16 => {
1576                     string_encoding = StringEncoding::CompactUtf16;
1577                 }
1578                 wasmparser::CanonicalOption::Memory(idx) => {
1579                     let idx = MemoryIndex::from_u32(*idx);
1580                     memory = Some(idx);
1581                 }
1582                 wasmparser::CanonicalOption::Realloc(idx) => {
1583                     let idx = FuncIndex::from_u32(*idx);
1584                     realloc = Some(idx);
1585                 }
1586                 wasmparser::CanonicalOption::PostReturn(idx) => {
1587                     let idx = FuncIndex::from_u32(*idx);
1588                     post_return = Some(idx);
1589                 }
1590                 wasmparser::CanonicalOption::Async => async_ = true,
1591                 wasmparser::CanonicalOption::Callback(idx) => {
1592                     let idx = FuncIndex::from_u32(*idx);
1593                     callback = Some(idx);
1594                 }
1595                 wasmparser::CanonicalOption::CoreType(idx) => {
1596                     if cfg!(debug_assertions) {
1597                         let types = self.validator.types(0).unwrap();
1598                         let core_ty_id = types.core_type_at_in_component(*idx).unwrap_sub();
1599                         let interned = self
1600                             .types
1601                             .module_types_builder()
1602                             .intern_type(types, core_ty_id)?;
1603                         debug_assert_eq!(interned, core_type);
1604                     }
1605                 }
1606                 wasmparser::CanonicalOption::Gc => {
1607                     gc = true;
1608                 }
1609             }
1610         }
1611 
1612         Ok(LocalCanonicalOptions {
1613             string_encoding,
1614             post_return,
1615             cancellable: false,
1616             async_,
1617             callback,
1618             core_type,
1619             data_model: if gc {
1620                 LocalDataModel::Gc {}
1621             } else {
1622                 LocalDataModel::LinearMemory { memory, realloc }
1623             },
1624         })
1625     }
1626 
1627     /// Get the interned type index for the `index`th core function.
core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex>1628     fn core_func_signature(&mut self, index: u32) -> WasmResult<ModuleInternedTypeIndex> {
1629         let types = self.validator.types(0).unwrap();
1630         let id = types.core_function_at(index);
1631         self.types.module_types_builder().intern_type(types, id)
1632     }
1633 
is_unsafe_intrinsics_import(&self, import: &str) -> bool1634     fn is_unsafe_intrinsics_import(&self, import: &str) -> bool {
1635         self.lexical_scopes.is_empty()
1636             && self
1637                 .unsafe_intrinsics_import
1638                 .is_some_and(|name| import == name)
1639     }
1640 
check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()>1641     fn check_unsafe_intrinsics_import(&self, import: &str, ty: ComponentEntityType) -> Result<()> {
1642         let types = &self.validator.types(0).unwrap();
1643 
1644         let ComponentEntityType::Instance(instance_ty) = ty else {
1645             bail!("bad unsafe intrinsics import: import `{import}` must be an instance import")
1646         };
1647         let instance_ty = &types[instance_ty];
1648 
1649         ensure!(
1650             instance_ty.defined_resources.is_empty(),
1651             "bad unsafe intrinsics import: import `{import}` cannot define any resources"
1652         );
1653         ensure!(
1654             instance_ty.explicit_resources.is_empty(),
1655             "bad unsafe intrinsics import: import `{import}` cannot export any resources"
1656         );
1657 
1658         for (name, ty) in &instance_ty.exports {
1659             let ComponentEntityType::Func(func_ty) = ty else {
1660                 bail!(
1661                     "bad unsafe intrinsics import: imported instance `{import}` must \
1662                      only export functions"
1663                 )
1664             };
1665             let func_ty = &types[*func_ty];
1666 
1667             fn ty_eq(a: &InterfaceType, b: &wasmparser::component_types::ComponentValType) -> bool {
1668                 use wasmparser::{PrimitiveValType as P, component_types::ComponentValType as C};
1669                 match (a, b) {
1670                     (InterfaceType::U8, C::Primitive(P::U8)) => true,
1671                     (InterfaceType::U8, _) => false,
1672 
1673                     (InterfaceType::U16, C::Primitive(P::U16)) => true,
1674                     (InterfaceType::U16, _) => false,
1675 
1676                     (InterfaceType::U32, C::Primitive(P::U32)) => true,
1677                     (InterfaceType::U32, _) => false,
1678 
1679                     (InterfaceType::U64, C::Primitive(P::U64)) => true,
1680                     (InterfaceType::U64, _) => false,
1681 
1682                     (ty, _) => unreachable!("no unsafe intrinsics use {ty:?}"),
1683                 }
1684             }
1685 
1686             fn check_types<'a>(
1687                 expected: impl ExactSizeIterator<Item = &'a InterfaceType>,
1688                 actual: impl ExactSizeIterator<Item = &'a wasmparser::component_types::ComponentValType>,
1689                 kind: &str,
1690                 import: &str,
1691                 name: &str,
1692             ) -> Result<()> {
1693                 let expected_len = expected.len();
1694                 let actual_len = actual.len();
1695                 ensure!(
1696                     expected_len == actual_len,
1697                     "bad unsafe intrinsics import at `{import}`: function `{name}` must have \
1698                      {expected_len} {kind}, found {actual_len}"
1699                 );
1700 
1701                 for (i, (actual_ty, expected_ty)) in actual.zip(expected).enumerate() {
1702                     ensure!(
1703                         ty_eq(expected_ty, actual_ty),
1704                         "bad unsafe intrinsics import at `{import}`: {kind}[{i}] for function \
1705                          `{name}` must be `{expected_ty:?}`, found `{actual_ty:?}`"
1706                     );
1707                 }
1708                 Ok(())
1709             }
1710 
1711             let intrinsic = UnsafeIntrinsic::from_str(name)
1712                 .with_context(|| format!("bad unsafe intrinsics import at `{import}`"))?;
1713 
1714             check_types(
1715                 intrinsic.component_params().iter(),
1716                 func_ty.params.iter().map(|(_name, ty)| ty),
1717                 "parameters",
1718                 &import,
1719                 &name,
1720             )?;
1721             check_types(
1722                 intrinsic.component_results().iter(),
1723                 func_ty.result.iter(),
1724                 "results",
1725                 &import,
1726                 &name,
1727             )?;
1728         }
1729 
1730         Ok(())
1731     }
1732 }
1733 
1734 impl Translation<'_> {
types_ref(&self) -> wasmparser::types::TypesRef<'_>1735     fn types_ref(&self) -> wasmparser::types::TypesRef<'_> {
1736         self.types.as_ref().unwrap().as_ref()
1737     }
1738 }
1739 
1740 /// A small helper module which wraps a `ComponentTypesBuilder` and attempts
1741 /// to disallow access to mutable access to the builder before the inlining
1742 /// pass.
1743 ///
1744 /// Type information in this translation pass must be preserved at the
1745 /// wasmparser layer of abstraction rather than being lowered into Wasmtime's
1746 /// own type system. Only during inlining are types fully assigned because
1747 /// that's when resource types become available as it's known which instance
1748 /// defines which resource, or more concretely the same component instantiated
1749 /// twice will produce two unique resource types unlike one as seen by
1750 /// wasmparser within the component.
1751 mod pre_inlining {
1752     use super::*;
1753 
1754     pub struct PreInliningComponentTypes<'a> {
1755         types: &'a mut ComponentTypesBuilder,
1756     }
1757 
1758     impl<'a> PreInliningComponentTypes<'a> {
new(types: &'a mut ComponentTypesBuilder) -> Self1759         pub fn new(types: &'a mut ComponentTypesBuilder) -> Self {
1760             Self { types }
1761         }
1762 
module_types_builder(&mut self) -> &mut ModuleTypesBuilder1763         pub fn module_types_builder(&mut self) -> &mut ModuleTypesBuilder {
1764             self.types.module_types_builder_mut()
1765         }
1766 
types(&self) -> &ComponentTypesBuilder1767         pub fn types(&self) -> &ComponentTypesBuilder {
1768             self.types
1769         }
1770 
1771         // NB: this should in theory only be used for the `inline` phase of
1772         // translation.
types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder1773         pub fn types_mut_for_inlining(&mut self) -> &mut ComponentTypesBuilder {
1774             self.types
1775         }
1776     }
1777 
1778     impl TypeConvert for PreInliningComponentTypes<'_> {
lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType1779         fn lookup_heap_type(&self, index: wasmparser::UnpackedIndex) -> WasmHeapType {
1780             self.types.lookup_heap_type(index)
1781         }
1782 
lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex1783         fn lookup_type_index(&self, index: wasmparser::UnpackedIndex) -> EngineOrModuleTypeIndex {
1784             self.types.lookup_type_index(index)
1785         }
1786     }
1787 }
1788 use pre_inlining::PreInliningComponentTypes;
1789