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