wit_component/
encoding.rs

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