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