Skip to main content

wit_component/
encoding.rs

1//! Support for encoding a core wasm module into a component.
2//!
3//! This module, at a high level, is tasked with transforming a core wasm
4//! module into a component. This will process the imports/exports of the core
5//! wasm module and translate between the `wit-parser` AST and the component
6//! model binary format, producing a final component which will import
7//! `*.wit` defined interfaces and export `*.wit` defined interfaces as well
8//! with everything wired up internally according to the canonical ABI and such.
9//!
10//! This doc block here is not currently 100% complete and doesn't cover the
11//! full functionality of this module.
12//!
13//! # Adapter Modules
14//!
15//! One feature of this encoding process which is non-obvious is the support for
16//! "adapter modules". The general idea here is that historical host API
17//! definitions have been around for quite some time, such as
18//! `wasi_snapshot_preview1`, but these host API definitions are not compatible
19//! with the canonical ABI or component model exactly. These APIs, however, can
20//! in most situations be roughly adapted to component-model equivalents. This
21//! is where adapter modules come into play, they're converting from some
22//! arbitrary API/ABI into a component-model using API.
23//!
24//! An adapter module is a separately compiled `*.wasm` blob which will export
25//! functions matching the desired ABI (e.g. exporting functions matching the
26//! `wasi_snapshot_preview1` ABI). The `*.wasm` blob will then import functions
27//! in the canonical ABI and internally adapt the exported functions to the
28//! imported functions. The encoding support in this module is what wires
29//! everything up and makes sure that everything is imported and exported to the
30//! right place. Adapter modules currently always use "indirect lowerings"
31//! meaning that a shim module is created and provided as the imports to the
32//! main core wasm module, and the shim module is "filled in" at a later time
33//! during the instantiation process.
34//!
35//! Adapter modules are not intended to be general purpose and are currently
36//! very restrictive, namely:
37//!
38//! * They must import a linear memory and not define their own linear memory
39//!   otherwise. In other words they import memory and cannot use multi-memory.
40//! * They cannot define any `elem` or `data` segments since otherwise there's
41//!   no knowledge ahead-of-time of where their data or element segments could
42//!   go. This means things like no panics, no indirect calls, etc.
43//! * If the adapter uses a shadow stack, the global that points to it must be a
44//!   mutable `i32` named `__stack_pointer`. This stack is automatically
45//!   allocated with an injected `allocate_stack` function that will either use
46//!   the main module's `cabi_realloc` export (if present) or `memory.grow`. It
47//!   allocates only 64KB of stack space, and there is no protection if that
48//!   overflows.
49//! * If the adapter has a global, mutable `i32` named `allocation_state`, it
50//!   will be used to keep track of stack allocation status and avoid infinite
51//!   recursion if the main module's `cabi_realloc` function calls back into the
52//!   adapter.  `allocate_stack` will check this global on entry; if it is zero,
53//!   it will set it to one, then allocate the stack, and finally set it to two.
54//!   If it is non-zero, `allocate_stack` will do nothing and return immediately
55//!   (because either the stack has already been allocated or is in the process
56//!   of being allocated).  If the adapter does not have an `allocation_state`,
57//!   `allocate_stack` will use `memory.grow` to allocate the stack; it will
58//!   _not_ use the main module's `cabi_realloc` even if it's available.
59//! * If the adapter imports a `cabi_realloc` function, and the main module
60//!   exports one, they'll be linked together via an alias. If the adapter
61//!   imports such a function but the main module does _not_ export one, we'll
62//!   synthesize one based on `memory.grow` (which will trap for any size other
63//!   than 64KB). Note that the main module's `cabi_realloc` function may call
64//!   back into the adapter before the shadow stack has been allocated. In this
65//!   case (when `allocation_state` is zero or one), the adapter should return
66//!   whatever dummy value(s) it can immediately without touching the stack.
67//!
68//! This means that adapter modules are not meant to be written by everyone.
69//! It's assumed that these will be relatively few and far between yet still a
70//! crucial part of the transition process from to the component model since
71//! otherwise there's no way to run a `wasi_snapshot_preview1` module within the
72//! component model.
73
74use crate::StringEncoding;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77    Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo, PayloadType,
78};
79use anyhow::{Context, Result, anyhow, bail};
80use indexmap::{IndexMap, IndexSet};
81use std::borrow::Cow;
82use std::collections::HashMap;
83use std::hash::Hash;
84use std::mem;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88    Function, FunctionKind, InterfaceId, LiveTypes, Param, Resolve, Stability, Type, TypeDefKind,
89    TypeId, TypeOwner, WorldItem, WorldKey,
90    abi::{AbiVariant, WasmSignature, WasmType},
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, TypeEncodingMaps, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103mod dedupe;
104pub(crate) use dedupe::ModuleImportMap;
105use wasm_metadata::AddMetadataField;
106
107fn to_val_type(ty: &WasmType) -> ValType {
108    match ty {
109        WasmType::I32 => ValType::I32,
110        WasmType::I64 => ValType::I64,
111        WasmType::F32 => ValType::F32,
112        WasmType::F64 => ValType::F64,
113        WasmType::Pointer => ValType::I32,
114        WasmType::PointerOrI64 => ValType::I64,
115        WasmType::Length => ValType::I32,
116    }
117}
118
119fn import_func_name(f: &Function) -> String {
120    match f.kind {
121        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
122            format!("import-func-{}", f.item_name())
123        }
124
125        // transform `[method]foo.bar` into `import-method-foo-bar` to
126        // have it be a valid kebab-name which can't conflict with
127        // anything else.
128        //
129        // There's probably a better and more "formal" way to do this
130        // but quick-and-dirty string manipulation should work well
131        // enough for now hopefully.
132        FunctionKind::Method(_)
133        | FunctionKind::AsyncMethod(_)
134        | FunctionKind::Static(_)
135        | FunctionKind::AsyncStatic(_)
136        | FunctionKind::Constructor(_) => {
137            format!(
138                "import-{}",
139                f.name.replace('[', "").replace([']', '.', ' '], "-")
140            )
141        }
142    }
143}
144
145bitflags::bitflags! {
146    /// Options in the `canon lower` or `canon lift` required for a particular
147    /// function.
148    #[derive(Copy, Clone, Debug)]
149    pub struct RequiredOptions: u8 {
150        /// A memory must be specified, typically the "main module"'s memory
151        /// export.
152        const MEMORY = 1 << 0;
153        /// A `realloc` function must be specified, typically named
154        /// `cabi_realloc`.
155        const REALLOC = 1 << 1;
156        /// A string encoding must be specified, which is always utf-8 for now
157        /// today.
158        const STRING_ENCODING = 1 << 2;
159        const ASYNC = 1 << 3;
160    }
161}
162
163impl RequiredOptions {
164    fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
165        let sig = resolve.wasm_signature(abi, func);
166        let mut ret = RequiredOptions::empty();
167        // Lift the params and lower the results for imports
168        ret.add_lift(TypeContents::for_types(
169            resolve,
170            func.params.iter().map(|p| &p.ty),
171        ));
172        ret.add_lower(TypeContents::for_types(resolve, &func.result));
173
174        // If anything is indirect then `memory` will be required to read the
175        // indirect values.
176        if sig.retptr || sig.indirect_params {
177            ret |= RequiredOptions::MEMORY;
178        }
179        if abi == AbiVariant::GuestImportAsync {
180            ret |= RequiredOptions::ASYNC;
181        }
182        ret
183    }
184
185    fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
186        let sig = resolve.wasm_signature(abi, func);
187        let mut ret = RequiredOptions::empty();
188        // Lower the params and lift the results for exports
189        ret.add_lower(TypeContents::for_types(
190            resolve,
191            func.params.iter().map(|p| &p.ty),
192        ));
193        ret.add_lift(TypeContents::for_types(resolve, &func.result));
194
195        // If anything is indirect then `memory` will be required to read the
196        // indirect values, but if the arguments are indirect then `realloc` is
197        // additionally required to allocate space for the parameters.
198        if sig.retptr || sig.indirect_params {
199            ret |= RequiredOptions::MEMORY;
200            if sig.indirect_params {
201                ret |= RequiredOptions::REALLOC;
202            }
203        }
204        if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
205            ret |= RequiredOptions::ASYNC;
206            ret |= task_return_options_and_type(resolve, func).0;
207        }
208        ret
209    }
210
211    fn add_lower(&mut self, types: TypeContents) {
212        // If lists/strings are lowered into wasm then memory is required as
213        // usual but `realloc` is also required to allow the external caller to
214        // allocate space in the destination for the list/string.
215        if types.contains(TypeContents::NEEDS_MEMORY) {
216            *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
217        }
218        if types.contains(TypeContents::STRING) {
219            *self |= RequiredOptions::MEMORY
220                | RequiredOptions::STRING_ENCODING
221                | RequiredOptions::REALLOC;
222        }
223    }
224
225    fn add_lift(&mut self, types: TypeContents) {
226        // Unlike for `lower` when lifting a string/list all that's needed is
227        // memory, since the string/list already resides in memory `realloc`
228        // isn't needed.
229        if types.contains(TypeContents::NEEDS_MEMORY) {
230            *self |= RequiredOptions::MEMORY;
231        }
232        if types.contains(TypeContents::STRING) {
233            *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
234        }
235    }
236
237    fn into_iter(
238        self,
239        encoding: StringEncoding,
240        memory_index: Option<u32>,
241        realloc_index: Option<u32>,
242    ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
243        #[derive(Default)]
244        struct Iter {
245            options: [Option<CanonicalOption>; 5],
246            current: usize,
247            count: usize,
248        }
249
250        impl Iter {
251            fn push(&mut self, option: CanonicalOption) {
252                assert!(self.count < self.options.len());
253                self.options[self.count] = Some(option);
254                self.count += 1;
255            }
256        }
257
258        impl Iterator for Iter {
259            type Item = CanonicalOption;
260
261            fn next(&mut self) -> Option<Self::Item> {
262                if self.current == self.count {
263                    return None;
264                }
265                let option = self.options[self.current];
266                self.current += 1;
267                option
268            }
269
270            fn size_hint(&self) -> (usize, Option<usize>) {
271                (self.count - self.current, Some(self.count - self.current))
272            }
273        }
274
275        impl ExactSizeIterator for Iter {}
276
277        let mut iter = Iter::default();
278
279        if self.contains(RequiredOptions::MEMORY) {
280            iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
281                anyhow!("module does not export a memory named `memory`")
282            })?));
283        }
284
285        if self.contains(RequiredOptions::REALLOC) {
286            iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
287                || anyhow!("module does not export a function named `cabi_realloc`"),
288            )?));
289        }
290
291        if self.contains(RequiredOptions::STRING_ENCODING) {
292            iter.push(encoding.into());
293        }
294
295        if self.contains(RequiredOptions::ASYNC) {
296            iter.push(CanonicalOption::Async);
297        }
298
299        Ok(iter)
300    }
301}
302
303bitflags::bitflags! {
304    /// Flags about what kinds of types are present within the recursive
305    /// structure of a type.
306    struct TypeContents: u8 {
307        const STRING = 1 << 0;
308        const NEEDS_MEMORY = 1 << 1;
309    }
310}
311
312impl TypeContents {
313    fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
314        let mut cur = TypeContents::empty();
315        for ty in types {
316            cur |= Self::for_type(resolve, ty);
317        }
318        cur
319    }
320
321    fn for_optional_types<'a>(
322        resolve: &Resolve,
323        types: impl Iterator<Item = Option<&'a Type>>,
324    ) -> Self {
325        Self::for_types(resolve, types.flatten())
326    }
327
328    fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
329        match ty {
330            Some(ty) => Self::for_type(resolve, ty),
331            None => Self::empty(),
332        }
333    }
334
335    fn for_type(resolve: &Resolve, ty: &Type) -> Self {
336        match ty {
337            Type::Id(id) => match &resolve.types[*id].kind {
338                TypeDefKind::Handle(h) => match h {
339                    wit_parser::Handle::Own(_) => Self::empty(),
340                    wit_parser::Handle::Borrow(_) => Self::empty(),
341                },
342                TypeDefKind::Resource => Self::empty(),
343                TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
344                TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
345                TypeDefKind::Flags(_) => Self::empty(),
346                TypeDefKind::Option(t) => Self::for_type(resolve, t),
347                TypeDefKind::Result(r) => {
348                    Self::for_optional_type(resolve, r.ok.as_ref())
349                        | Self::for_optional_type(resolve, r.err.as_ref())
350                }
351                TypeDefKind::Variant(v) => {
352                    Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
353                }
354                TypeDefKind::Enum(_) => Self::empty(),
355                TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::NEEDS_MEMORY,
356                TypeDefKind::Map(k, v) => {
357                    Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::NEEDS_MEMORY
358                }
359                TypeDefKind::FixedLengthList(t, _elements) => Self::for_type(resolve, t),
360                TypeDefKind::Type(t) => Self::for_type(resolve, t),
361                TypeDefKind::Future(_) => Self::empty(),
362                TypeDefKind::Stream(_) => Self::empty(),
363                TypeDefKind::Unknown => unreachable!(),
364            },
365            Type::String => Self::STRING,
366            _ => Self::empty(),
367        }
368    }
369}
370
371/// State relating to encoding a component.
372pub struct EncodingState<'a> {
373    /// The component being encoded.
374    component: ComponentBuilder,
375    /// The index into the core module index space for the inner core module.
376    ///
377    /// If `None`, the core module has not been encoded.
378    module_index: Option<u32>,
379    /// The index into the core instance index space for the inner core module.
380    ///
381    /// If `None`, the core module has not been instantiated.
382    instance_index: Option<u32>,
383    /// The index in the core memory index space for the exported memory.
384    ///
385    /// If `None`, then the memory has not yet been aliased.
386    memory_index: Option<u32>,
387    /// The index of the shim instance used for lowering imports into the core instance.
388    ///
389    /// If `None`, then the shim instance how not yet been encoded.
390    shim_instance_index: Option<u32>,
391    /// The index of the fixups module to instantiate to fill in the lowered imports.
392    ///
393    /// If `None`, then a fixup module has not yet been encoded.
394    fixups_module_index: Option<u32>,
395
396    /// A map of named adapter modules and the index that the module was defined
397    /// at.
398    adapter_modules: IndexMap<&'a str, u32>,
399    /// A map of adapter module instances and the index of their instance.
400    adapter_instances: IndexMap<&'a str, u32>,
401
402    /// Imported/exported instances and what index they were imported as.
403    instances: IndexMap<InterfaceId, u32>,
404    imported_funcs: IndexMap<String, u32>,
405
406    /// Maps used when translating types to the component model binary format.
407    /// Note that imports and exports are stored in separate maps since they
408    /// need fresh hierarchies of types in case the same interface is both
409    /// imported and exported.
410    type_encoding_maps: TypeEncodingMaps<'a>,
411
412    /// Cache of items that have been aliased from core instances.
413    ///
414    /// This is a helper to reduce the number of aliases created by ensuring
415    /// that repeated requests for the same item return the same index of an
416    /// original `core alias` item.
417    aliased_core_items: HashMap<(u32, String), u32>,
418
419    /// Metadata about the world inferred from the input to `ComponentEncoder`.
420    info: &'a ComponentWorld<'a>,
421
422    /// Maps from original export name to task initialization wrapper function index.
423    /// Used to wrap exports with __wasm_init_(async_)task calls.
424    export_task_initialization_wrappers: HashMap<String, u32>,
425}
426
427impl<'a> EncodingState<'a> {
428    fn encode_core_modules(&mut self) {
429        assert!(self.module_index.is_none());
430        let idx = self
431            .component
432            .core_module_raw(Some("main"), &self.info.encoder.module);
433        self.module_index = Some(idx);
434
435        for (name, adapter) in self.info.adapters.iter() {
436            let debug_name = if adapter.library_info.is_some() {
437                name.to_string()
438            } else {
439                format!("wit-component:adapter:{name}")
440            };
441            let idx = if self.info.encoder.debug_names {
442                let mut add_meta = wasm_metadata::AddMetadata::default();
443                add_meta.name = AddMetadataField::Set(debug_name.clone());
444                let wasm = add_meta
445                    .to_wasm(&adapter.wasm)
446                    .expect("core wasm can get name added");
447                self.component.core_module_raw(Some(&debug_name), &wasm)
448            } else {
449                self.component
450                    .core_module_raw(Some(&debug_name), &adapter.wasm)
451            };
452            let prev = self.adapter_modules.insert(name, idx);
453            assert!(prev.is_none());
454        }
455    }
456
457    fn root_import_type_encoder(
458        &mut self,
459        interface: Option<InterfaceId>,
460    ) -> RootTypeEncoder<'_, 'a> {
461        RootTypeEncoder {
462            state: self,
463            interface,
464            import_types: true,
465        }
466    }
467
468    fn root_export_type_encoder(
469        &mut self,
470        interface: Option<InterfaceId>,
471    ) -> RootTypeEncoder<'_, 'a> {
472        RootTypeEncoder {
473            state: self,
474            interface,
475            import_types: false,
476        }
477    }
478
479    fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
480        InstanceTypeEncoder {
481            state: self,
482            interface,
483            type_encoding_maps: Default::default(),
484            ty: Default::default(),
485        }
486    }
487
488    fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
489        let mut has_funcs = false;
490        for (name, info) in self.info.import_map.iter() {
491            match name {
492                Some(name) => {
493                    self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
494                }
495                None => has_funcs = true,
496            }
497        }
498
499        let resolve = &self.info.encoder.metadata.resolve;
500        let world = &resolve.worlds[self.info.encoder.metadata.world];
501
502        // FIXME: ideally this would use the liveness analysis from
503        // world-building to only encode live types, not all type in a world.
504        for (_name, item) in world.imports.iter() {
505            if let WorldItem::Type { id, .. } = item {
506                self.root_import_type_encoder(None)
507                    .encode_valtype(resolve, &Type::Id(*id))?;
508            }
509        }
510
511        if has_funcs {
512            let info = &self.info.import_map[&None];
513            self.encode_root_import_funcs(info)?;
514        }
515        Ok(())
516    }
517
518    fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
519        let resolve = &self.info.encoder.metadata.resolve;
520        let interface_id = info.interface.as_ref().unwrap();
521        let interface_id = *interface_id;
522        let interface = &resolve.interfaces[interface_id];
523        log::trace!("encoding imports for `{name}` as {interface_id:?}");
524        let mut encoder = self.instance_type_encoder(interface_id);
525
526        // First encode all type information
527        if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
528            for ty in live {
529                log::trace!(
530                    "encoding extra type {ty:?} name={:?}",
531                    resolve.types[*ty].name
532                );
533                encoder.encode_valtype(resolve, &Type::Id(*ty))?;
534            }
535        }
536
537        // Next encode all required functions from this imported interface
538        // into the instance type.
539        for (_, func) in interface.functions.iter() {
540            if !(info
541                .lowerings
542                .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
543                || info
544                    .lowerings
545                    .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
546            {
547                continue;
548            }
549            log::trace!("encoding function type for `{}`", func.name);
550            let idx = encoder.encode_func_type(resolve, func)?;
551
552            encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
553        }
554
555        let ty = encoder.ty;
556        // Don't encode empty instance types since they're not
557        // meaningful to the runtime of the component anyway.
558        if ty.is_empty() {
559            return Ok(());
560        }
561        let instance_type_idx = self
562            .component
563            .type_instance(Some(&format!("ty-{name}")), &ty);
564        let instance_idx = self.component.import(
565            wasm_encoder::ComponentExternName {
566                name: name.into(),
567                implements: info.implements.as_deref().map(|s| s.into()),
568            },
569            ComponentTypeRef::Instance(instance_type_idx),
570        );
571        let prev = self.instances.insert(interface_id, instance_idx);
572        assert!(prev.is_none());
573        Ok(())
574    }
575
576    fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
577        let resolve = &self.info.encoder.metadata.resolve;
578        let world = self.info.encoder.metadata.world;
579        for (name, item) in resolve.worlds[world].imports.iter() {
580            let func = match item {
581                WorldItem::Function(f) => f,
582                WorldItem::Interface { .. } | WorldItem::Type { .. } => continue,
583            };
584            let name = resolve.name_world_key(name);
585            if !(info
586                .lowerings
587                .contains_key(&(name.clone(), AbiVariant::GuestImport))
588                || info
589                    .lowerings
590                    .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
591            {
592                continue;
593            }
594            log::trace!("encoding function type for `{}`", func.name);
595            let idx = self
596                .root_import_type_encoder(None)
597                .encode_func_type(resolve, func)?;
598            let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
599            let prev = self.imported_funcs.insert(name, func_idx);
600            assert!(prev.is_none());
601        }
602        Ok(())
603    }
604
605    fn alias_instance_type_export(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
606        let ty = &self.info.encoder.metadata.resolve.types[id];
607        let name = ty.name.as_ref().expect("type must have a name");
608        let instance = self.instances[&interface];
609        self.component
610            .alias_export(instance, name, ComponentExportKind::Type)
611    }
612
613    fn encode_core_instantiation(&mut self) -> Result<()> {
614        // Encode a shim instantiation if needed
615        let shims = self.encode_shim_instantiation()?;
616
617        // Next declare any types needed for imported intrinsics. This
618        // populates `export_type_map` and will additionally be used for
619        // imports to modules instantiated below.
620        self.declare_types_for_imported_intrinsics(&shims)?;
621
622        // Next instantiate the main module. This provides the linear memory to
623        // use for all future adapters and enables creating indirect lowerings
624        // at the end.
625        self.instantiate_main_module(&shims)?;
626
627        // Create any wrappers needed for initializing tasks if task initialization
628        // exports are present in the main module.
629        self.create_export_task_initialization_wrappers()?;
630
631        // Separate the adapters according which should be instantiated before
632        // and after indirect lowerings are encoded.
633        let (before, after) = self
634            .info
635            .adapters
636            .iter()
637            .partition::<Vec<_>, _>(|(_, adapter)| {
638                !matches!(
639                    adapter.library_info,
640                    Some(LibraryInfo {
641                        instantiate_after_shims: true,
642                        ..
643                    })
644                )
645            });
646
647        for (name, _adapter) in before {
648            self.instantiate_adapter_module(&shims, name)?;
649        }
650
651        // With all the relevant core wasm instances in play now the original shim
652        // module, if present, can be filled in with lowerings/adapters/etc.
653        self.encode_indirect_lowerings(&shims)?;
654
655        for (name, _adapter) in after {
656            self.instantiate_adapter_module(&shims, name)?;
657        }
658
659        self.encode_initialize_with_start()?;
660
661        Ok(())
662    }
663
664    fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
665        let resolve = &self.info.encoder.metadata.resolve;
666        let ty = &resolve.types[id];
667        match ty.owner {
668            // If this resource is owned by a world then it's a top-level
669            // resource which means it must have already been translated so
670            // it's available for lookup in `import_type_map`.
671            TypeOwner::World(_) => self.type_encoding_maps.id_to_index[&id],
672            TypeOwner::Interface(i) => {
673                let instance = self.instances[&i];
674                let name = ty.name.as_ref().expect("resources must be named");
675                self.component
676                    .alias_export(instance, name, ComponentExportKind::Type)
677            }
678            TypeOwner::None => panic!("resources must have an owner"),
679        }
680    }
681
682    fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
683        let resolve = &self.info.encoder.metadata.resolve;
684        let exports = match module {
685            CustomModule::Main => &self.info.encoder.main_module_exports,
686            CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
687        };
688
689        if exports.is_empty() {
690            return Ok(());
691        }
692
693        let mut interface_func_core_names = IndexMap::new();
694        let mut world_func_core_names = IndexMap::new();
695        for (core_name, export) in self.info.exports_for(module).iter() {
696            match export {
697                Export::WorldFunc(_, name, _) => {
698                    let prev = world_func_core_names.insert(name, core_name);
699                    assert!(prev.is_none());
700                }
701                Export::InterfaceFunc(key, _, name, _) => {
702                    let prev = interface_func_core_names
703                        .entry(key)
704                        .or_insert(IndexMap::new())
705                        .insert(name.as_str(), core_name);
706                    assert!(prev.is_none());
707                }
708                Export::WorldFuncCallback(..)
709                | Export::InterfaceFuncCallback(..)
710                | Export::WorldFuncPostReturn(..)
711                | Export::InterfaceFuncPostReturn(..)
712                | Export::ResourceDtor(..)
713                | Export::Memory
714                | Export::GeneralPurposeRealloc
715                | Export::GeneralPurposeExportRealloc
716                | Export::GeneralPurposeImportRealloc
717                | Export::Initialize
718                | Export::ReallocForAdapter
719                | Export::IndirectFunctionTable
720                | Export::WasmInitTask
721                | Export::WasmInitAsyncTask => continue,
722            }
723        }
724
725        let world = &resolve.worlds[self.info.encoder.metadata.world];
726
727        for export_name in exports {
728            let export_string = resolve.name_world_key(export_name);
729            match &world.exports[export_name] {
730                WorldItem::Function(func) => {
731                    let ty = self
732                        .root_import_type_encoder(None)
733                        .encode_func_type(resolve, func)?;
734                    let core_name = world_func_core_names[&func.name];
735                    let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
736                    self.component
737                        .export(export_string, ComponentExportKind::Func, idx, None);
738                }
739                item @ WorldItem::Interface { id, .. } => {
740                    let core_names = interface_func_core_names.get(export_name);
741                    self.encode_interface_export(
742                        &export_string,
743                        module,
744                        export_name,
745                        item,
746                        *id,
747                        core_names,
748                    )?;
749                }
750                WorldItem::Type { .. } => unreachable!(),
751            }
752        }
753
754        Ok(())
755    }
756
757    fn encode_interface_export(
758        &mut self,
759        export_name: &str,
760        module: CustomModule<'_>,
761        key: &WorldKey,
762        item: &WorldItem,
763        export: InterfaceId,
764        interface_func_core_names: Option<&IndexMap<&str, &str>>,
765    ) -> Result<()> {
766        log::trace!("encode interface export `{export_name}`");
767        let resolve = &self.info.encoder.metadata.resolve;
768
769        // First execute a `canon lift` for all the functions in this interface
770        // from the core wasm export. This requires type information but notably
771        // not exported type information since we don't want to export this
772        // interface's types from the root of the component. Each lifted
773        // function is saved off into an `imports` array to get imported into
774        // the nested component synthesized below.
775        let mut imports = Vec::new();
776        let mut root = self.root_export_type_encoder(Some(export));
777        for (_, func) in &resolve.interfaces[export].functions {
778            let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
779            let ty = root.encode_func_type(resolve, func)?;
780            let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
781            imports.push((
782                import_func_name(func),
783                ComponentExportKind::Func,
784                func_index,
785            ));
786        }
787
788        // Next a nested component is created which will import the functions
789        // above and then reexport them. The purpose of them is to "re-type" the
790        // functions through type ascription on each `func` item.
791        let mut nested = NestedComponentTypeEncoder {
792            component: ComponentBuilder::default(),
793            type_encoding_maps: Default::default(),
794            export_types: false,
795            interface: export,
796            state: self,
797            imports: IndexMap::new(),
798        };
799
800        // Import all transitively-referenced types from other interfaces into
801        // this component. This temporarily switches the `interface` listed to
802        // the interface of the referred-to-type to generate the import. After
803        // this loop `interface` is rewritten to `export`.
804        //
805        // Each component is a standalone "island" so the necessary type
806        // information needs to be rebuilt within this component. This ensures
807        // that we're able to build a valid component and additionally connect
808        // all the type information to the outer context.
809        let mut types_to_import = LiveTypes::default();
810        types_to_import.add_interface(resolve, export);
811        let exports_used = &nested.state.info.exports_used[&export];
812        for ty in types_to_import.iter() {
813            if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
814                if owner == export {
815                    // Here this deals with the current exported interface which
816                    // is handled below.
817                    continue;
818                }
819
820                // Ensure that `self` has encoded this type before. If so this
821                // is a noop but otherwise it generates the type here.
822                let mut encoder = if exports_used.contains(&owner) {
823                    nested.state.root_export_type_encoder(Some(export))
824                } else {
825                    nested.state.root_import_type_encoder(Some(export))
826                };
827                encoder.encode_valtype(resolve, &Type::Id(ty))?;
828
829                // Next generate the same type but this time within the
830                // component itself. The type generated above (or prior) will be
831                // used to satisfy this type import.
832                nested.interface = owner;
833                nested.encode_valtype(resolve, &Type::Id(ty))?;
834            }
835        }
836        nested.interface = export;
837
838        // Record the map of types imported to their index at where they were
839        // imported. This is used after imports are encoded as exported types
840        // will refer to these.
841        let imported_type_maps = nested.type_encoding_maps.clone();
842
843        // Handle resource types for this instance specially, namely importing
844        // them into the nested component. This models how the resource is
845        // imported from its definition in the outer component to get reexported
846        // internally. This chiefly avoids creating a second resource which is
847        // not desired in this situation.
848        let mut resources = HashMap::new();
849        for (_name, ty) in resolve.interfaces[export].types.iter() {
850            if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
851                continue;
852            }
853            let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
854                ComponentValType::Type(idx) => idx,
855                _ => unreachable!(),
856            };
857            resources.insert(*ty, idx);
858        }
859
860        // Next import each function of this interface. This will end up
861        // defining local types as necessary or using the types as imported
862        // above.
863        for (_, func) in resolve.interfaces[export].functions.iter() {
864            let ty = nested.encode_func_type(resolve, func)?;
865            nested
866                .component
867                .import(&import_func_name(func), ComponentTypeRef::Func(ty));
868        }
869
870        // Swap the `nested.type_map` which was previously from `TypeId` to
871        // `u32` to instead being from `u32` to `TypeId`. This reverse map is
872        // then used in conjunction with `self.type_map` to satisfy all type
873        // imports of the nested component generated. The type import's index in
874        // the inner component is translated to a `TypeId` via `reverse_map`
875        // which is then translated back to our own index space via `type_map`.
876        let reverse_map = nested
877            .type_encoding_maps
878            .id_to_index
879            .drain()
880            .map(|p| (p.1, p.0))
881            .collect::<HashMap<_, _>>();
882        nested.type_encoding_maps.def_to_index.clear();
883        for (name, idx) in nested.imports.drain(..) {
884            let id = reverse_map[&idx];
885            let idx = nested.state.type_encoding_maps.id_to_index[&id];
886            imports.push((name, ComponentExportKind::Type, idx))
887        }
888
889        // Before encoding exports reset the type map to what all was imported
890        // from foreign interfaces. This will enable any encoded types below to
891        // refer to imports which, after type substitution, will point to the
892        // correct type in the outer component context.
893        nested.type_encoding_maps = imported_type_maps;
894
895        // Next the component reexports all of its imports, but notably uses the
896        // type ascription feature to change the type of the function. Note that
897        // no structural change is happening to the types here but instead types
898        // are getting proper names and such now that this nested component is a
899        // new type index space. Hence the `export_types = true` flag here which
900        // flows through the type encoding and when types are emitted.
901        nested.export_types = true;
902        nested.type_encoding_maps.func_type_map.clear();
903
904        // To start off all type information is encoded. This will be used by
905        // functions below but notably this also has special handling for
906        // resources. Resources reexport their imported resource type under
907        // the final name which achieves the desired goal of threading through
908        // the original resource without creating a new one.
909        for (_, id) in resolve.interfaces[export].types.iter() {
910            let ty = &resolve.types[*id];
911            match ty.kind {
912                TypeDefKind::Resource => {
913                    let idx = nested.component.export(
914                        ty.name.as_ref().expect("resources must be named"),
915                        ComponentExportKind::Type,
916                        resources[id],
917                        None,
918                    );
919                    nested.type_encoding_maps.id_to_index.insert(*id, idx);
920                }
921                _ => {
922                    nested.encode_valtype(resolve, &Type::Id(*id))?;
923                }
924            }
925        }
926
927        for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
928            let ty = nested.encode_func_type(resolve, func)?;
929            nested.component.export(
930                &func.name,
931                ComponentExportKind::Func,
932                i as u32,
933                Some(ComponentTypeRef::Func(ty)),
934            );
935        }
936
937        // Embed the component within our component and then instantiate it with
938        // the lifted functions. That final instance is then exported under the
939        // appropriate name as the final typed export of this component.
940        let component = nested.component;
941        let component_index = self
942            .component
943            .component(Some(&format!("{export_name}-shim-component")), component);
944        let instance_index = self.component.instantiate(
945            Some(&format!("{export_name}-shim-instance")),
946            component_index,
947            imports,
948        );
949        let idx = self.component.export(
950            wasm_encoder::ComponentExternName {
951                name: export_name.into(),
952                implements: resolve.implements_value(key, item).map(|s| s.into()),
953            },
954            ComponentExportKind::Instance,
955            instance_index,
956            None,
957        );
958        let prev = self.instances.insert(export, idx);
959        assert!(prev.is_none());
960
961        // After everything is all said and done remove all the type information
962        // about type exports of this interface. Any entries in the map
963        // currently were used to create the instance above but aren't the
964        // actual copy of the exported type since that comes from the exported
965        // instance itself. Entries will be re-inserted into this map as
966        // necessary via aliases from the exported instance which is the new
967        // source of truth for all these types.
968        for (_name, id) in resolve.interfaces[export].types.iter() {
969            self.type_encoding_maps.id_to_index.remove(id);
970            self.type_encoding_maps
971                .def_to_index
972                .remove(&resolve.types[*id].kind);
973        }
974
975        return Ok(());
976
977        struct NestedComponentTypeEncoder<'state, 'a> {
978            component: ComponentBuilder,
979            type_encoding_maps: TypeEncodingMaps<'a>,
980            export_types: bool,
981            interface: InterfaceId,
982            state: &'state mut EncodingState<'a>,
983            imports: IndexMap<String, u32>,
984        }
985
986        impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
987            fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
988                self.component.type_defined(None)
989            }
990            fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
991                self.component.type_function(None)
992            }
993            fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
994                if self.export_types {
995                    Some(
996                        self.component
997                            .export(name, ComponentExportKind::Type, idx, None),
998                    )
999                } else {
1000                    let name = self.unique_import_name(name);
1001                    let ret = self
1002                        .component
1003                        .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1004                    self.imports.insert(name, ret);
1005                    Some(ret)
1006                }
1007            }
1008            fn export_resource(&mut self, name: &'a str) -> u32 {
1009                if self.export_types {
1010                    panic!("resources should already be exported")
1011                } else {
1012                    let name = self.unique_import_name(name);
1013                    let ret = self
1014                        .component
1015                        .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1016                    self.imports.insert(name, ret);
1017                    ret
1018                }
1019            }
1020            fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1021                unreachable!()
1022            }
1023            fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
1024                &mut self.type_encoding_maps
1025            }
1026            fn interface(&self) -> Option<InterfaceId> {
1027                Some(self.interface)
1028            }
1029        }
1030
1031        impl NestedComponentTypeEncoder<'_, '_> {
1032            fn unique_import_name(&mut self, name: &str) -> String {
1033                let mut name = format!("import-type-{name}");
1034                let mut n = 0;
1035                while self.imports.contains_key(&name) {
1036                    name = format!("{name}{n}");
1037                    n += 1;
1038                }
1039                name
1040            }
1041        }
1042    }
1043
1044    fn encode_lift(
1045        &mut self,
1046        module: CustomModule<'_>,
1047        core_name: &str,
1048        key: &WorldKey,
1049        func: &Function,
1050        ty: u32,
1051    ) -> Result<u32> {
1052        let resolve = &self.info.encoder.metadata.resolve;
1053        let metadata = self.info.module_metadata_for(module);
1054        let instance_index = self.instance_for(module);
1055        // If we generated an init task wrapper for this export, use that,
1056        // otherwise alias the original export.
1057        let core_func_index =
1058            if let Some(&wrapper_idx) = self.export_task_initialization_wrappers.get(core_name) {
1059                wrapper_idx
1060            } else {
1061                self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func)
1062            };
1063        let exports = self.info.exports_for(module);
1064
1065        let options = RequiredOptions::for_export(
1066            resolve,
1067            func,
1068            exports
1069                .abi(key, func)
1070                .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1071        );
1072
1073        let encoding = metadata
1074            .export_encodings
1075            .get(resolve, key, &func.name)
1076            .unwrap();
1077        let exports = self.info.exports_for(module);
1078        let realloc_index = exports
1079            .export_realloc_for(key, &func.name)
1080            .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1081        let mut options = options
1082            .into_iter(encoding, self.memory_index, realloc_index)?
1083            .collect::<Vec<_>>();
1084
1085        if let Some(post_return) = exports.post_return(key, func) {
1086            let post_return = self.core_alias_export(
1087                Some(post_return),
1088                instance_index,
1089                post_return,
1090                ExportKind::Func,
1091            );
1092            options.push(CanonicalOption::PostReturn(post_return));
1093        }
1094        if let Some(callback) = exports.callback(key, func) {
1095            let callback =
1096                self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1097            options.push(CanonicalOption::Callback(callback));
1098        }
1099        let func_index = self
1100            .component
1101            .lift_func(Some(&func.name), core_func_index, ty, options);
1102        Ok(func_index)
1103    }
1104
1105    fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1106        let mut ret = Shims::default();
1107
1108        ret.append_indirect(self.info, CustomModule::Main)
1109            .context("failed to register indirect shims for main module")?;
1110
1111        // For all required adapter modules a shim is created for each required
1112        // function and additionally a set of shims are created for the
1113        // interface imported into the shim module itself.
1114        for (adapter_name, _adapter) in self.info.adapters.iter() {
1115            ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1116                .with_context(|| {
1117                    format!("failed to register indirect shims for adapter {adapter_name}")
1118                })?;
1119        }
1120
1121        if ret.shims.is_empty() {
1122            return Ok(ret);
1123        }
1124
1125        assert!(self.shim_instance_index.is_none());
1126        assert!(self.fixups_module_index.is_none());
1127
1128        // This function encodes two modules:
1129        // - A shim module that defines a table and exports functions
1130        //   that indirectly call through the table.
1131        // - A fixup module that imports that table and a set of functions
1132        //   and populates the imported table via active element segments. The
1133        //   fixup module is used to populate the shim's table once the
1134        //   imported functions have been lowered.
1135
1136        let mut types = TypeSection::new();
1137        let mut tables = TableSection::new();
1138        let mut functions = FunctionSection::new();
1139        let mut exports = ExportSection::new();
1140        let mut code = CodeSection::new();
1141        let mut sigs = IndexMap::new();
1142        let mut imports_section = ImportSection::new();
1143        let mut elements = ElementSection::new();
1144        let mut func_indexes = Vec::new();
1145        let mut func_names = NameMap::new();
1146
1147        for (i, shim) in ret.shims.values().enumerate() {
1148            let i = i as u32;
1149            let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1150                let index = types.len();
1151                types.ty().function(
1152                    shim.sig.params.iter().map(to_val_type),
1153                    shim.sig.results.iter().map(to_val_type),
1154                );
1155                index
1156            });
1157
1158            functions.function(type_index);
1159            Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1160            exports.export(&shim.name, ExportKind::Func, i);
1161
1162            imports_section.import("", &shim.name, EntityType::Function(type_index));
1163            func_indexes.push(i);
1164            func_names.append(i, &shim.debug_name);
1165        }
1166        let mut names = NameSection::new();
1167        names.module("wit-component:shim");
1168        names.functions(&func_names);
1169
1170        let table_type = TableType {
1171            element_type: RefType::FUNCREF,
1172            minimum: ret.shims.len() as u64,
1173            maximum: Some(ret.shims.len() as u64),
1174            table64: false,
1175            shared: false,
1176        };
1177
1178        tables.table(table_type);
1179
1180        exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1181        imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1182
1183        elements.active(
1184            None,
1185            &ConstExpr::i32_const(0),
1186            Elements::Functions(func_indexes.into()),
1187        );
1188
1189        let mut shim = Module::new();
1190        shim.section(&types);
1191        shim.section(&functions);
1192        shim.section(&tables);
1193        shim.section(&exports);
1194        shim.section(&code);
1195        shim.section(&RawCustomSection(
1196            &crate::base_producers().raw_custom_section(),
1197        ));
1198        if self.info.encoder.debug_names {
1199            shim.section(&names);
1200        }
1201
1202        let mut fixups = Module::default();
1203        fixups.section(&types);
1204        fixups.section(&imports_section);
1205        fixups.section(&elements);
1206        fixups.section(&RawCustomSection(
1207            &crate::base_producers().raw_custom_section(),
1208        ));
1209
1210        if self.info.encoder.debug_names {
1211            let mut names = NameSection::new();
1212            names.module("wit-component:fixups");
1213            fixups.section(&names);
1214        }
1215
1216        let shim_module_index = self
1217            .component
1218            .core_module(Some("wit-component-shim-module"), &shim);
1219        let fixup_index = self
1220            .component
1221            .core_module(Some("wit-component-fixup"), &fixups);
1222        self.fixups_module_index = Some(fixup_index);
1223        let shim_instance = self.component.core_instantiate(
1224            Some("wit-component-shim-instance"),
1225            shim_module_index,
1226            [],
1227        );
1228        self.shim_instance_index = Some(shim_instance);
1229
1230        return Ok(ret);
1231    }
1232
1233    fn encode_shim_function(
1234        type_index: u32,
1235        func_index: u32,
1236        code: &mut CodeSection,
1237        param_count: u32,
1238    ) {
1239        let mut func = wasm_encoder::Function::new(std::iter::empty());
1240        for i in 0..param_count {
1241            func.instructions().local_get(i);
1242        }
1243        func.instructions().i32_const(func_index as i32);
1244        func.instructions().call_indirect(0, type_index);
1245        func.instructions().end();
1246        code.function(&func);
1247    }
1248
1249    fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1250        if shims.shims.is_empty() {
1251            return Ok(());
1252        }
1253
1254        let shim_instance_index = self
1255            .shim_instance_index
1256            .expect("must have an instantiated shim");
1257
1258        let table_index = self.core_alias_export(
1259            Some("shim table"),
1260            shim_instance_index,
1261            INDIRECT_TABLE_NAME,
1262            ExportKind::Table,
1263        );
1264
1265        let resolve = &self.info.encoder.metadata.resolve;
1266
1267        let mut exports = Vec::new();
1268        exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1269
1270        for shim in shims.shims.values() {
1271            let core_func_index = match &shim.kind {
1272                // Indirect lowerings are a `canon lower`'d function with
1273                // options specified from a previously instantiated instance.
1274                // This previous instance could either be the main module or an
1275                // adapter module, which affects the `realloc` option here.
1276                // Currently only one linear memory is supported so the linear
1277                // memory always comes from the main module.
1278                ShimKind::IndirectLowering {
1279                    interface,
1280                    index,
1281                    realloc,
1282                    encoding,
1283                } => {
1284                    let interface = &self.info.import_map[interface];
1285                    let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1286                    let func_index = match &interface.interface {
1287                        Some(interface_id) => {
1288                            let instance_index = self.instances[interface_id];
1289                            self.component.alias_export(
1290                                instance_index,
1291                                name,
1292                                ComponentExportKind::Func,
1293                            )
1294                        }
1295                        None => self.imported_funcs[name],
1296                    };
1297
1298                    let realloc = self
1299                        .info
1300                        .exports_for(*realloc)
1301                        .import_realloc_for(interface.interface, name)
1302                        .map(|name| {
1303                            let instance = self.instance_for(*realloc);
1304                            self.core_alias_export(
1305                                Some("realloc"),
1306                                instance,
1307                                name,
1308                                ExportKind::Func,
1309                            )
1310                        });
1311
1312                    self.component.lower_func(
1313                        Some(&shim.debug_name),
1314                        func_index,
1315                        shim.options
1316                            .into_iter(*encoding, self.memory_index, realloc)?,
1317                    )
1318                }
1319
1320                // Adapter shims are defined by an export from an adapter
1321                // instance, so use the specified name here and the previously
1322                // created instances to get the core item that represents the
1323                // shim.
1324                ShimKind::Adapter { adapter, func } => self.core_alias_export(
1325                    Some(func),
1326                    self.adapter_instances[adapter],
1327                    func,
1328                    ExportKind::Func,
1329                ),
1330
1331                // Resources are required for a module to be instantiated
1332                // meaning that any destructor for the resource must be called
1333                // indirectly due to the otherwise circular dependency between
1334                // the module and the resource itself.
1335                ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1336                    Some(export),
1337                    self.instance_for(*module),
1338                    export,
1339                    ExportKind::Func,
1340                ),
1341
1342                ShimKind::PayloadFunc {
1343                    for_module,
1344                    info,
1345                    kind,
1346                } => {
1347                    let metadata = self.info.module_metadata_for(*for_module);
1348                    let exports = self.info.exports_for(*for_module);
1349                    let instance_index = self.instance_for(*for_module);
1350                    let (encoding, realloc) = match &info.ty {
1351                        PayloadType::Type { function, .. } => {
1352                            if info.imported {
1353                                (
1354                                    metadata.import_encodings.get(resolve, &info.key, function),
1355                                    exports.import_realloc_for(info.interface, function),
1356                                )
1357                            } else {
1358                                (
1359                                    metadata.export_encodings.get(resolve, &info.key, function),
1360                                    exports.export_realloc_for(&info.key, function),
1361                                )
1362                            }
1363                        }
1364                        PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1365                    };
1366                    let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1367                    let realloc_index = realloc.map(|name| {
1368                        self.core_alias_export(
1369                            Some("realloc"),
1370                            instance_index,
1371                            name,
1372                            ExportKind::Func,
1373                        )
1374                    });
1375                    let type_index = self.payload_type_index(info)?;
1376                    let options =
1377                        shim.options
1378                            .into_iter(encoding, self.memory_index, realloc_index)?;
1379
1380                    match kind {
1381                        PayloadFuncKind::FutureWrite => {
1382                            self.component.future_write(type_index, options)
1383                        }
1384                        PayloadFuncKind::FutureRead => {
1385                            self.component.future_read(type_index, options)
1386                        }
1387                        PayloadFuncKind::StreamWrite => {
1388                            self.component.stream_write(type_index, options)
1389                        }
1390                        PayloadFuncKind::StreamRead => {
1391                            self.component.stream_read(type_index, options)
1392                        }
1393                    }
1394                }
1395
1396                ShimKind::WaitableSetWait { cancellable } => self
1397                    .component
1398                    .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1399                ShimKind::WaitableSetPoll { cancellable } => self
1400                    .component
1401                    .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1402                ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1403                    shim.options.into_iter(*encoding, self.memory_index, None)?,
1404                ),
1405                ShimKind::ErrorContextDebugMessage {
1406                    for_module,
1407                    encoding,
1408                } => {
1409                    let instance_index = self.instance_for(*for_module);
1410                    let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1411                    let realloc_index = realloc.map(|r| {
1412                        self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1413                    });
1414
1415                    self.component
1416                        .error_context_debug_message(shim.options.into_iter(
1417                            *encoding,
1418                            self.memory_index,
1419                            realloc_index,
1420                        )?)
1421                }
1422                ShimKind::TaskReturn {
1423                    interface,
1424                    func,
1425                    result,
1426                    encoding,
1427                    for_module,
1428                } => {
1429                    // See `Import::ExportedTaskReturn` handling for why this
1430                    // encoder is treated specially.
1431                    let mut encoder = if interface.is_none() {
1432                        self.root_import_type_encoder(*interface)
1433                    } else {
1434                        self.root_export_type_encoder(*interface)
1435                    };
1436                    let result = match result {
1437                        Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1438                        None => None,
1439                    };
1440
1441                    let exports = self.info.exports_for(*for_module);
1442                    let realloc = exports.import_realloc_for(*interface, func);
1443
1444                    let instance_index = self.instance_for(*for_module);
1445                    let realloc_index = realloc.map(|r| {
1446                        self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1447                    });
1448                    let options =
1449                        shim.options
1450                            .into_iter(*encoding, self.memory_index, realloc_index)?;
1451                    self.component.task_return(result, options)
1452                }
1453                ShimKind::ThreadNewIndirect {
1454                    for_module,
1455                    func_ty,
1456                } => {
1457                    // Encode the function type for the thread start function so we can reference it in the `canon` call.
1458                    let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1459                    f.core().func_type(func_ty);
1460
1461                    // In order for the funcref table referenced by `thread.new-indirect` to be used,
1462                    // it must have been exported by the module.
1463                    let exports = self.info.exports_for(*for_module);
1464                    let instance_index = self.instance_for(*for_module);
1465                    let table_idx = exports.indirect_function_table().map(|table| {
1466                        self.core_alias_export(
1467                            Some("indirect-function-table"),
1468                            instance_index,
1469                            table,
1470                            ExportKind::Table,
1471                        )
1472                    }).ok_or_else(|| {
1473                        anyhow!(
1474                            "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1475                        )
1476                    })?;
1477
1478                    self.component.thread_new_indirect(func_ty_idx, table_idx)
1479                }
1480            };
1481
1482            exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1483        }
1484
1485        let instance_index = self
1486            .component
1487            .core_instantiate_exports(Some("fixup-args"), exports);
1488        self.component.core_instantiate(
1489            Some("fixup"),
1490            self.fixups_module_index.expect("must have fixup module"),
1491            [("", ModuleArg::Instance(instance_index))],
1492        );
1493        Ok(())
1494    }
1495
1496    /// Encode the specified `stream` or `future` type in the component using
1497    /// either the `root_import_type_encoder` or the `root_export_type_encoder`
1498    /// depending on the value of `imported`.
1499    ///
1500    /// Note that the payload type `T` of `stream<T>` or `future<T>` may be an
1501    /// imported or exported type, and that determines the appropriate type
1502    /// encoder to use.
1503    fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1504        let resolve = &self.info.encoder.metadata.resolve;
1505        // What exactly is selected here as the encoder is a bit unusual here.
1506        // If the interface is imported, an import encoder is used. An import
1507        // encoder is also used though if `info` is exported and
1508        // `info.interface` is `None`, meaning that this is for a function that
1509        // is in the top-level of a world. At the top level of a world all
1510        // types are imported.
1511        //
1512        // Additionally for the import encoder the interface passed in is
1513        // `None`, not `info.interface`. Notably this means that references to
1514        // named types will be aliased from their imported versions, which is
1515        // what we want here.
1516        //
1517        // Finally though exports do use `info.interface`. Honestly I'm not
1518        // really entirely sure why. Fuzzing is happy though, and truly
1519        // everything must be ok if the fuzzers are happy, right?
1520        let mut encoder = if info.imported || info.interface.is_none() {
1521            self.root_import_type_encoder(None)
1522        } else {
1523            self.root_export_type_encoder(info.interface)
1524        };
1525        match info.ty {
1526            PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1527                ComponentValType::Type(index) => Ok(index),
1528                ComponentValType::Primitive(_) => unreachable!(),
1529            },
1530            PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1531            PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1532        }
1533    }
1534
1535    /// This is a helper function that will declare any types necessary for
1536    /// declaring intrinsics that are imported into the module or adapter.
1537    ///
1538    /// For example resources must be declared to generate
1539    /// destructors/constructors/etc. Additionally types must also be declared
1540    /// for `task.return` with the component model async feature.
1541    fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1542        let resolve = &self.info.encoder.metadata.resolve;
1543        let world = &resolve.worlds[self.info.encoder.metadata.world];
1544
1545        // Iterate over the main module's exports and the exports of all
1546        // adapters. Look for exported interfaces.
1547        let main_module_keys = self.info.encoder.main_module_exports.iter();
1548        let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1549        let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1550            info.required_exports
1551                .iter()
1552                .map(move |key| (CustomModule::Adapter(name), key))
1553        });
1554        for (for_module, key) in main_module_keys.chain(adapter_keys) {
1555            let id = match &world.exports[key] {
1556                WorldItem::Interface { id, .. } => *id,
1557                WorldItem::Type { .. } => unreachable!(),
1558                WorldItem::Function(_) => continue,
1559            };
1560
1561            for ty in resolve.interfaces[id].types.values() {
1562                let def = &resolve.types[*ty];
1563                match &def.kind {
1564                    // Declare exported resources specially as they generally
1565                    // need special treatment for later handling exports and
1566                    // such.
1567                    TypeDefKind::Resource => {
1568                        // Load the destructor, previously detected in module
1569                        // validation, if one is present.
1570                        let exports = self.info.exports_for(for_module);
1571                        let dtor = exports.resource_dtor(*ty).map(|name| {
1572                            let shim = &shims.shims[&ShimKind::ResourceDtor {
1573                                module: for_module,
1574                                export: name,
1575                            }];
1576                            let index = self.shim_instance_index.unwrap();
1577                            self.core_alias_export(
1578                                Some(&shim.debug_name),
1579                                index,
1580                                &shim.name,
1581                                ExportKind::Func,
1582                            )
1583                        });
1584
1585                        // Declare the resource with this destructor and register it in
1586                        // our internal map. This should be the first and only time this
1587                        // type is inserted into this map.
1588                        let resource_idx = self.component.type_resource(
1589                            Some(def.name.as_ref().unwrap()),
1590                            ValType::I32,
1591                            dtor,
1592                        );
1593                        let prev = self
1594                            .type_encoding_maps
1595                            .id_to_index
1596                            .insert(*ty, resource_idx);
1597                        assert!(prev.is_none());
1598                    }
1599                    _other => {
1600                        self.root_export_type_encoder(Some(id))
1601                            .encode_valtype(resolve, &Type::Id(*ty))?;
1602                    }
1603                }
1604            }
1605        }
1606        Ok(())
1607    }
1608
1609    /// Helper to instantiate the main module and record various results of its
1610    /// instantiation within `self`.
1611    fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1612        assert!(self.instance_index.is_none());
1613
1614        let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1615
1616        if let Some(memory) = self.info.info.exports.memory() {
1617            self.memory_index = Some(self.core_alias_export(
1618                Some("memory"),
1619                instance_index,
1620                memory,
1621                ExportKind::Memory,
1622            ));
1623        }
1624
1625        self.instance_index = Some(instance_index);
1626        Ok(())
1627    }
1628
1629    /// This function will instantiate the specified adapter module, which may
1630    /// depend on previously-instantiated modules.
1631    fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1632        let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1633        self.adapter_instances.insert(name, instance);
1634        Ok(())
1635    }
1636
1637    /// Generic helper to instantiate a module.
1638    ///
1639    /// The `for_module` provided will have all of its imports satisfied from
1640    /// either previous instantiations or the `shims` module present. This
1641    /// iterates over the metadata produced during validation to determine what
1642    /// hooks up to what import.
1643    fn instantiate_core_module(
1644        &mut self,
1645        shims: &Shims,
1646        for_module: CustomModule<'_>,
1647    ) -> Result<u32> {
1648        let module = self.module_for(for_module);
1649
1650        let mut args = Vec::new();
1651        for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1652            match instance {
1653                // For import modules that are a "bag of names" iterate over
1654                // each name and materialize it into this component with the
1655                // `materialize_import` helper. This is then all bottled up into
1656                // a bag-of-exports instance which is then used for
1657                // instantiation.
1658                ImportInstance::Names(names) => {
1659                    let mut exports = Vec::new();
1660                    for (name, import) in names {
1661                        log::trace!(
1662                            "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1663                        );
1664                        let (kind, index) = self
1665                            .materialize_import(&shims, for_module, import)
1666                            .with_context(|| {
1667                                format!("failed to satisfy import `{core_wasm_name}::{name}`")
1668                            })?;
1669                        exports.push((name.as_str(), kind, index));
1670                    }
1671                    let index = self
1672                        .component
1673                        .core_instantiate_exports(Some(core_wasm_name), exports);
1674                    args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1675                }
1676
1677                // Some imports are entire instances, so use the instance for
1678                // the module identifier as the import.
1679                ImportInstance::Whole(which) => {
1680                    let instance = self.instance_for(which.to_custom_module());
1681                    args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1682                }
1683            }
1684        }
1685
1686        // And with all arguments prepared now, instantiate the module.
1687        Ok(self
1688            .component
1689            .core_instantiate(Some(for_module.debug_name()), module, args))
1690    }
1691
1692    /// Helper function to materialize an import into a core module within the
1693    /// component being built.
1694    ///
1695    /// This function is called for individual imports and uses the results of
1696    /// validation, notably the `Import` type, to determine what WIT-level or
1697    /// component-level construct is being hooked up.
1698    fn materialize_import(
1699        &mut self,
1700        shims: &Shims<'_>,
1701        for_module: CustomModule<'_>,
1702        import: &'a Import,
1703    ) -> Result<(ExportKind, u32)> {
1704        let resolve = &self.info.encoder.metadata.resolve;
1705        match import {
1706            // Main module dependencies on an adapter in use are done with an
1707            // indirection here, so load the shim function and use that.
1708            Import::AdapterExport {
1709                adapter,
1710                func,
1711                ty: _,
1712            } => {
1713                assert!(self.info.encoder.adapters.contains_key(adapter));
1714                Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1715            }
1716
1717            // Adapters might use the main module's memory, in which case it
1718            // should have been previously instantiated.
1719            Import::MainModuleMemory => {
1720                let index = self
1721                    .memory_index
1722                    .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1723                Ok((ExportKind::Memory, index))
1724            }
1725
1726            // Grab-bag of "this adapter wants this thing from the main module".
1727            Import::MainModuleExport { name, kind } => {
1728                let instance = self.instance_index.unwrap();
1729                let index = self.core_alias_export(Some(name), instance, name, *kind);
1730                Ok((*kind, index))
1731            }
1732
1733            // A similar grab-bag to above but with a slightly different
1734            // structure. Should probably refactor to make these two the same in
1735            // the future.
1736            Import::Item(item) => {
1737                let instance = self.instance_for(item.which.to_custom_module());
1738                let index =
1739                    self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1740                Ok((item.kind, index))
1741            }
1742
1743            // Resource intrinsics related to exported resources. Despite being
1744            // an exported resource the component still provides necessary
1745            // intrinsics for manipulating resource state. These are all
1746            // handled here using the resource types created during
1747            // `declare_types_for_imported_intrinsics` above.
1748            Import::ExportedResourceDrop(_key, id) => {
1749                let index = self
1750                    .component
1751                    .resource_drop(self.type_encoding_maps.id_to_index[id]);
1752                Ok((ExportKind::Func, index))
1753            }
1754            Import::ExportedResourceRep(_key, id) => {
1755                let index = self
1756                    .component
1757                    .resource_rep(self.type_encoding_maps.id_to_index[id]);
1758                Ok((ExportKind::Func, index))
1759            }
1760            Import::ExportedResourceNew(_key, id) => {
1761                let index = self
1762                    .component
1763                    .resource_new(self.type_encoding_maps.id_to_index[id]);
1764                Ok((ExportKind::Func, index))
1765            }
1766
1767            // And finally here at the end these cases are going to all fall
1768            // through to the code below. This is where these are connected to a
1769            // WIT `ImportedInterface` one way or another with the name that was
1770            // detected during validation.
1771            Import::ImportedResourceDrop(key, iface, id) => {
1772                let ty = &resolve.types[*id];
1773                let name = ty.name.as_ref().unwrap();
1774                self.materialize_wit_import(
1775                    shims,
1776                    for_module,
1777                    iface.map(|_| resolve.name_world_key(key)),
1778                    &format!("{name}_drop"),
1779                    key,
1780                    AbiVariant::GuestImport,
1781                )
1782            }
1783            Import::ExportedTaskReturn(key, interface, func) => {
1784                let (options, _sig) = task_return_options_and_type(resolve, func);
1785                let result_ty = func.result;
1786                if options.is_empty() {
1787                    // Note that an "import type encoder" is used here despite
1788                    // this being for an exported function if the `interface`
1789                    // is none, meaning that this is for a top-level world
1790                    // function. In that situation all types that can be
1791                    // referred to are imported, not exported.
1792                    let mut encoder = if interface.is_none() {
1793                        self.root_import_type_encoder(*interface)
1794                    } else {
1795                        self.root_export_type_encoder(*interface)
1796                    };
1797
1798                    let result = match result_ty.as_ref() {
1799                        Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1800                        None => None,
1801                    };
1802                    let index = self.component.task_return(result, []);
1803                    Ok((ExportKind::Func, index))
1804                } else {
1805                    let metadata = &self.info.module_metadata_for(for_module);
1806                    let encoding = metadata
1807                        .export_encodings
1808                        .get(resolve, key, &func.name)
1809                        .unwrap();
1810                    Ok(self.materialize_shim_import(
1811                        shims,
1812                        &ShimKind::TaskReturn {
1813                            for_module,
1814                            interface: *interface,
1815                            func: &func.name,
1816                            result: result_ty,
1817                            encoding,
1818                        },
1819                    ))
1820                }
1821            }
1822            Import::BackpressureInc => {
1823                let index = self.component.backpressure_inc();
1824                Ok((ExportKind::Func, index))
1825            }
1826            Import::BackpressureDec => {
1827                let index = self.component.backpressure_dec();
1828                Ok((ExportKind::Func, index))
1829            }
1830            Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1831                shims,
1832                &ShimKind::WaitableSetWait {
1833                    cancellable: *cancellable,
1834                },
1835            )),
1836            Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1837                shims,
1838                &ShimKind::WaitableSetPoll {
1839                    cancellable: *cancellable,
1840                },
1841            )),
1842            Import::ThreadYield { cancellable } => {
1843                let index = self.component.thread_yield(*cancellable);
1844                Ok((ExportKind::Func, index))
1845            }
1846            Import::SubtaskDrop => {
1847                let index = self.component.subtask_drop();
1848                Ok((ExportKind::Func, index))
1849            }
1850            Import::SubtaskCancel { async_ } => {
1851                let index = self.component.subtask_cancel(*async_);
1852                Ok((ExportKind::Func, index))
1853            }
1854            Import::StreamNew(info) => {
1855                let ty = self.payload_type_index(info)?;
1856                let index = self.component.stream_new(ty);
1857                Ok((ExportKind::Func, index))
1858            }
1859            Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1860                shims,
1861                for_module,
1862                info,
1863                PayloadFuncKind::StreamRead,
1864            )),
1865            Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1866                shims,
1867                for_module,
1868                info,
1869                PayloadFuncKind::StreamWrite,
1870            )),
1871            Import::StreamCancelRead { info, async_ } => {
1872                let ty = self.payload_type_index(info)?;
1873                let index = self.component.stream_cancel_read(ty, *async_);
1874                Ok((ExportKind::Func, index))
1875            }
1876            Import::StreamCancelWrite { info, async_ } => {
1877                let ty = self.payload_type_index(info)?;
1878                let index = self.component.stream_cancel_write(ty, *async_);
1879                Ok((ExportKind::Func, index))
1880            }
1881            Import::StreamDropReadable(info) => {
1882                let type_index = self.payload_type_index(info)?;
1883                let index = self.component.stream_drop_readable(type_index);
1884                Ok((ExportKind::Func, index))
1885            }
1886            Import::StreamDropWritable(info) => {
1887                let type_index = self.payload_type_index(info)?;
1888                let index = self.component.stream_drop_writable(type_index);
1889                Ok((ExportKind::Func, index))
1890            }
1891            Import::FutureNew(info) => {
1892                let ty = self.payload_type_index(info)?;
1893                let index = self.component.future_new(ty);
1894                Ok((ExportKind::Func, index))
1895            }
1896            Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1897                shims,
1898                for_module,
1899                info,
1900                PayloadFuncKind::FutureRead,
1901            )),
1902            Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1903                shims,
1904                for_module,
1905                info,
1906                PayloadFuncKind::FutureWrite,
1907            )),
1908            Import::FutureCancelRead { info, async_ } => {
1909                let ty = self.payload_type_index(info)?;
1910                let index = self.component.future_cancel_read(ty, *async_);
1911                Ok((ExportKind::Func, index))
1912            }
1913            Import::FutureCancelWrite { info, async_ } => {
1914                let ty = self.payload_type_index(info)?;
1915                let index = self.component.future_cancel_write(ty, *async_);
1916                Ok((ExportKind::Func, index))
1917            }
1918            Import::FutureDropReadable(info) => {
1919                let type_index = self.payload_type_index(info)?;
1920                let index = self.component.future_drop_readable(type_index);
1921                Ok((ExportKind::Func, index))
1922            }
1923            Import::FutureDropWritable(info) => {
1924                let type_index = self.payload_type_index(info)?;
1925                let index = self.component.future_drop_writable(type_index);
1926                Ok((ExportKind::Func, index))
1927            }
1928            Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1929                shims,
1930                &ShimKind::ErrorContextNew {
1931                    encoding: *encoding,
1932                },
1933            )),
1934            Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1935                shims,
1936                &ShimKind::ErrorContextDebugMessage {
1937                    for_module,
1938                    encoding: *encoding,
1939                },
1940            )),
1941            Import::ErrorContextDrop => {
1942                let index = self.component.error_context_drop();
1943                Ok((ExportKind::Func, index))
1944            }
1945            Import::WorldFunc(key, name, abi) => {
1946                self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1947            }
1948            Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1949                shims,
1950                for_module,
1951                Some(resolve.name_world_key(key)),
1952                name,
1953                key,
1954                *abi,
1955            ),
1956
1957            Import::WaitableSetNew => {
1958                let index = self.component.waitable_set_new();
1959                Ok((ExportKind::Func, index))
1960            }
1961            Import::WaitableSetDrop => {
1962                let index = self.component.waitable_set_drop();
1963                Ok((ExportKind::Func, index))
1964            }
1965            Import::WaitableJoin => {
1966                let index = self.component.waitable_join();
1967                Ok((ExportKind::Func, index))
1968            }
1969            Import::ContextGet { ty, slot } => {
1970                let index = self.component.context_get((*ty).try_into()?, *slot);
1971                Ok((ExportKind::Func, index))
1972            }
1973            Import::ContextSet { ty, slot } => {
1974                let index = self.component.context_set((*ty).try_into()?, *slot);
1975                Ok((ExportKind::Func, index))
1976            }
1977            Import::ExportedTaskCancel => {
1978                let index = self.component.task_cancel();
1979                Ok((ExportKind::Func, index))
1980            }
1981            Import::ThreadIndex => {
1982                let index = self.component.thread_index();
1983                Ok((ExportKind::Func, index))
1984            }
1985            Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
1986                shims,
1987                &ShimKind::ThreadNewIndirect {
1988                    for_module,
1989                    // This is fixed for now
1990                    func_ty: FuncType::new([ValType::I32], []),
1991                },
1992            )),
1993            Import::ThreadSuspendToSuspended { cancellable } => {
1994                let index = self.component.thread_suspend_to_suspended(*cancellable);
1995                Ok((ExportKind::Func, index))
1996            }
1997            Import::ThreadSuspend { cancellable } => {
1998                let index = self.component.thread_suspend(*cancellable);
1999                Ok((ExportKind::Func, index))
2000            }
2001            Import::ThreadSuspendTo { cancellable } => {
2002                let index = self.component.thread_suspend_to(*cancellable);
2003                Ok((ExportKind::Func, index))
2004            }
2005            Import::ThreadUnsuspend => {
2006                let index = self.component.thread_unsuspend();
2007                Ok((ExportKind::Func, index))
2008            }
2009            Import::ThreadYieldToSuspended { cancellable } => {
2010                let index = self.component.thread_yield_to_suspended(*cancellable);
2011                Ok((ExportKind::Func, index))
2012            }
2013        }
2014    }
2015
2016    /// Helper for `materialize_import` above for materializing functions that
2017    /// are part of the "shim module" generated.
2018    fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2019        let index = self.core_alias_export(
2020            Some(&shims.shims[kind].debug_name),
2021            self.shim_instance_index
2022                .expect("shim should be instantiated"),
2023            &shims.shims[kind].name,
2024            ExportKind::Func,
2025        );
2026        (ExportKind::Func, index)
2027    }
2028
2029    /// Helper for `materialize_import` above for generating imports for
2030    /// future/stream read/write intrinsics.
2031    fn materialize_payload_import(
2032        &mut self,
2033        shims: &Shims<'_>,
2034        for_module: CustomModule<'_>,
2035        info: &PayloadInfo,
2036        kind: PayloadFuncKind,
2037    ) -> (ExportKind, u32) {
2038        self.materialize_shim_import(
2039            shims,
2040            &ShimKind::PayloadFunc {
2041                for_module,
2042                info,
2043                kind,
2044            },
2045        )
2046    }
2047
2048    /// Helper for `materialize_import` above which specifically operates on
2049    /// WIT-level functions identified by `interface_key`, `name`, and `abi`.
2050    fn materialize_wit_import(
2051        &mut self,
2052        shims: &Shims<'_>,
2053        for_module: CustomModule<'_>,
2054        interface_key: Option<String>,
2055        name: &String,
2056        key: &WorldKey,
2057        abi: AbiVariant,
2058    ) -> Result<(ExportKind, u32)> {
2059        let resolve = &self.info.encoder.metadata.resolve;
2060        let import = &self.info.import_map[&interface_key];
2061        let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2062        let metadata = self.info.module_metadata_for(for_module);
2063
2064        let index = match lowering {
2065            // All direct lowerings can be `canon lower`'d here immediately
2066            // and passed as arguments.
2067            Lowering::Direct => {
2068                let func_index = match &import.interface {
2069                    Some(interface) => {
2070                        let instance_index = self.instances[interface];
2071                        self.component
2072                            .alias_export(instance_index, name, ComponentExportKind::Func)
2073                    }
2074                    None => self.imported_funcs[name],
2075                };
2076                self.component.lower_func(
2077                    Some(name),
2078                    func_index,
2079                    if let AbiVariant::GuestImportAsync = abi {
2080                        vec![CanonicalOption::Async]
2081                    } else {
2082                        Vec::new()
2083                    },
2084                )
2085            }
2086
2087            // Indirect lowerings come from the shim that was previously
2088            // created, so the specific export is loaded here and used as an
2089            // import.
2090            Lowering::Indirect { .. } => {
2091                let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2092                return Ok(self.materialize_shim_import(
2093                    shims,
2094                    &ShimKind::IndirectLowering {
2095                        interface: interface_key,
2096                        index,
2097                        realloc: for_module,
2098                        encoding,
2099                    },
2100                ));
2101            }
2102
2103            // A "resource drop" intrinsic only needs to find the index of the
2104            // resource type itself and then the intrinsic is declared.
2105            Lowering::ResourceDrop(id) => {
2106                let resource_idx = self.lookup_resource_index(*id);
2107                self.component.resource_drop(resource_idx)
2108            }
2109        };
2110        Ok((ExportKind::Func, index))
2111    }
2112
2113    /// Generates component bits that are responsible for executing
2114    /// `_initialize`, if found, in the original component.
2115    ///
2116    /// The `_initialize` function was a part of WASIp1 where it generally is
2117    /// intended to run after imports and memory and such are all "hooked up"
2118    /// and performs other various initialization tasks. This is additionally
2119    /// specified in https://github.com/WebAssembly/component-model/pull/378
2120    /// to be part of the component model lowerings as well.
2121    ///
2122    /// This implements this functionality by encoding a core module that
2123    /// imports a function and then registers a `start` section with that
2124    /// imported function. This is all encoded after the
2125    /// imports/lowerings/tables/etc are all filled in above meaning that this
2126    /// is the last piece to run. That means that when this is running
2127    /// everything should be hooked up for all imported functions to work.
2128    ///
2129    /// Note that at this time `_initialize` is only detected in the "main
2130    /// module", not adapters/libraries.
2131    fn encode_initialize_with_start(&mut self) -> Result<()> {
2132        let initialize = match self.info.info.exports.initialize() {
2133            Some(name) => name,
2134            // If this core module didn't have `_initialize` or similar, then
2135            // there's nothing to do here.
2136            None => return Ok(()),
2137        };
2138        let initialize_index = self.core_alias_export(
2139            Some("start"),
2140            self.instance_index.unwrap(),
2141            initialize,
2142            ExportKind::Func,
2143        );
2144        let mut shim = Module::default();
2145        let mut section = TypeSection::new();
2146        section.ty().function([], []);
2147        shim.section(&section);
2148        let mut section = ImportSection::new();
2149        section.import("", "", EntityType::Function(0));
2150        shim.section(&section);
2151        shim.section(&StartSection { function_index: 0 });
2152
2153        // Declare the core module within the component, create a dummy core
2154        // instance with one export of our `_initialize` function, and then use
2155        // that to instantiate the module we emit to run the `start` function in
2156        // core wasm to run `_initialize`.
2157        let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2158        let shim_args_instance_index = self.component.core_instantiate_exports(
2159            Some("start-shim-args"),
2160            [("", ExportKind::Func, initialize_index)],
2161        );
2162        self.component.core_instantiate(
2163            Some("start-shim-instance"),
2164            shim_module_index,
2165            [("", ModuleArg::Instance(shim_args_instance_index))],
2166        );
2167        Ok(())
2168    }
2169
2170    /// Convenience function to go from `CustomModule` to the instance index
2171    /// corresponding to what that points to.
2172    fn instance_for(&self, module: CustomModule) -> u32 {
2173        match module {
2174            CustomModule::Main => self.instance_index.expect("instantiated by now"),
2175            CustomModule::Adapter(name) => self.adapter_instances[name],
2176        }
2177    }
2178
2179    /// Convenience function to go from `CustomModule` to the module index
2180    /// corresponding to what that points to.
2181    fn module_for(&self, module: CustomModule) -> u32 {
2182        match module {
2183            CustomModule::Main => self.module_index.unwrap(),
2184            CustomModule::Adapter(name) => self.adapter_modules[name],
2185        }
2186    }
2187
2188    /// Convenience function which caches aliases created so repeated calls to
2189    /// this function will all return the same index.
2190    fn core_alias_export(
2191        &mut self,
2192        debug_name: Option<&str>,
2193        instance: u32,
2194        name: &str,
2195        kind: ExportKind,
2196    ) -> u32 {
2197        *self
2198            .aliased_core_items
2199            .entry((instance, name.to_string()))
2200            .or_insert_with(|| {
2201                self.component
2202                    .core_alias_export(debug_name, instance, name, kind)
2203            })
2204    }
2205
2206    /// Modules may define `__wasm_init_(async_)task` functions that must be called
2207    /// at the start of every exported function to set up the stack pointer and
2208    /// thread-local storage. To achieve this, we create a wrapper module called
2209    /// `task-init-wrappers` that imports the original exports and the
2210    /// task initialization functions, and defines wrapper functions that call
2211    /// the relevant task initialization function before delegating to the original export.
2212    /// We then instantiate this wrapper module and use its exports as the final
2213    /// exports of the component. If we don't find a `__wasm_init_task` export,
2214    /// we elide the wrapper module entirely.
2215    fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2216        let instance_index = self.instance_index.unwrap();
2217        let resolve = &self.info.encoder.metadata.resolve;
2218        let world = &resolve.worlds[self.info.encoder.metadata.world];
2219        let exports = self.info.exports_for(CustomModule::Main);
2220
2221        let wasm_init_task_export = exports.wasm_init_task();
2222        let wasm_init_async_task_export = exports.wasm_init_async_task();
2223        if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2224            // __wasm_init_(async_)task was not exported by the main module,
2225            // so no wrappers are needed.
2226            return Ok(());
2227        }
2228        let wasm_init_task = wasm_init_task_export.unwrap();
2229        let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2230
2231        // Collect the exports that we will need to wrap, alongside information
2232        // that we'll need to build the wrappers.
2233        let funcs_to_wrap: Vec<_> = exports
2234            .iter()
2235            .flat_map(|(core_name, export)| match export {
2236                Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2237                    WorldItem::Function(f) => Some((core_name, f, abi)),
2238                    _ => None,
2239                },
2240                Export::InterfaceFunc(_, id, func_name, abi) => {
2241                    let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2242                    Some((core_name, func, abi))
2243                }
2244                _ => None,
2245            })
2246            .collect();
2247
2248        if funcs_to_wrap.is_empty() {
2249            // No exports, so no wrappers are needed.
2250            return Ok(());
2251        }
2252
2253        // Now we build the wrapper module
2254        let mut types = TypeSection::new();
2255        let mut imports = ImportSection::new();
2256        let mut functions = FunctionSection::new();
2257        let mut exports_section = ExportSection::new();
2258        let mut code = CodeSection::new();
2259
2260        // Type for __wasm_init_(async_)task: () -> ()
2261        types.ty().function([], []);
2262        let wasm_init_task_type_idx = 0;
2263
2264        // Import __wasm_init_task and __wasm_init_async_task into the wrapper module
2265        imports.import(
2266            "",
2267            wasm_init_task,
2268            EntityType::Function(wasm_init_task_type_idx),
2269        );
2270        imports.import(
2271            "",
2272            wasm_init_async_task,
2273            EntityType::Function(wasm_init_task_type_idx),
2274        );
2275        let wasm_init_task_func_idx = 0u32;
2276        let wasm_init_async_task_func_idx = 1u32;
2277
2278        let mut type_indices = HashMap::new();
2279        let mut next_type_idx = 1u32;
2280        let mut next_func_idx = 2u32;
2281
2282        // First pass: create all types and import all original functions
2283        struct FuncInfo<'a> {
2284            name: &'a str,
2285            type_idx: u32,
2286            orig_func_idx: u32,
2287            is_async: bool,
2288            n_params: usize,
2289        }
2290        let mut func_info = Vec::new();
2291        for &(name, func, abi) in funcs_to_wrap.iter() {
2292            let sig = resolve.wasm_signature(*abi, func);
2293            let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2294                let idx = next_type_idx;
2295                types.ty().function(
2296                    sig.params.iter().map(to_val_type),
2297                    sig.results.iter().map(to_val_type),
2298                );
2299                next_type_idx += 1;
2300                idx
2301            });
2302
2303            imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2304            let orig_func_idx = next_func_idx;
2305            next_func_idx += 1;
2306
2307            func_info.push(FuncInfo {
2308                name,
2309                type_idx,
2310                orig_func_idx,
2311                is_async: abi.is_async(),
2312                n_params: sig.params.len(),
2313            });
2314        }
2315
2316        // Second pass: define wrapper functions
2317        for info in func_info.iter() {
2318            let wrapper_func_idx = next_func_idx;
2319            functions.function(info.type_idx);
2320
2321            let mut func = wasm_encoder::Function::new([]);
2322            if info.is_async {
2323                func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2324            } else {
2325                func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2326            }
2327            for i in 0..info.n_params as u32 {
2328                func.instruction(&Instruction::LocalGet(i));
2329            }
2330            func.instruction(&Instruction::Call(info.orig_func_idx));
2331            func.instruction(&Instruction::End);
2332            code.function(&func);
2333
2334            exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2335            next_func_idx += 1;
2336        }
2337
2338        let mut wrapper_module = Module::new();
2339        wrapper_module.section(&types);
2340        wrapper_module.section(&imports);
2341        wrapper_module.section(&functions);
2342        wrapper_module.section(&exports_section);
2343        wrapper_module.section(&code);
2344
2345        let wrapper_module_idx = self
2346            .component
2347            .core_module(Some("init-task-wrappers"), &wrapper_module);
2348
2349        // Prepare imports for instantiating the wrapper module
2350        let mut wrapper_imports = Vec::new();
2351        let init_idx = self.core_alias_export(
2352            Some(wasm_init_task),
2353            instance_index,
2354            wasm_init_task,
2355            ExportKind::Func,
2356        );
2357        let init_async_idx = self.core_alias_export(
2358            Some(wasm_init_async_task),
2359            instance_index,
2360            wasm_init_async_task,
2361            ExportKind::Func,
2362        );
2363        wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2364        wrapper_imports.push((
2365            wasm_init_async_task.into(),
2366            ExportKind::Func,
2367            init_async_idx,
2368        ));
2369
2370        // Import all original exports to be wrapped
2371        for (name, func, _) in &funcs_to_wrap {
2372            let orig_idx =
2373                self.core_alias_export(Some(name), instance_index, name, ExportKind::Func);
2374            wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2375        }
2376
2377        let wrapper_args_idx = self.component.core_instantiate_exports(
2378            Some("init-task-wrappers-args"),
2379            wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2380        );
2381
2382        let wrapper_instance = self.component.core_instantiate(
2383            Some("init-task-wrappers-instance"),
2384            wrapper_module_idx,
2385            [("", ModuleArg::Instance(wrapper_args_idx))],
2386        );
2387
2388        // Map original names to wrapper indices
2389        for (name, _, _) in funcs_to_wrap {
2390            let wrapper_idx =
2391                self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2392            self.export_task_initialization_wrappers
2393                .insert(name.into(), wrapper_idx);
2394        }
2395
2396        Ok(())
2397    }
2398}
2399
2400/// A list of "shims" which start out during the component instantiation process
2401/// as functions which immediately trap due to a `call_indirect`-to-`null` but
2402/// will get filled in by the time the component instantiation process
2403/// completes.
2404///
2405/// Shims currently include:
2406///
2407/// * "Indirect functions" lowered from imported instances where the lowering
2408///   requires an item exported from the main module. These are indirect due to
2409///   the circular dependency between the module needing an import and the
2410///   import needing the module.
2411///
2412/// * Adapter modules which convert from a historical ABI to the component
2413///   model's ABI (e.g. wasi preview1 to preview2) get a shim since the adapters
2414///   are currently indicated as always requiring the memory of the main module.
2415///
2416/// This structure is created by `encode_shim_instantiation`.
2417#[derive(Default)]
2418struct Shims<'a> {
2419    /// The list of all shims that a module will require.
2420    shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2421}
2422
2423struct Shim<'a> {
2424    /// Canonical ABI options required by this shim, used during `canon lower`
2425    /// operations.
2426    options: RequiredOptions,
2427
2428    /// The name, in the shim instance, of this shim.
2429    ///
2430    /// Currently this is `"0"`, `"1"`, ...
2431    name: String,
2432
2433    /// A human-readable debugging name for this shim, used in a core wasm
2434    /// `name` section.
2435    debug_name: String,
2436
2437    /// Precise information about what this shim is a lowering of.
2438    kind: ShimKind<'a>,
2439
2440    /// Wasm type of this shim.
2441    sig: WasmSignature,
2442}
2443
2444/// Which variation of `{stream|future}.{read|write}` we're emitting for a
2445/// `ShimKind::PayloadFunc`.
2446#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2447enum PayloadFuncKind {
2448    FutureWrite,
2449    FutureRead,
2450    StreamWrite,
2451    StreamRead,
2452}
2453
2454#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2455enum ShimKind<'a> {
2456    /// This shim is a late indirect lowering of an imported function in a
2457    /// component which is only possible after prior core wasm modules are
2458    /// instantiated so their memories and functions are available.
2459    IndirectLowering {
2460        /// The name of the interface that's being lowered.
2461        interface: Option<String>,
2462        /// The index within the `lowerings` array of the function being lowered.
2463        index: usize,
2464        /// Which instance to pull the `realloc` function from, if necessary.
2465        realloc: CustomModule<'a>,
2466        /// The string encoding that this lowering is going to use.
2467        encoding: StringEncoding,
2468    },
2469    /// This shim is a core wasm function defined in an adapter module but isn't
2470    /// available until the adapter module is itself instantiated.
2471    Adapter {
2472        /// The name of the adapter module this shim comes from.
2473        adapter: &'a str,
2474        /// The name of the export in the adapter module this shim points to.
2475        func: &'a str,
2476    },
2477    /// A shim used as the destructor for a resource which allows defining the
2478    /// resource before the core module being instantiated.
2479    ResourceDtor {
2480        /// Which instance to pull the destructor function from.
2481        module: CustomModule<'a>,
2482        /// The exported function name of this destructor in the core module.
2483        export: &'a str,
2484    },
2485    /// A shim used for a `{stream|future}.{read|write}` built-in function,
2486    /// which must refer to the core module instance's memory from/to which
2487    /// payload values must be lifted/lowered.
2488    PayloadFunc {
2489        /// Which instance to pull the `realloc` function and string encoding
2490        /// from, if necessary.
2491        for_module: CustomModule<'a>,
2492        /// Additional information regarding the function where this `stream` or
2493        /// `future` type appeared, which we use in combination with
2494        /// `for_module` to determine which `realloc` and string encoding to
2495        /// use, as well as which type to specify when emitting the built-in.
2496        info: &'a PayloadInfo,
2497        /// Which variation of `{stream|future}.{read|write}` we're emitting.
2498        kind: PayloadFuncKind,
2499    },
2500    /// A shim used for the `waitable-set.wait` built-in function, which must
2501    /// refer to the core module instance's memory to which results will be
2502    /// written.
2503    WaitableSetWait { cancellable: bool },
2504    /// A shim used for the `waitable-set.poll` built-in function, which must
2505    /// refer to the core module instance's memory to which results will be
2506    /// written.
2507    WaitableSetPoll { cancellable: bool },
2508    /// Shim for `task.return` to handle a reference to a `memory` which may
2509    TaskReturn {
2510        /// The interface (optional) that owns `func` below. If `None` then it's
2511        /// a world export.
2512        interface: Option<InterfaceId>,
2513        /// The function that this `task.return` is returning for, owned
2514        /// within `interface` above.
2515        func: &'a str,
2516        /// The WIT type that `func` returns.
2517        result: Option<Type>,
2518        /// Which instance to pull the `realloc` function from, if necessary.
2519        for_module: CustomModule<'a>,
2520        /// String encoding to use in the ABI options.
2521        encoding: StringEncoding,
2522    },
2523    /// A shim used for the `error-context.new` built-in function, which must
2524    /// refer to the core module instance's memory from which the debug message
2525    /// will be read.
2526    ErrorContextNew {
2527        /// String encoding to use when lifting the debug message.
2528        encoding: StringEncoding,
2529    },
2530    /// A shim used for the `error-context.debug-message` built-in function,
2531    /// which must refer to the core module instance's memory to which results
2532    /// will be written.
2533    ErrorContextDebugMessage {
2534        /// Which instance to pull the `realloc` function from, if necessary.
2535        for_module: CustomModule<'a>,
2536        /// The string encoding to use when lowering the debug message.
2537        encoding: StringEncoding,
2538    },
2539    /// A shim used for the `thread.new-indirect` built-in function, which
2540    /// must refer to the core module instance's indirect function table.
2541    ThreadNewIndirect {
2542        /// Which instance to pull the function table from.
2543        for_module: CustomModule<'a>,
2544        /// The function type to use when creating the thread.
2545        func_ty: FuncType,
2546    },
2547}
2548
2549/// Indicator for which module is being used for a lowering or where options
2550/// like `realloc` are drawn from.
2551///
2552/// This is necessary for situations such as an imported function being lowered
2553/// into the main module and additionally into an adapter module. For example an
2554/// adapter might adapt from preview1 to preview2 for the standard library of a
2555/// programming language but the main module's custom application code may also
2556/// explicitly import from preview2. These two different lowerings of a preview2
2557/// function are parameterized by this enumeration.
2558#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2559enum CustomModule<'a> {
2560    /// This points to the "main module" which is generally the "output of LLVM"
2561    /// or what a user wrote.
2562    Main,
2563    /// This is selecting an adapter module, identified by name here, where
2564    /// something is being lowered into.
2565    Adapter(&'a str),
2566}
2567
2568impl<'a> CustomModule<'a> {
2569    fn debug_name(&self) -> &'a str {
2570        match self {
2571            CustomModule::Main => "main",
2572            CustomModule::Adapter(s) => s,
2573        }
2574    }
2575}
2576
2577impl<'a> Shims<'a> {
2578    /// Adds all shims necessary for the instantiation of `for_module`.
2579    ///
2580    /// This function will iterate over all the imports required by this module
2581    /// and for those that require a shim they're registered here.
2582    fn append_indirect(
2583        &mut self,
2584        world: &'a ComponentWorld<'a>,
2585        for_module: CustomModule<'a>,
2586    ) -> Result<()> {
2587        let module_imports = world.imports_for(for_module);
2588        let module_exports = world.exports_for(for_module);
2589        let resolve = &world.encoder.metadata.resolve;
2590
2591        for (module, field, import) in module_imports.imports() {
2592            match import {
2593                // These imports don't require shims, they can be satisfied
2594                // as-needed when required.
2595                Import::ImportedResourceDrop(..)
2596                | Import::MainModuleMemory
2597                | Import::MainModuleExport { .. }
2598                | Import::Item(_)
2599                | Import::ExportedResourceDrop(..)
2600                | Import::ExportedResourceRep(..)
2601                | Import::ExportedResourceNew(..)
2602                | Import::ExportedTaskCancel
2603                | Import::ErrorContextDrop
2604                | Import::BackpressureInc
2605                | Import::BackpressureDec
2606                | Import::ThreadYield { .. }
2607                | Import::SubtaskDrop
2608                | Import::SubtaskCancel { .. }
2609                | Import::FutureNew(..)
2610                | Import::StreamNew(..)
2611                | Import::FutureCancelRead { .. }
2612                | Import::FutureCancelWrite { .. }
2613                | Import::FutureDropWritable { .. }
2614                | Import::FutureDropReadable { .. }
2615                | Import::StreamCancelRead { .. }
2616                | Import::StreamCancelWrite { .. }
2617                | Import::StreamDropWritable { .. }
2618                | Import::StreamDropReadable { .. }
2619                | Import::WaitableSetNew
2620                | Import::WaitableSetDrop
2621                | Import::WaitableJoin
2622                | Import::ContextGet { .. }
2623                | Import::ContextSet { .. }
2624                | Import::ThreadIndex
2625                | Import::ThreadSuspendToSuspended { .. }
2626                | Import::ThreadSuspend { .. }
2627                | Import::ThreadSuspendTo { .. }
2628                | Import::ThreadUnsuspend
2629                | Import::ThreadYieldToSuspended { .. } => {}
2630
2631                // If `task.return` needs to be indirect then generate a shim
2632                // for it, otherwise skip the shim and let it get materialized
2633                // naturally later.
2634                Import::ExportedTaskReturn(key, interface, func) => {
2635                    let (options, sig) = task_return_options_and_type(resolve, func);
2636                    if options.is_empty() {
2637                        continue;
2638                    }
2639                    let name = self.shims.len().to_string();
2640                    let encoding = world
2641                        .module_metadata_for(for_module)
2642                        .export_encodings
2643                        .get(resolve, key, &func.name)
2644                        .ok_or_else(|| {
2645                            anyhow::anyhow!(
2646                                "missing component metadata for export of \
2647                                `{module}::{field}`"
2648                            )
2649                        })?;
2650                    self.push(Shim {
2651                        name,
2652                        debug_name: format!("task-return-{}", func.name),
2653                        options,
2654                        kind: ShimKind::TaskReturn {
2655                            interface: *interface,
2656                            func: &func.name,
2657                            result: func.result,
2658                            for_module,
2659                            encoding,
2660                        },
2661                        sig,
2662                    });
2663                }
2664
2665                Import::FutureWrite { async_, info } => {
2666                    self.append_indirect_payload_push(
2667                        resolve,
2668                        for_module,
2669                        module,
2670                        *async_,
2671                        info,
2672                        PayloadFuncKind::FutureWrite,
2673                        vec![WasmType::I32; 2],
2674                        vec![WasmType::I32],
2675                    );
2676                }
2677                Import::FutureRead { async_, info } => {
2678                    self.append_indirect_payload_push(
2679                        resolve,
2680                        for_module,
2681                        module,
2682                        *async_,
2683                        info,
2684                        PayloadFuncKind::FutureRead,
2685                        vec![WasmType::I32; 2],
2686                        vec![WasmType::I32],
2687                    );
2688                }
2689                Import::StreamWrite { async_, info } => {
2690                    self.append_indirect_payload_push(
2691                        resolve,
2692                        for_module,
2693                        module,
2694                        *async_,
2695                        info,
2696                        PayloadFuncKind::StreamWrite,
2697                        vec![WasmType::I32; 3],
2698                        vec![WasmType::I32],
2699                    );
2700                }
2701                Import::StreamRead { async_, info } => {
2702                    self.append_indirect_payload_push(
2703                        resolve,
2704                        for_module,
2705                        module,
2706                        *async_,
2707                        info,
2708                        PayloadFuncKind::StreamRead,
2709                        vec![WasmType::I32; 3],
2710                        vec![WasmType::I32],
2711                    );
2712                }
2713
2714                Import::WaitableSetWait { cancellable } => {
2715                    let name = self.shims.len().to_string();
2716                    self.push(Shim {
2717                        name,
2718                        debug_name: "waitable-set.wait".to_string(),
2719                        options: RequiredOptions::empty(),
2720                        kind: ShimKind::WaitableSetWait {
2721                            cancellable: *cancellable,
2722                        },
2723                        sig: WasmSignature {
2724                            params: vec![WasmType::I32; 2],
2725                            results: vec![WasmType::I32],
2726                            indirect_params: false,
2727                            retptr: false,
2728                        },
2729                    });
2730                }
2731
2732                Import::WaitableSetPoll { cancellable } => {
2733                    let name = self.shims.len().to_string();
2734                    self.push(Shim {
2735                        name,
2736                        debug_name: "waitable-set.poll".to_string(),
2737                        options: RequiredOptions::empty(),
2738                        kind: ShimKind::WaitableSetPoll {
2739                            cancellable: *cancellable,
2740                        },
2741                        sig: WasmSignature {
2742                            params: vec![WasmType::I32; 2],
2743                            results: vec![WasmType::I32],
2744                            indirect_params: false,
2745                            retptr: false,
2746                        },
2747                    });
2748                }
2749
2750                Import::ErrorContextNew { encoding } => {
2751                    let name = self.shims.len().to_string();
2752                    self.push(Shim {
2753                        name,
2754                        debug_name: "error-new".to_string(),
2755                        options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2756                        kind: ShimKind::ErrorContextNew {
2757                            encoding: *encoding,
2758                        },
2759                        sig: WasmSignature {
2760                            params: vec![WasmType::I32; 2],
2761                            results: vec![WasmType::I32],
2762                            indirect_params: false,
2763                            retptr: false,
2764                        },
2765                    });
2766                }
2767
2768                Import::ErrorContextDebugMessage { encoding } => {
2769                    let name = self.shims.len().to_string();
2770                    self.push(Shim {
2771                        name,
2772                        debug_name: "error-debug-message".to_string(),
2773                        options: RequiredOptions::MEMORY
2774                            | RequiredOptions::STRING_ENCODING
2775                            | RequiredOptions::REALLOC,
2776                        kind: ShimKind::ErrorContextDebugMessage {
2777                            for_module,
2778                            encoding: *encoding,
2779                        },
2780                        sig: WasmSignature {
2781                            params: vec![WasmType::I32; 2],
2782                            results: vec![],
2783                            indirect_params: false,
2784                            retptr: false,
2785                        },
2786                    });
2787                }
2788
2789                Import::ThreadNewIndirect => {
2790                    let name = self.shims.len().to_string();
2791                    self.push(Shim {
2792                        name,
2793                        debug_name: "thread.new-indirect".to_string(),
2794                        options: RequiredOptions::empty(),
2795                        kind: ShimKind::ThreadNewIndirect {
2796                            for_module,
2797                            // This is fixed for now
2798                            func_ty: FuncType::new([ValType::I32], vec![]),
2799                        },
2800                        sig: WasmSignature {
2801                            params: vec![WasmType::I32; 2],
2802                            results: vec![WasmType::I32],
2803                            indirect_params: false,
2804                            retptr: false,
2805                        },
2806                    });
2807                }
2808
2809                // Adapter imports into the main module must got through an
2810                // indirection, so that's registered here.
2811                Import::AdapterExport { adapter, func, ty } => {
2812                    let name = self.shims.len().to_string();
2813                    log::debug!("shim {name} is adapter `{module}::{field}`");
2814                    self.push(Shim {
2815                        name,
2816                        debug_name: format!("adapt-{module}-{field}"),
2817                        // Pessimistically assume that all adapters require
2818                        // memory in one form or another. While this isn't
2819                        // technically true it's true enough for WASI.
2820                        options: RequiredOptions::MEMORY,
2821                        kind: ShimKind::Adapter { adapter, func },
2822                        sig: WasmSignature {
2823                            params: ty.params().iter().map(to_wasm_type).collect(),
2824                            results: ty.results().iter().map(to_wasm_type).collect(),
2825                            indirect_params: false,
2826                            retptr: false,
2827                        },
2828                    });
2829
2830                    fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2831                        match ty {
2832                            wasmparser::ValType::I32 => WasmType::I32,
2833                            wasmparser::ValType::I64 => WasmType::I64,
2834                            wasmparser::ValType::F32 => WasmType::F32,
2835                            wasmparser::ValType::F64 => WasmType::F64,
2836                            _ => unreachable!(),
2837                        }
2838                    }
2839                }
2840
2841                // WIT-level functions may require an indirection, so yield some
2842                // metadata out of this `match` to the loop below to figure that
2843                // out.
2844                Import::InterfaceFunc(key, _, name, abi) => {
2845                    self.append_indirect_wit_func(
2846                        world,
2847                        for_module,
2848                        module,
2849                        field,
2850                        key,
2851                        name,
2852                        Some(resolve.name_world_key(key)),
2853                        *abi,
2854                    )?;
2855                }
2856                Import::WorldFunc(key, name, abi) => {
2857                    self.append_indirect_wit_func(
2858                        world, for_module, module, field, key, name, None, *abi,
2859                    )?;
2860                }
2861            }
2862        }
2863
2864        // In addition to all the shims added for imports above this module also
2865        // requires shims for resource destructors that it exports. Resource
2866        // types are declared before the module is instantiated so the actual
2867        // destructor is registered as a shim (defined here) and it's then
2868        // filled in with the module's exports later.
2869        for (export_name, export) in module_exports.iter() {
2870            let id = match export {
2871                Export::ResourceDtor(id) => id,
2872                _ => continue,
2873            };
2874            let resource = resolve.types[*id].name.as_ref().unwrap();
2875            let name = self.shims.len().to_string();
2876            self.push(Shim {
2877                name,
2878                debug_name: format!("dtor-{resource}"),
2879                options: RequiredOptions::empty(),
2880                kind: ShimKind::ResourceDtor {
2881                    module: for_module,
2882                    export: export_name,
2883                },
2884                sig: WasmSignature {
2885                    params: vec![WasmType::I32],
2886                    results: Vec::new(),
2887                    indirect_params: false,
2888                    retptr: false,
2889                },
2890            });
2891        }
2892
2893        Ok(())
2894    }
2895
2896    /// Helper of `append_indirect` above which pushes information for
2897    /// futures/streams read/write intrinsics.
2898    fn append_indirect_payload_push(
2899        &mut self,
2900        resolve: &Resolve,
2901        for_module: CustomModule<'a>,
2902        module: &str,
2903        async_: bool,
2904        info: &'a PayloadInfo,
2905        kind: PayloadFuncKind,
2906        params: Vec<WasmType>,
2907        results: Vec<WasmType>,
2908    ) {
2909        let debug_name = format!("{module}-{}", info.name);
2910        let name = self.shims.len().to_string();
2911
2912        let payload = info.payload(resolve);
2913        let (wit_param, wit_result) = match kind {
2914            PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2915            PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2916        };
2917        self.push(Shim {
2918            name,
2919            debug_name,
2920            options: RequiredOptions::MEMORY
2921                | RequiredOptions::for_import(
2922                    resolve,
2923                    &Function {
2924                        name: String::new(),
2925                        kind: FunctionKind::Freestanding,
2926                        params: match wit_param {
2927                            Some(ty) => vec![Param {
2928                                name: "a".to_string(),
2929                                ty,
2930                                span: Default::default(),
2931                            }],
2932                            None => Vec::new(),
2933                        },
2934                        result: wit_result,
2935                        docs: Default::default(),
2936                        stability: Stability::Unknown,
2937                        span: Default::default(),
2938                    },
2939                    if async_ {
2940                        AbiVariant::GuestImportAsync
2941                    } else {
2942                        AbiVariant::GuestImport
2943                    },
2944                ),
2945            kind: ShimKind::PayloadFunc {
2946                for_module,
2947                info,
2948                kind,
2949            },
2950            sig: WasmSignature {
2951                params,
2952                results,
2953                indirect_params: false,
2954                retptr: false,
2955            },
2956        });
2957    }
2958
2959    /// Helper for `append_indirect` above which will conditionally push a shim
2960    /// for the WIT function specified by `interface_key`, `name`, and `abi`.
2961    fn append_indirect_wit_func(
2962        &mut self,
2963        world: &'a ComponentWorld<'a>,
2964        for_module: CustomModule<'a>,
2965        module: &str,
2966        field: &str,
2967        key: &WorldKey,
2968        name: &String,
2969        interface_key: Option<String>,
2970        abi: AbiVariant,
2971    ) -> Result<()> {
2972        let resolve = &world.encoder.metadata.resolve;
2973        let metadata = world.module_metadata_for(for_module);
2974        let interface = &world.import_map[&interface_key];
2975        let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
2976        let shim_name = self.shims.len().to_string();
2977        match lowering {
2978            Lowering::Direct | Lowering::ResourceDrop(_) => {}
2979
2980            Lowering::Indirect { sig, options } => {
2981                log::debug!(
2982                    "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
2983                );
2984                let encoding = metadata
2985                    .import_encodings
2986                    .get(resolve, key, name)
2987                    .ok_or_else(|| {
2988                        anyhow::anyhow!(
2989                            "missing component metadata for import of \
2990                                `{module}::{field}`"
2991                        )
2992                    })?;
2993                self.push(Shim {
2994                    name: shim_name,
2995                    debug_name: format!("indirect-{module}-{field}"),
2996                    options: *options,
2997                    kind: ShimKind::IndirectLowering {
2998                        interface: interface_key,
2999                        index,
3000                        realloc: for_module,
3001                        encoding,
3002                    },
3003                    sig: sig.clone(),
3004                });
3005            }
3006        }
3007
3008        Ok(())
3009    }
3010
3011    fn push(&mut self, shim: Shim<'a>) {
3012        // Only one shim per `ShimKind` is retained, so if it's already present
3013        // don't overwrite it. If it's not present though go ahead and insert
3014        // it.
3015        if !self.shims.contains_key(&shim.kind) {
3016            self.shims.insert(shim.kind.clone(), shim);
3017        }
3018    }
3019}
3020
3021fn task_return_options_and_type(
3022    resolve: &Resolve,
3023    func: &Function,
3024) -> (RequiredOptions, WasmSignature) {
3025    let func_tmp = Function {
3026        name: String::new(),
3027        kind: FunctionKind::Freestanding,
3028        params: match &func.result {
3029            Some(ty) => vec![Param {
3030                name: "a".to_string(),
3031                ty: *ty,
3032                span: Default::default(),
3033            }],
3034            None => Vec::new(),
3035        },
3036        result: None,
3037        docs: Default::default(),
3038        stability: Stability::Unknown,
3039        span: Default::default(),
3040    };
3041    let abi = AbiVariant::GuestImport;
3042    let mut options = RequiredOptions::for_import(resolve, func, abi);
3043    // `task.return` does not support a `realloc` canonical option.
3044    options.remove(RequiredOptions::REALLOC);
3045    let sig = resolve.wasm_signature(abi, &func_tmp);
3046    (options, sig)
3047}
3048
3049/// Alias argument to an instantiation
3050#[derive(Clone, Debug)]
3051pub struct Item {
3052    pub alias: String,
3053    pub kind: ExportKind,
3054    pub which: MainOrAdapter,
3055    pub name: String,
3056}
3057
3058/// Module argument to an instantiation
3059#[derive(Debug, PartialEq, Clone)]
3060pub enum MainOrAdapter {
3061    Main,
3062    Adapter(String),
3063}
3064
3065impl MainOrAdapter {
3066    fn to_custom_module(&self) -> CustomModule<'_> {
3067        match self {
3068            MainOrAdapter::Main => CustomModule::Main,
3069            MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3070        }
3071    }
3072}
3073
3074/// Module instantiation argument
3075#[derive(Clone)]
3076pub enum Instance {
3077    /// Module argument
3078    MainOrAdapter(MainOrAdapter),
3079
3080    /// Alias argument
3081    Items(Vec<Item>),
3082}
3083
3084/// Provides fine-grained control of how a library module is instantiated
3085/// relative to other module instances
3086#[derive(Clone)]
3087pub struct LibraryInfo {
3088    /// If true, instantiate any shims prior to this module
3089    pub instantiate_after_shims: bool,
3090
3091    /// Instantiation arguments
3092    pub arguments: Vec<(String, Instance)>,
3093}
3094
3095/// Represents an adapter or library to be instantiated as part of the component
3096pub(super) struct Adapter {
3097    /// The wasm of the module itself, with `component-type` sections stripped
3098    wasm: Vec<u8>,
3099
3100    /// The metadata for the adapter
3101    metadata: ModuleMetadata,
3102
3103    /// The set of exports from the final world which are defined by this
3104    /// adapter or library
3105    required_exports: IndexSet<WorldKey>,
3106
3107    /// If present, treat this module as a library rather than a "minimal" adapter
3108    ///
3109    /// TODO: We should refactor how various flavors of module are represented
3110    /// and differentiated to avoid mistaking one for another.
3111    library_info: Option<LibraryInfo>,
3112}
3113
3114/// An encoder of components based on `wit` interface definitions.
3115#[derive(Default)]
3116pub struct ComponentEncoder {
3117    module: Vec<u8>,
3118    module_import_map: Option<ModuleImportMap>,
3119    pub(super) metadata: Bindgen,
3120    validate: bool,
3121    pub(super) main_module_exports: IndexSet<WorldKey>,
3122    pub(super) adapters: IndexMap<String, Adapter>,
3123    import_name_map: HashMap<String, String>,
3124    realloc_via_memory_grow: bool,
3125    merge_imports_based_on_semver: Option<bool>,
3126    pub(super) reject_legacy_names: bool,
3127    debug_names: bool,
3128}
3129
3130impl ComponentEncoder {
3131    /// Set the core module to encode as a component.
3132    /// This method will also parse any component type information stored in custom sections
3133    /// inside the module and add them as the interface, imports, and exports.
3134    /// It will also add any producers information inside the component type information to the
3135    /// core module.
3136    pub fn module(mut self, module: &[u8]) -> Result<Self> {
3137        let (wasm, metadata) = self.decode(module.as_ref())?;
3138        let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3139        let exports = self
3140            .merge_metadata(metadata)
3141            .context("failed merge WIT metadata for module with previous metadata")?;
3142        self.main_module_exports.extend(exports);
3143        self.module = if let Some(producers) = &self.metadata.producers {
3144            producers.add_to_wasm(&wasm)?
3145        } else {
3146            wasm.to_vec()
3147        };
3148        self.module_import_map = module_import_map;
3149        Ok(self)
3150    }
3151
3152    fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3153        let (bytes, metadata) = metadata::decode(wasm)?;
3154        match bytes {
3155            Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3156            None => Ok((Cow::Borrowed(wasm), metadata)),
3157        }
3158    }
3159
3160    fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3161        self.metadata.merge(metadata)
3162    }
3163
3164    /// Sets whether or not the encoder will validate its output.
3165    pub fn validate(mut self, validate: bool) -> Self {
3166        self.validate = validate;
3167        self
3168    }
3169
3170    /// Sets whether or not to generate debug names in the output component.
3171    pub fn debug_names(mut self, debug_names: bool) -> Self {
3172        self.debug_names = debug_names;
3173        self
3174    }
3175
3176    /// Sets whether to merge imports based on semver to the specified value.
3177    ///
3178    /// This affects how when to WIT worlds are merged together, for example
3179    /// from two different libraries, whether their imports are unified when the
3180    /// semver version ranges for interface allow it.
3181    ///
3182    /// This is enabled by default.
3183    pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3184        self.merge_imports_based_on_semver = Some(merge);
3185        self
3186    }
3187
3188    /// Sets whether to reject the historical mangling/name scheme for core wasm
3189    /// imports/exports as they map to the component model.
3190    ///
3191    /// The `wit-component` crate supported a different set of names prior to
3192    /// WebAssembly/component-model#378 and this can be used to disable this
3193    /// support.
3194    ///
3195    /// This is disabled by default.
3196    pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3197        self.reject_legacy_names = reject;
3198        self
3199    }
3200
3201    /// Specifies a new adapter which is used to translate from a historical
3202    /// wasm ABI to the canonical ABI and the `interface` provided.
3203    ///
3204    /// This is primarily used to polyfill, for example,
3205    /// `wasi_snapshot_preview1` with a component-model using interface. The
3206    /// `name` provided is the module name of the adapter that is being
3207    /// polyfilled, for example `"wasi_snapshot_preview1"`.
3208    ///
3209    /// The `bytes` provided is a core wasm module which implements the `name`
3210    /// interface in terms of the `interface` interface. This core wasm module
3211    /// is severely restricted in its shape, for example it cannot have any data
3212    /// segments or element segments.
3213    ///
3214    /// The `interface` provided is the component-model-using-interface that the
3215    /// wasm module specified by `bytes` imports. The `bytes` will then import
3216    /// `interface` and export functions to get imported from the module `name`
3217    /// in the core wasm that's being wrapped.
3218    pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3219        self.library_or_adapter(name, bytes, None)
3220    }
3221
3222    /// Specifies a shared-everything library to link into the component.
3223    ///
3224    /// Unlike adapters, libraries _may_ have data and/or element segments, but
3225    /// they must operate on an imported memory and table, respectively.  In
3226    /// this case, the correct amount of space is presumed to have been
3227    /// statically allocated in the main module's memory and table at the
3228    /// offsets which the segments target, e.g. as arranged by
3229    /// [super::linking::Linker].
3230    ///
3231    /// Libraries are treated similarly to adapters, except that they are not
3232    /// "minified" the way adapters are, and instantiation is controlled
3233    /// declaratively via the `library_info` parameter.
3234    pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3235        self.library_or_adapter(name, bytes, Some(library_info))
3236    }
3237
3238    fn library_or_adapter(
3239        mut self,
3240        name: &str,
3241        bytes: &[u8],
3242        library_info: Option<LibraryInfo>,
3243    ) -> Result<Self> {
3244        let (wasm, mut metadata) = self.decode(bytes)?;
3245        // Merge the adapter's document into our own document to have one large
3246        // document, and then afterwards merge worlds as well.
3247        //
3248        // Note that the `metadata` tracking import/export encodings is removed
3249        // since this adapter can get different lowerings and is allowed to
3250        // differ from the main module. This is then tracked within the
3251        // `Adapter` structure produced below.
3252        let adapter_metadata = mem::take(&mut metadata.metadata);
3253        let exports = self.merge_metadata(metadata).with_context(|| {
3254            format!("failed to merge WIT packages of adapter `{name}` into main packages")
3255        })?;
3256        if let Some(library_info) = &library_info {
3257            // Validate that all referenced modules can be resolved.
3258            for (_, instance) in &library_info.arguments {
3259                let resolve = |which: &_| match which {
3260                    MainOrAdapter::Main => Ok(()),
3261                    MainOrAdapter::Adapter(name) => {
3262                        if self.adapters.contains_key(name.as_str()) {
3263                            Ok(())
3264                        } else {
3265                            Err(anyhow!("instance refers to unknown adapter `{name}`"))
3266                        }
3267                    }
3268                };
3269
3270                match instance {
3271                    Instance::MainOrAdapter(which) => resolve(which)?,
3272                    Instance::Items(items) => {
3273                        for item in items {
3274                            resolve(&item.which)?;
3275                        }
3276                    }
3277                }
3278            }
3279        }
3280        self.adapters.insert(
3281            name.to_string(),
3282            Adapter {
3283                wasm: wasm.to_vec(),
3284                metadata: adapter_metadata,
3285                required_exports: exports,
3286                library_info,
3287            },
3288        );
3289        Ok(self)
3290    }
3291
3292    /// True if the realloc and stack allocation should use memory.grow
3293    /// The default is to use the main module realloc
3294    /// Can be useful if cabi_realloc cannot be called before the host
3295    /// runtime is initialized.
3296    pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3297        self.realloc_via_memory_grow = value;
3298        self
3299    }
3300
3301    /// The instance import name map to use.
3302    ///
3303    /// This is used to rename instance imports in the final component.
3304    ///
3305    /// For example, if there is an instance import `foo:bar/baz` and it is
3306    /// desired that the import actually be an `unlocked-dep` name, then
3307    /// `foo:bar/baz` can be mapped to `unlocked-dep=<a:b/c@{>=x.y.z}>`.
3308    ///
3309    /// Note: the replacement names are not validated during encoding unless
3310    /// the `validate` option is set to true.
3311    pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3312        self.import_name_map = map;
3313        self
3314    }
3315
3316    /// Encode the component and return the bytes.
3317    pub fn encode(&mut self) -> Result<Vec<u8>> {
3318        if self.module.is_empty() {
3319            bail!("a module is required when encoding a component");
3320        }
3321
3322        if self.merge_imports_based_on_semver.unwrap_or(true) {
3323            self.metadata
3324                .resolve
3325                .merge_world_imports_based_on_semver(self.metadata.world)?;
3326        }
3327
3328        self.finalize_resolve_with_nominal_ids();
3329
3330        let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3331        let mut state = EncodingState {
3332            component: ComponentBuilder::default(),
3333            module_index: None,
3334            instance_index: None,
3335            memory_index: None,
3336            shim_instance_index: None,
3337            fixups_module_index: None,
3338            adapter_modules: IndexMap::new(),
3339            adapter_instances: IndexMap::new(),
3340            type_encoding_maps: Default::default(),
3341            instances: Default::default(),
3342            imported_funcs: Default::default(),
3343            aliased_core_items: Default::default(),
3344            info: &world,
3345            export_task_initialization_wrappers: HashMap::new(),
3346        };
3347        state.encode_imports(&self.import_name_map)?;
3348        state.encode_core_modules();
3349        state.encode_core_instantiation()?;
3350        state.encode_exports(CustomModule::Main)?;
3351        for name in self.adapters.keys() {
3352            state.encode_exports(CustomModule::Adapter(name))?;
3353        }
3354        state.component.append_names();
3355        state
3356            .component
3357            .raw_custom_section(&crate::base_producers().raw_custom_section());
3358        let bytes = state.component.finish();
3359
3360        if self.validate {
3361            Validator::new_with_features(WasmFeatures::all())
3362                .validate_all(&bytes)
3363                .context("failed to validate component output")?;
3364        }
3365
3366        Ok(bytes)
3367    }
3368
3369    /// Call the `generate_nominal_type_ids` method on the `Resolve` that we're
3370    /// using, adjusting any preexisting keys/pointers as necessary.
3371    ///
3372    /// This is the final step after merging all known `Resolve`s together
3373    /// before a component is actually created. By creating a unique
3374    /// `InterfaceId` for all interfaces it makes the generation process easier
3375    /// since there's no need to fret about whether an `InterfaceId` is an
3376    /// import or an export for example.
3377    fn finalize_resolve_with_nominal_ids(&mut self) {
3378        // Before calling `generate_nominal_type_ids` we need to handle the fact
3379        // that the exports of the world are going to be rewritten. The only
3380        // pointers we have into those are the exports of the main module and
3381        // adapters. To handle this, before we generate nominal ids, indices of
3382        // exports are saved here on the stack to get restored later on.
3383        // Effectively we're clearing out the exports and rebuilding them later.
3384        let world = &self.metadata.resolve.worlds[self.metadata.world];
3385        let main_module_exports = self
3386            .main_module_exports
3387            .iter()
3388            .map(|i| world.exports.get_index_of(i).unwrap())
3389            .collect::<Vec<_>>();
3390        let adapter_exports = self
3391            .adapters
3392            .values()
3393            .map(|adapter| {
3394                adapter
3395                    .required_exports
3396                    .iter()
3397                    .map(|i| world.exports.get_index_of(i).unwrap())
3398                    .collect::<Vec<_>>()
3399            })
3400            .collect::<Vec<_>>();
3401
3402        // With everything saved this will modify `Resolve` to ensure there's a
3403        // nominal identifier for all interfaces (e.g. not both simultaneously
3404        // imported and exported).
3405        self.metadata
3406            .resolve
3407            .generate_nominal_type_ids(self.metadata.world);
3408
3409        // Rebuild the sets of exports now that the world's exports have been
3410        // clobbered.
3411        self.main_module_exports.clear();
3412        let world = &self.metadata.resolve.worlds[self.metadata.world];
3413        for index in main_module_exports {
3414            let (key, _) = world.exports.get_index(index).unwrap();
3415            self.main_module_exports.insert(key.clone());
3416        }
3417        for (exports, adapter) in adapter_exports.into_iter().zip(self.adapters.values_mut()) {
3418            adapter.required_exports.clear();
3419            for index in exports {
3420                let (key, _) = world.exports.get_index(index).unwrap();
3421                adapter.required_exports.insert(key.clone());
3422            }
3423        }
3424    }
3425}
3426
3427impl ComponentWorld<'_> {
3428    /// Convenience function to lookup a module's import map.
3429    fn imports_for(&self, module: CustomModule) -> &ImportMap {
3430        match module {
3431            CustomModule::Main => &self.info.imports,
3432            CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3433        }
3434    }
3435
3436    /// Convenience function to lookup a module's export map.
3437    fn exports_for(&self, module: CustomModule) -> &ExportMap {
3438        match module {
3439            CustomModule::Main => &self.info.exports,
3440            CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3441        }
3442    }
3443
3444    /// Convenience function to lookup a module's metadata.
3445    fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3446        match module {
3447            CustomModule::Main => &self.encoder.metadata.metadata,
3448            CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3449        }
3450    }
3451}
3452
3453#[cfg(all(test, feature = "dummy-module"))]
3454mod test {
3455    use super::*;
3456    use crate::{dummy_module, embed_component_metadata};
3457    use wit_parser::ManglingAndAbi;
3458
3459    #[test]
3460    fn it_renames_imports() {
3461        let mut resolve = Resolve::new();
3462        let pkg = resolve
3463            .push_str(
3464                "test.wit",
3465                r#"
3466package test:wit;
3467
3468interface i {
3469    f: func();
3470}
3471
3472world test {
3473    import i;
3474    import foo: interface {
3475        f: func();
3476    }
3477}
3478"#,
3479            )
3480            .unwrap();
3481        let world = resolve.select_world(&[pkg], None).unwrap();
3482
3483        let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3484
3485        embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3486
3487        let encoded = ComponentEncoder::default()
3488            .import_name_map(HashMap::from([
3489                (
3490                    "foo".to_string(),
3491                    "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3492                ),
3493                (
3494                    "test:wit/i".to_string(),
3495                    "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3496                ),
3497            ]))
3498            .module(&module)
3499            .unwrap()
3500            .validate(true)
3501            .encode()
3502            .unwrap();
3503
3504        let wat = wasmprinter::print_bytes(encoded).unwrap();
3505        assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3506        assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3507    }
3508}