wit_component/
encoding.rs

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