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