Skip to main content

wit_component/
encoding.rs

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