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