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