wit_component_update/
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::encoding::world::WorldAdapter;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77    ResourceInfo, ValidatedModule, BARE_FUNC_MODULE_NAME, MAIN_MODULE_IMPORT_NAME,
78    POST_RETURN_PREFIX,
79};
80use crate::StringEncoding;
81use anyhow::{anyhow, bail, Context, Result};
82use indexmap::{IndexMap, IndexSet};
83use std::collections::HashMap;
84use std::hash::Hash;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88    abi::{AbiVariant, WasmSignature, WasmType},
89    Function, FunctionKind, InterfaceId, LiveTypes, Resolve, Type, TypeDefKind, TypeId, TypeOwner,
90    WorldItem, WorldKey,
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103fn to_val_type(ty: &WasmType) -> ValType {
104    match ty {
105        WasmType::I32 => ValType::I32,
106        WasmType::I64 => ValType::I64,
107        WasmType::F32 => ValType::F32,
108        WasmType::F64 => ValType::F64,
109        WasmType::Pointer => ValType::I32,
110        WasmType::PointerOrI64 => ValType::I64,
111        WasmType::Length => ValType::I32,
112    }
113}
114
115bitflags::bitflags! {
116    /// Options in the `canon lower` or `canon lift` required for a particular
117    /// function.
118    #[derive(Copy, Clone, Debug)]
119    pub struct RequiredOptions: u8 {
120        /// A memory must be specified, typically the "main module"'s memory
121        /// export.
122        const MEMORY = 1 << 0;
123        /// A `realloc` function must be specified, typically named
124        /// `cabi_realloc`.
125        const REALLOC = 1 << 1;
126        /// A string encoding must be specified, which is always utf-8 for now
127        /// today.
128        const STRING_ENCODING = 1 << 2;
129    }
130}
131
132impl RequiredOptions {
133    fn for_import(resolve: &Resolve, func: &Function) -> RequiredOptions {
134        let sig = resolve.wasm_signature(AbiVariant::GuestImport, func);
135        let mut ret = RequiredOptions::empty();
136        // Lift the params and lower the results for imports
137        ret.add_lift(TypeContents::for_types(
138            resolve,
139            func.params.iter().map(|(_, t)| t),
140        ));
141        ret.add_lower(TypeContents::for_types(resolve, func.results.iter_types()));
142
143        // If anything is indirect then `memory` will be required to read the
144        // indirect values.
145        if sig.retptr || sig.indirect_params {
146            ret |= RequiredOptions::MEMORY;
147        }
148        ret
149    }
150
151    fn for_export(resolve: &Resolve, func: &Function) -> RequiredOptions {
152        let sig = resolve.wasm_signature(AbiVariant::GuestExport, func);
153        let mut ret = RequiredOptions::empty();
154        // Lower the params and lift the results for exports
155        ret.add_lower(TypeContents::for_types(
156            resolve,
157            func.params.iter().map(|(_, t)| t),
158        ));
159        ret.add_lift(TypeContents::for_types(resolve, func.results.iter_types()));
160
161        // If anything is indirect then `memory` will be required to read the
162        // indirect values, but if the arguments are indirect then `realloc` is
163        // additionally required to allocate space for the parameters.
164        if sig.retptr || sig.indirect_params {
165            ret |= RequiredOptions::MEMORY;
166            if sig.indirect_params {
167                ret |= RequiredOptions::REALLOC;
168            }
169        }
170        ret
171    }
172
173    fn add_lower(&mut self, types: TypeContents) {
174        // If lists/strings are lowered into wasm then memory is required as
175        // usual but `realloc` is also required to allow the external caller to
176        // allocate space in the destination for the list/string.
177        if types.contains(TypeContents::LIST) {
178            *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
179        }
180        if types.contains(TypeContents::STRING) {
181            *self |= RequiredOptions::MEMORY
182                | RequiredOptions::STRING_ENCODING
183                | RequiredOptions::REALLOC;
184        }
185    }
186
187    fn add_lift(&mut self, types: TypeContents) {
188        // Unlike for `lower` when lifting a string/list all that's needed is
189        // memory, since the string/list already resides in memory `realloc`
190        // isn't needed.
191        if types.contains(TypeContents::LIST) {
192            *self |= RequiredOptions::MEMORY;
193        }
194        if types.contains(TypeContents::STRING) {
195            *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
196        }
197    }
198
199    fn into_iter(
200        self,
201        encoding: StringEncoding,
202        memory_index: Option<u32>,
203        realloc_index: Option<u32>,
204    ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
205        #[derive(Default)]
206        struct Iter {
207            options: [Option<CanonicalOption>; 3],
208            current: usize,
209            count: usize,
210        }
211
212        impl Iter {
213            fn push(&mut self, option: CanonicalOption) {
214                assert!(self.count < self.options.len());
215                self.options[self.count] = Some(option);
216                self.count += 1;
217            }
218        }
219
220        impl Iterator for Iter {
221            type Item = CanonicalOption;
222
223            fn next(&mut self) -> Option<Self::Item> {
224                if self.current == self.count {
225                    return None;
226                }
227                let option = self.options[self.current];
228                self.current += 1;
229                option
230            }
231
232            fn size_hint(&self) -> (usize, Option<usize>) {
233                (self.count - self.current, Some(self.count - self.current))
234            }
235        }
236
237        impl ExactSizeIterator for Iter {}
238
239        let mut iter = Iter::default();
240
241        if self.contains(RequiredOptions::MEMORY) {
242            iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
243                anyhow!("module does not export a memory named `memory`")
244            })?));
245        }
246
247        if self.contains(RequiredOptions::REALLOC) {
248            iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
249                || anyhow!("module does not export a function named `cabi_realloc`"),
250            )?));
251        }
252
253        if self.contains(RequiredOptions::STRING_ENCODING) {
254            iter.push(encoding.into());
255        }
256
257        Ok(iter)
258    }
259}
260
261bitflags::bitflags! {
262    /// Flags about what kinds of types are present within the recursive
263    /// structure of a type.
264    struct TypeContents: u8 {
265        const STRING = 1 << 0;
266        const LIST = 1 << 1;
267    }
268}
269
270impl TypeContents {
271    fn for_types<'a>(resolve: &Resolve, types: impl Iterator<Item = &'a Type>) -> Self {
272        let mut cur = TypeContents::empty();
273        for ty in types {
274            cur |= Self::for_type(resolve, ty);
275        }
276        cur
277    }
278
279    fn for_optional_types<'a>(
280        resolve: &Resolve,
281        types: impl Iterator<Item = Option<&'a Type>>,
282    ) -> Self {
283        Self::for_types(resolve, types.flatten())
284    }
285
286    fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
287        match ty {
288            Some(ty) => Self::for_type(resolve, ty),
289            None => Self::empty(),
290        }
291    }
292
293    fn for_type(resolve: &Resolve, ty: &Type) -> Self {
294        match ty {
295            Type::Id(id) => match &resolve.types[*id].kind {
296                TypeDefKind::Handle(h) => match h {
297                    wit_parser::Handle::Own(_) => Self::empty(),
298                    wit_parser::Handle::Borrow(_) => Self::empty(),
299                },
300                TypeDefKind::Resource => Self::empty(),
301                TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
302                TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
303                TypeDefKind::Flags(_) => Self::empty(),
304                TypeDefKind::Option(t) => Self::for_type(resolve, t),
305                TypeDefKind::Result(r) => {
306                    Self::for_optional_type(resolve, r.ok.as_ref())
307                        | Self::for_optional_type(resolve, r.err.as_ref())
308                }
309                TypeDefKind::Variant(v) => {
310                    Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
311                }
312                TypeDefKind::Enum(_) => Self::empty(),
313                TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::LIST,
314                TypeDefKind::Type(t) => Self::for_type(resolve, t),
315                TypeDefKind::Future(_) => todo!("encoding for future"),
316                TypeDefKind::Stream(_) => todo!("encoding for stream"),
317                TypeDefKind::Unknown => unreachable!(),
318            },
319            Type::String => Self::STRING,
320            _ => Self::empty(),
321        }
322    }
323}
324
325/// State relating to encoding a component.
326pub struct EncodingState<'a> {
327    /// The component being encoded.
328    component: ComponentBuilder,
329    /// The index into the core module index space for the inner core module.
330    ///
331    /// If `None`, the core module has not been encoded.
332    module_index: Option<u32>,
333    /// The index into the core instance index space for the inner core module.
334    ///
335    /// If `None`, the core module has not been instantiated.
336    instance_index: Option<u32>,
337    /// The index in the core memory index space for the exported memory.
338    ///
339    /// If `None`, then the memory has not yet been aliased.
340    memory_index: Option<u32>,
341    /// The index in the core function index space for the realloc function.
342    ///
343    /// If `None`, then the realloc function has not yet been aliased.
344    realloc_index: Option<u32>,
345    /// The index of the shim instance used for lowering imports into the core instance.
346    ///
347    /// If `None`, then the shim instance how not yet been encoded.
348    shim_instance_index: Option<u32>,
349    /// The index of the fixups module to instantiate to fill in the lowered imports.
350    ///
351    /// If `None`, then a fixup module has not yet been encoded.
352    fixups_module_index: Option<u32>,
353
354    /// A map of named adapter modules and the index that the module was defined
355    /// at.
356    adapter_modules: IndexMap<&'a str, u32>,
357    /// A map of adapter module instances and the index of their instance.
358    adapter_instances: IndexMap<&'a str, u32>,
359    /// A map of the index of the aliased realloc function for each adapter
360    /// module. Note that adapters have two realloc functions, one for imports
361    /// and one for exports.
362    adapter_import_reallocs: IndexMap<&'a str, Option<u32>>,
363    adapter_export_reallocs: IndexMap<&'a str, Option<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    /// Metadata about the world inferred from the input to `ComponentEncoder`.
380    info: &'a ComponentWorld<'a>,
381}
382
383impl<'a> EncodingState<'a> {
384    fn encode_core_modules(&mut self) {
385        assert!(self.module_index.is_none());
386        let idx = self.component.core_module_raw(&self.info.encoder.module);
387        self.module_index = Some(idx);
388
389        for (name, adapter) in self.info.adapters.iter() {
390            let add_meta = wasm_metadata::AddMetadata {
391                name: Some(if adapter.library_info.is_some() {
392                    name.to_string()
393                } else {
394                    format!("wit-component:adapter:{name}")
395                }),
396                ..Default::default()
397            };
398            let wasm = add_meta
399                .to_wasm(&adapter.wasm)
400                .expect("core wasm can get name added");
401            let idx = self.component.core_module_raw(&wasm);
402            let prev = self.adapter_modules.insert(name, idx);
403            assert!(prev.is_none());
404        }
405    }
406
407    fn root_import_type_encoder(
408        &mut self,
409        interface: Option<InterfaceId>,
410    ) -> RootTypeEncoder<'_, 'a> {
411        RootTypeEncoder {
412            state: self,
413            interface,
414            import_types: true,
415        }
416    }
417
418    fn root_export_type_encoder(
419        &mut self,
420        interface: Option<InterfaceId>,
421    ) -> RootTypeEncoder<'_, 'a> {
422        RootTypeEncoder {
423            state: self,
424            interface,
425            import_types: false,
426        }
427    }
428
429    fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
430        InstanceTypeEncoder {
431            state: self,
432            interface,
433            type_map: Default::default(),
434            func_type_map: Default::default(),
435            ty: Default::default(),
436        }
437    }
438
439    fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
440        let mut has_funcs = false;
441        for (name, info) in self.info.import_map.iter() {
442            match name {
443                Some(name) => {
444                    self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
445                }
446                None => has_funcs = true,
447            }
448        }
449
450        let resolve = &self.info.encoder.metadata.resolve;
451        let world = &resolve.worlds[self.info.encoder.metadata.world];
452        for (_name, item) in world.imports.iter() {
453            if let WorldItem::Type(ty) = item {
454                self.root_import_type_encoder(None)
455                    .encode_valtype(resolve, &Type::Id(*ty))?;
456            }
457        }
458
459        if has_funcs {
460            let info = &self.info.import_map[&None];
461            self.encode_root_import_funcs(info)?;
462        }
463        Ok(())
464    }
465
466    fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
467        let resolve = &self.info.encoder.metadata.resolve;
468        let interface_id = info.interface.as_ref().unwrap();
469        let interface_id = *interface_id;
470        let interface = &resolve.interfaces[interface_id];
471        log::trace!("encoding imports for `{name}` as {:?}", interface_id);
472        let mut encoder = self.instance_type_encoder(interface_id);
473
474        // First encode all type information
475        if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
476            for ty in live {
477                log::trace!(
478                    "encoding extra type {ty:?} name={:?}",
479                    resolve.types[*ty].name
480                );
481                encoder.encode_valtype(resolve, &Type::Id(*ty))?;
482            }
483        }
484
485        // Next encode all required functions from this imported interface
486        // into the instance type.
487        for (_, func) in interface.functions.iter() {
488            if !info.lowerings.contains_key(&func.name) {
489                continue;
490            }
491            log::trace!("encoding function type for `{}`", func.name);
492            let idx = encoder.encode_func_type(resolve, func)?;
493
494            encoder.ty.export(&func.name, ComponentTypeRef::Func(idx));
495        }
496
497        let ty = encoder.ty;
498        // Don't encode empty instance types since they're not
499        // meaningful to the runtime of the component anyway.
500        if ty.is_empty() {
501            return Ok(());
502        }
503        let instance_type_idx = self.component.type_instance(&ty);
504        let instance_idx = self
505            .component
506            .import(name, ComponentTypeRef::Instance(instance_type_idx));
507        let prev = self.imported_instances.insert(interface_id, instance_idx);
508        assert!(prev.is_none());
509        Ok(())
510    }
511
512    fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
513        let resolve = &self.info.encoder.metadata.resolve;
514        let world = self.info.encoder.metadata.world;
515        for (name, item) in resolve.worlds[world].imports.iter() {
516            let func = match item {
517                WorldItem::Function(f) => f,
518                WorldItem::Interface(_) | WorldItem::Type(_) => continue,
519            };
520            let name = resolve.name_world_key(name);
521            if !info.lowerings.contains_key(&name) {
522                continue;
523            }
524            log::trace!("encoding function type for `{}`", func.name);
525            let idx = self
526                .root_import_type_encoder(None)
527                .encode_func_type(resolve, func)?;
528            let func_idx = self.component.import(&name, ComponentTypeRef::Func(idx));
529            let prev = self.imported_funcs.insert(name, func_idx);
530            assert!(prev.is_none());
531        }
532        Ok(())
533    }
534
535    fn alias_imported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
536        let ty = &self.info.encoder.metadata.resolve.types[id];
537        let name = ty.name.as_ref().expect("type must have a name");
538        let instance = self.imported_instances[&interface];
539        self.component
540            .alias_export(instance, name, ComponentExportKind::Type)
541    }
542
543    fn alias_exported_type(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
544        let ty = &self.info.encoder.metadata.resolve.types[id];
545        let name = ty.name.as_ref().expect("type must have a name");
546        let instance = self.exported_instances[&interface];
547        self.component
548            .alias_export(instance, name, ComponentExportKind::Type)
549    }
550
551    fn encode_core_instantiation(&mut self) -> Result<()> {
552        let info = &self.info.info;
553
554        // Encode a shim instantiation if needed
555        let shims = self.encode_shim_instantiation()?;
556
557        // For each instance import into the main module create a
558        // pseudo-core-wasm-module via a bag-of-exports.
559        let mut args = Vec::new();
560        for core_wasm_name in info.required_imports.keys() {
561            let index = self.import_instance_to_lowered_core_instance(
562                CustomModule::Main,
563                core_wasm_name,
564                &shims,
565                info.metadata,
566            );
567            args.push((*core_wasm_name, ModuleArg::Instance(index)));
568        }
569
570        // For each adapter module instance imported into the core wasm module
571        // the appropriate shim is packaged up into a bag-of-exports instance.
572        // Note that adapter modules currently don't deal with
573        // indirect-vs-direct lowerings, everything is indirect.
574        for (adapter, funcs) in info.adapters_required.iter() {
575            let shim_instance = self
576                .shim_instance_index
577                .expect("shim should be instantiated");
578            let mut exports = Vec::new();
579
580            for (func, _ty) in funcs {
581                let index = self.component.core_alias_export(
582                    shim_instance,
583                    &shims.shim_names[&ShimKind::Adapter { adapter, func }],
584                    ExportKind::Func,
585                );
586                exports.push((*func, ExportKind::Func, index));
587            }
588
589            let index = self.component.core_instantiate_exports(exports);
590            args.push((*adapter, ModuleArg::Instance(index)));
591        }
592
593        self.add_resource_funcs(
594            CustomModule::Main,
595            &info.required_resource_funcs,
596            &shims,
597            &mut args,
598        );
599
600        // Instantiate the main module now that all of its arguments have been
601        // prepared. With this we now have the main linear memory for
602        // liftings/lowerings later on as well as the adapter modules, if any,
603        // instantiated after the core wasm module.
604        self.instantiate_core_module(args, info);
605
606        // Separate the adapters according which should be instantiated before
607        // and after indirect lowerings are encoded.
608        let (before, after) = self
609            .info
610            .adapters
611            .iter()
612            .partition::<Vec<_>, _>(|(_, adapter)| {
613                !matches!(
614                    adapter.library_info,
615                    Some(LibraryInfo {
616                        instantiate_after_shims: true,
617                        ..
618                    })
619                )
620            });
621
622        for (name, adapter) in before {
623            self.instantiate_adapter_module(&shims, name, adapter);
624        }
625
626        // With all the relevant core wasm instances in play now the original shim
627        // module, if present, can be filled in with lowerings/adapters/etc.
628        self.encode_indirect_lowerings(&shims)?;
629
630        for (name, adapter) in after {
631            self.instantiate_adapter_module(&shims, name, adapter);
632        }
633
634        Ok(())
635    }
636
637    /// Lowers a named imported interface a core wasm instances suitable to
638    /// provide as an instantiation argument to another core wasm module.
639    ///
640    /// * `for_module` the module that this instance is being created for, or
641    ///   otherwise which `realloc` option is used for the lowerings.
642    /// * `name` - the name of the imported interface that's being lowered.
643    /// * `imports` - the list of all imports known for this encoding.
644    /// * `shims` - the indirect/adapter shims created prior, if any.
645    fn import_instance_to_lowered_core_instance(
646        &mut self,
647        for_module: CustomModule<'_>,
648        core_wasm_name: &str,
649        shims: &Shims<'_>,
650        metadata: &ModuleMetadata,
651    ) -> u32 {
652        let interface = if core_wasm_name == BARE_FUNC_MODULE_NAME {
653            None
654        } else {
655            Some(core_wasm_name.to_string())
656        };
657        let import = &self.info.import_map[&interface];
658        let required_imports = match for_module {
659            CustomModule::Main => &self.info.info.required_imports[core_wasm_name],
660            CustomModule::Adapter(name) => {
661                &self.info.adapters[name].info.required_imports[core_wasm_name]
662            }
663        };
664        let mut exports = Vec::with_capacity(import.lowerings.len());
665
666        for (index, (name, lowering)) in import.lowerings.iter().enumerate() {
667            if !required_imports.funcs.contains(name.as_str()) {
668                continue;
669            }
670            let index = match lowering {
671                // All direct lowerings can be `canon lower`'d here immediately
672                // and passed as arguments.
673                Lowering::Direct => {
674                    let func_index = match &import.interface {
675                        Some(interface) => {
676                            let instance_index = self.imported_instances[interface];
677                            self.component.alias_export(
678                                instance_index,
679                                name,
680                                ComponentExportKind::Func,
681                            )
682                        }
683                        None => self.imported_funcs[name],
684                    };
685                    self.component.lower_func(func_index, [])
686                }
687
688                // Add an entry for all indirect lowerings which come as an
689                // export of the shim module.
690                Lowering::Indirect { .. } => {
691                    let encoding =
692                        metadata.import_encodings[&(core_wasm_name.to_string(), name.clone())];
693                    self.component.core_alias_export(
694                        self.shim_instance_index
695                            .expect("shim should be instantiated"),
696                        &shims.shim_names[&ShimKind::IndirectLowering {
697                            interface: interface.clone(),
698                            index,
699                            realloc: for_module,
700                            encoding,
701                        }],
702                        ExportKind::Func,
703                    )
704                }
705
706                Lowering::ResourceDrop(id) => {
707                    let resource_idx = self.lookup_resource_index(*id);
708                    self.component.resource_drop(resource_idx)
709                }
710            };
711            exports.push((name.as_str(), ExportKind::Func, index));
712        }
713
714        self.component.core_instantiate_exports(exports)
715    }
716
717    fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
718        let resolve = &self.info.encoder.metadata.resolve;
719        let ty = &resolve.types[id];
720        match ty.owner {
721            // If this resource is owned by a world then it's a top-level
722            // resource which means it must have already been translated so
723            // it's available for lookup in `import_type_map`.
724            TypeOwner::World(_) => self.import_type_map[&id],
725            TypeOwner::Interface(i) => {
726                let instance = self.imported_instances[&i];
727                let name = ty.name.as_ref().expect("resources must be named");
728                self.component
729                    .alias_export(instance, name, ComponentExportKind::Type)
730            }
731            TypeOwner::None => panic!("resources must have an owner"),
732        }
733    }
734
735    fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
736        let resolve = &self.info.encoder.metadata.resolve;
737        let exports = match module {
738            CustomModule::Main => &self.info.encoder.main_module_exports,
739            CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
740        };
741        let world = &resolve.worlds[self.info.encoder.metadata.world];
742        for export_name in exports {
743            let export_string = resolve.name_world_key(export_name);
744            match &world.exports[export_name] {
745                WorldItem::Function(func) => {
746                    let ty = self
747                        .root_import_type_encoder(None)
748                        .encode_func_type(resolve, func)?;
749                    let core_name = func.core_export_name(None);
750                    let idx = self.encode_lift(module, &core_name, func, ty)?;
751                    self.component
752                        .export(&export_string, ComponentExportKind::Func, idx, None);
753                }
754                WorldItem::Interface(export) => {
755                    self.encode_interface_export(&export_string, module, *export)?;
756                }
757                WorldItem::Type(_) => unreachable!(),
758            }
759        }
760
761        Ok(())
762    }
763
764    fn encode_interface_export(
765        &mut self,
766        export_name: &str,
767        module: CustomModule<'_>,
768        export: InterfaceId,
769    ) -> Result<()> {
770        log::trace!("encode interface export `{export_name}`");
771        let resolve = &self.info.encoder.metadata.resolve;
772
773        // First execute a `canon lift` for all the functions in this interface
774        // from the core wasm export. This requires type information but notably
775        // not exported type information since we don't want to export this
776        // interface's types from the root of the component. Each lifted
777        // function is saved off into an `imports` array to get imported into
778        // the nested component synthesized below.
779        let mut imports = Vec::new();
780        let mut root = self.root_export_type_encoder(Some(export));
781        for (_, func) in &resolve.interfaces[export].functions {
782            let core_name = func.core_export_name(Some(export_name));
783            let ty = root.encode_func_type(resolve, func)?;
784            let func_index = root.state.encode_lift(module, &core_name, func, ty)?;
785            imports.push((
786                import_func_name(func),
787                ComponentExportKind::Func,
788                func_index,
789            ));
790        }
791
792        // Next a nested component is created which will import the functions
793        // above and then reexport them. The purpose of them is to "re-type" the
794        // functions through type ascription on each `func` item.
795        let mut nested = NestedComponentTypeEncoder {
796            component: ComponentBuilder::default(),
797            type_map: Default::default(),
798            func_type_map: Default::default(),
799            export_types: false,
800            interface: export,
801            state: self,
802            imports: IndexMap::new(),
803        };
804
805        // Import all transitively-referenced types from other interfaces into
806        // this component. This temporarily switches the `interface` listed to
807        // the interface of the referred-to-type to generate the import. After
808        // this loop `interface` is rewritten to `export`.
809        //
810        // Each component is a standalone "island" so the necessary type
811        // information needs to be rebuilt within this component. This ensures
812        // that we're able to build a valid component and additionally connect
813        // all the type information to the outer context.
814        let mut types_to_import = LiveTypes::default();
815        types_to_import.add_interface(resolve, export);
816        let exports_used = &nested.state.info.exports_used[&export];
817        for ty in types_to_import.iter() {
818            if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
819                if owner == export {
820                    // Here this deals with the current exported interface which
821                    // is handled below.
822                    continue;
823                }
824
825                // Ensure that `self` has encoded this type before. If so this
826                // is a noop but otherwise it generates the type here.
827                let mut encoder = if exports_used.contains(&owner) {
828                    nested.state.root_export_type_encoder(Some(export))
829                } else {
830                    nested.state.root_import_type_encoder(Some(export))
831                };
832                encoder.encode_valtype(resolve, &Type::Id(ty))?;
833
834                // Next generate the same type but this time within the
835                // component itself. The type generated above (or prior) will be
836                // used to satisfy this type import.
837                nested.interface = owner;
838                nested.encode_valtype(resolve, &Type::Id(ty))?;
839            }
840        }
841        nested.interface = export;
842
843        // Record the map of types imported to their index at where they were
844        // imported. This is used after imports are encoded as exported types
845        // will refer to these.
846        let imported_types = nested.type_map.clone();
847
848        // Handle resource types for this instance specially, namely importing
849        // them into the nested component. This models how the resource is
850        // imported from its definition in the outer component to get reexported
851        // internally. This chiefly avoids creating a second resource which is
852        // not desired in this situation.
853        let mut resources = HashMap::new();
854        for (_name, ty) in resolve.interfaces[export].types.iter() {
855            if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
856                continue;
857            }
858            let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
859                ComponentValType::Type(idx) => idx,
860                _ => unreachable!(),
861            };
862            resources.insert(*ty, idx);
863        }
864
865        // Next import each function of this interface. This will end up
866        // defining local types as necessary or using the types as imported
867        // above.
868        for (_, func) in resolve.interfaces[export].functions.iter() {
869            let ty = nested.encode_func_type(resolve, func)?;
870            nested
871                .component
872                .import(&import_func_name(func), ComponentTypeRef::Func(ty));
873        }
874
875        // Swap the `nested.type_map` which was previously from `TypeId` to
876        // `u32` to instead being from `u32` to `TypeId`. This reverse map is
877        // then used in conjunction with `self.type_map` to satisfy all type
878        // imports of the nested component generated. The type import's index in
879        // the inner component is translated to a `TypeId` via `reverse_map`
880        // which is then translated back to our own index space via `type_map`.
881        let reverse_map = nested
882            .type_map
883            .drain()
884            .map(|p| (p.1, p.0))
885            .collect::<HashMap<_, _>>();
886        for (name, idx) in nested.imports.drain(..) {
887            let id = reverse_map[&idx];
888            let owner = match resolve.types[id].owner {
889                TypeOwner::Interface(id) => id,
890                _ => unreachable!(),
891            };
892            let idx = if owner == export || exports_used.contains(&owner) {
893                log::trace!("consulting exports for {id:?}");
894                nested.state.export_type_map[&id]
895            } else {
896                log::trace!("consulting imports for {id:?}");
897                nested.state.import_type_map[&id]
898            };
899            imports.push((name, ComponentExportKind::Type, idx))
900        }
901
902        // Before encoding exports reset the type map to what all was imported
903        // from foreign interfaces. This will enable any encoded types below to
904        // refer to imports which, after type substitution, will point to the
905        // correct type in the outer component context.
906        nested.type_map = imported_types;
907
908        // Next the component reexports all of its imports, but notably uses the
909        // type ascription feature to change the type of the function. Note that
910        // no structural change is happening to the types here but instead types
911        // are getting proper names and such now that this nested component is a
912        // new type index space. Hence the `export_types = true` flag here which
913        // flows through the type encoding and when types are emitted.
914        nested.export_types = true;
915        nested.func_type_map.clear();
916
917        // To start off all type information is encoded. This will be used by
918        // functions below but notably this also has special handling for
919        // resources. Resources reexport their imported resource type under
920        // the final name which achieves the desired goal of threading through
921        // the original resource without creating a new one.
922        for (_, id) in resolve.interfaces[export].types.iter() {
923            let ty = &resolve.types[*id];
924            match ty.kind {
925                TypeDefKind::Resource => {
926                    let idx = nested.component.export(
927                        ty.name.as_ref().expect("resources must be named"),
928                        ComponentExportKind::Type,
929                        resources[id],
930                        None,
931                    );
932                    nested.type_map.insert(*id, idx);
933                }
934                _ => {
935                    nested.encode_valtype(resolve, &Type::Id(*id))?;
936                }
937            }
938        }
939
940        for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
941            let ty = nested.encode_func_type(resolve, func)?;
942            nested.component.export(
943                &func.name,
944                ComponentExportKind::Func,
945                i as u32,
946                Some(ComponentTypeRef::Func(ty)),
947            );
948        }
949
950        // Embed the component within our component and then instantiate it with
951        // the lifted functions. That final instance is then exported under the
952        // appropriate name as the final typed export of this component.
953        let component = nested.component;
954        let component_index = self.component.component(component);
955        let instance_index = self.component.instantiate(component_index, imports);
956        let idx = self.component.export(
957            export_name,
958            ComponentExportKind::Instance,
959            instance_index,
960            None,
961        );
962        let prev = self.exported_instances.insert(export, idx);
963        assert!(prev.is_none());
964
965        // After everything is all said and done remove all the type information
966        // about type exports of this interface. Any entries in the map
967        // currently were used to create the instance above but aren't the
968        // actual copy of the exported type since that comes from the exported
969        // instance itself. Entries will be re-inserted into this map as
970        // necessary via aliases from the exported instance which is the new
971        // source of truth for all these types.
972        for (_name, id) in resolve.interfaces[export].types.iter() {
973            self.export_type_map.remove(id);
974        }
975
976        return Ok(());
977
978        struct NestedComponentTypeEncoder<'state, 'a> {
979            component: ComponentBuilder,
980            type_map: HashMap<TypeId, u32>,
981            func_type_map: HashMap<types::FunctionKey<'a>, u32>,
982            export_types: bool,
983            interface: InterfaceId,
984            state: &'state mut EncodingState<'a>,
985            imports: IndexMap<String, u32>,
986        }
987
988        impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
989            fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
990                self.component.type_defined()
991            }
992            fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
993                self.component.type_function()
994            }
995            fn export_type(&mut self, idx: u32, name: &'a str) -> Option<u32> {
996                if self.export_types {
997                    Some(
998                        self.component
999                            .export(name, ComponentExportKind::Type, idx, None),
1000                    )
1001                } else {
1002                    let name = self.unique_import_name(name);
1003                    let ret = self
1004                        .component
1005                        .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1006                    self.imports.insert(name, ret);
1007                    Some(ret)
1008                }
1009            }
1010            fn export_resource(&mut self, name: &'a str) -> u32 {
1011                if self.export_types {
1012                    panic!("resources should already be exported")
1013                } else {
1014                    let name = self.unique_import_name(name);
1015                    let ret = self
1016                        .component
1017                        .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1018                    self.imports.insert(name, ret);
1019                    ret
1020                }
1021            }
1022            fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1023                unreachable!()
1024            }
1025            fn type_map(&mut self) -> &mut HashMap<TypeId, u32> {
1026                &mut self.type_map
1027            }
1028            fn func_type_map(&mut self) -> &mut HashMap<types::FunctionKey<'a>, u32> {
1029                &mut self.func_type_map
1030            }
1031            fn interface(&self) -> Option<InterfaceId> {
1032                Some(self.interface)
1033            }
1034        }
1035
1036        impl NestedComponentTypeEncoder<'_, '_> {
1037            fn unique_import_name(&mut self, name: &str) -> String {
1038                let mut name = format!("import-type-{name}");
1039                let mut n = 0;
1040                while self.imports.contains_key(&name) {
1041                    name = format!("{name}{n}");
1042                    n += 1;
1043                }
1044                name
1045            }
1046        }
1047
1048        fn import_func_name(f: &Function) -> String {
1049            match f.kind {
1050                FunctionKind::Freestanding => {
1051                    format!("import-func-{}", f.name)
1052                }
1053
1054                // transform `[method]foo.bar` into `import-method-foo-bar` to
1055                // have it be a valid kebab-name which can't conflict with
1056                // anything else.
1057                //
1058                // There's probably a better and more "formal" way to do this
1059                // but quick-and-dirty string manipulation should work well
1060                // enough for now hopefully.
1061                FunctionKind::Method(_)
1062                | FunctionKind::Static(_)
1063                | FunctionKind::Constructor(_) => {
1064                    format!(
1065                        "import-{}",
1066                        f.name.replace('[', "").replace([']', '.'], "-")
1067                    )
1068                }
1069            }
1070        }
1071    }
1072
1073    fn encode_lift(
1074        &mut self,
1075        module: CustomModule<'_>,
1076        core_name: &str,
1077        func: &Function,
1078        ty: u32,
1079    ) -> Result<u32> {
1080        let resolve = &self.info.encoder.metadata.resolve;
1081        let metadata = match module {
1082            CustomModule::Main => &self.info.encoder.metadata.metadata,
1083            CustomModule::Adapter(name) => &self.info.encoder.adapters[name].metadata,
1084        };
1085        let post_returns = match module {
1086            CustomModule::Main => &self.info.info.post_returns,
1087            CustomModule::Adapter(name) => &self.info.adapters[name].info.post_returns,
1088        };
1089        let instance_index = match module {
1090            CustomModule::Main => self.instance_index.expect("instantiated by now"),
1091            CustomModule::Adapter(name) => self.adapter_instances[name],
1092        };
1093        let core_func_index =
1094            self.component
1095                .core_alias_export(instance_index, core_name, ExportKind::Func);
1096
1097        let options = RequiredOptions::for_export(resolve, func);
1098
1099        let encoding = metadata.export_encodings[core_name];
1100        // TODO: This realloc detection should probably be improved with
1101        // some sort of scheme to have per-function reallocs like
1102        // `cabi_realloc_{name}` or something like that.
1103        let realloc_index = match module {
1104            CustomModule::Main => self.realloc_index,
1105            CustomModule::Adapter(name) => self.adapter_export_reallocs[name],
1106        };
1107        let mut options = options
1108            .into_iter(encoding, self.memory_index, realloc_index)?
1109            .collect::<Vec<_>>();
1110
1111        let post_return = format!("{POST_RETURN_PREFIX}{core_name}");
1112        if post_returns.contains(&post_return[..]) {
1113            let post_return =
1114                self.component
1115                    .core_alias_export(instance_index, &post_return, ExportKind::Func);
1116            options.push(CanonicalOption::PostReturn(post_return));
1117        }
1118        let func_index = self.component.lift_func(core_func_index, ty, options);
1119        Ok(func_index)
1120    }
1121
1122    fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1123        let mut signatures = Vec::new();
1124        let mut ret = Shims::default();
1125        let info = &self.info.info;
1126
1127        // For all interfaces imported into the main module record all of their
1128        // indirect lowerings into `Shims`.
1129        for (core_wasm_name, required) in info.required_imports.iter() {
1130            let import_name = if *core_wasm_name == BARE_FUNC_MODULE_NAME {
1131                None
1132            } else {
1133                Some(core_wasm_name.to_string())
1134            };
1135            let import = &self.info.import_map[&import_name];
1136            ret.append_indirect(
1137                core_wasm_name,
1138                CustomModule::Main,
1139                import,
1140                &required.funcs,
1141                info.metadata,
1142                &mut signatures,
1143            )
1144            .context("failed to register indirect shims for main module")?;
1145        }
1146
1147        // For all required adapter modules a shim is created for each required
1148        // function and additionally a set of shims are created for the
1149        // interface imported into the shim module itself.
1150        for (adapter_name, adapter) in self.info.adapters.iter() {
1151            for (name, required) in adapter.info.required_imports.iter() {
1152                let import_name = if *name == BARE_FUNC_MODULE_NAME {
1153                    None
1154                } else {
1155                    Some(name.to_string())
1156                };
1157                let import = &self.info.import_map[&import_name];
1158                ret.append_indirect(
1159                    name,
1160                    CustomModule::Adapter(adapter_name),
1161                    import,
1162                    &required.funcs,
1163                    adapter.info.metadata,
1164                    &mut signatures,
1165                )
1166                .with_context(|| {
1167                    format!("failed to register indirect shims for adapter {adapter_name}")
1168                })?;
1169            }
1170
1171            self.encode_resource_dtors(
1172                CustomModule::Adapter(adapter_name),
1173                &adapter.info.required_resource_funcs,
1174                &mut signatures,
1175                &mut ret,
1176            );
1177
1178            let funcs = match self.info.info.adapters_required.get(adapter_name) {
1179                Some(funcs) => funcs,
1180                None => continue,
1181            };
1182            for (func, ty) in funcs {
1183                let name = ret.list.len().to_string();
1184                log::debug!("shim {name} is adapter `{adapter_name}::{func}`");
1185                signatures.push(WasmSignature {
1186                    params: ty.params().iter().map(to_wasm_type).collect(),
1187                    results: ty.results().iter().map(to_wasm_type).collect(),
1188                    indirect_params: false,
1189                    retptr: false,
1190                });
1191                ret.list.push(Shim {
1192                    name,
1193                    debug_name: format!("adapt-{adapter_name}-{func}"),
1194                    // Pessimistically assume that all adapters require memory
1195                    // in one form or another. While this isn't technically true
1196                    // it's true enough for WASI.
1197                    options: RequiredOptions::MEMORY,
1198                    kind: ShimKind::Adapter {
1199                        adapter: adapter_name,
1200                        func,
1201                    },
1202                });
1203            }
1204        }
1205
1206        self.encode_resource_dtors(
1207            CustomModule::Main,
1208            &self.info.info.required_resource_funcs,
1209            &mut signatures,
1210            &mut ret,
1211        );
1212
1213        if ret.list.is_empty() {
1214            return Ok(ret);
1215        }
1216
1217        for shim in ret.list.iter() {
1218            let prev = ret.shim_names.insert(shim.kind.clone(), shim.name.clone());
1219            assert!(prev.is_none());
1220        }
1221
1222        assert!(self.shim_instance_index.is_none());
1223        assert!(self.fixups_module_index.is_none());
1224
1225        // This function encodes two modules:
1226        // - A shim module that defines a table and exports functions
1227        //   that indirectly call through the table.
1228        // - A fixup module that imports that table and a set of functions
1229        //   and populates the imported table via active element segments. The
1230        //   fixup module is used to populate the shim's table once the
1231        //   imported functions have been lowered.
1232
1233        let mut types = TypeSection::new();
1234        let mut tables = TableSection::new();
1235        let mut functions = FunctionSection::new();
1236        let mut exports = ExportSection::new();
1237        let mut code = CodeSection::new();
1238        let mut sigs = IndexMap::new();
1239        let mut imports_section = ImportSection::new();
1240        let mut elements = ElementSection::new();
1241        let mut func_indexes = Vec::new();
1242        let mut func_names = NameMap::new();
1243
1244        for (i, (sig, shim)) in signatures.iter().zip(&ret.list).enumerate() {
1245            let i = i as u32;
1246            let type_index = *sigs.entry(sig).or_insert_with(|| {
1247                let index = types.len();
1248                types.function(
1249                    sig.params.iter().map(to_val_type),
1250                    sig.results.iter().map(to_val_type),
1251                );
1252                index
1253            });
1254
1255            functions.function(type_index);
1256            Self::encode_shim_function(type_index, i, &mut code, sig.params.len() as u32);
1257            exports.export(&shim.name, ExportKind::Func, i);
1258
1259            imports_section.import("", &shim.name, EntityType::Function(type_index));
1260            func_indexes.push(i);
1261            func_names.append(i, &shim.debug_name);
1262        }
1263        let mut names = NameSection::new();
1264        names.module("wit-component:shim");
1265        names.functions(&func_names);
1266
1267        let table_type = TableType {
1268            element_type: RefType::FUNCREF,
1269            minimum: signatures.len() as u32,
1270            maximum: Some(signatures.len() as u32),
1271        };
1272
1273        tables.table(table_type);
1274
1275        exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1276        imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1277
1278        elements.active(
1279            None,
1280            &ConstExpr::i32_const(0),
1281            Elements::Functions(&func_indexes),
1282        );
1283
1284        let mut shim = Module::new();
1285        shim.section(&types);
1286        shim.section(&functions);
1287        shim.section(&tables);
1288        shim.section(&exports);
1289        shim.section(&code);
1290        shim.section(&RawCustomSection(
1291            &crate::base_producers().raw_custom_section(),
1292        ));
1293        shim.section(&names);
1294
1295        let mut fixups = Module::default();
1296        fixups.section(&types);
1297        fixups.section(&imports_section);
1298        fixups.section(&elements);
1299        fixups.section(&RawCustomSection(
1300            &crate::base_producers().raw_custom_section(),
1301        ));
1302
1303        let mut names = NameSection::new();
1304        names.module("wit-component:fixups");
1305        fixups.section(&names);
1306
1307        let shim_module_index = self.component.core_module(&shim);
1308        self.fixups_module_index = Some(self.component.core_module(&fixups));
1309        self.shim_instance_index = Some(self.component.core_instantiate(shim_module_index, []));
1310
1311        return Ok(ret);
1312
1313        fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
1314            match ty {
1315                wasmparser::ValType::I32 => WasmType::I32,
1316                wasmparser::ValType::I64 => WasmType::I64,
1317                wasmparser::ValType::F32 => WasmType::F32,
1318                wasmparser::ValType::F64 => WasmType::F64,
1319                _ => unreachable!(),
1320            }
1321        }
1322    }
1323
1324    fn encode_shim_function(
1325        type_index: u32,
1326        func_index: u32,
1327        code: &mut CodeSection,
1328        param_count: u32,
1329    ) {
1330        let mut func = wasm_encoder::Function::new(std::iter::empty());
1331        for i in 0..param_count {
1332            func.instruction(&Instruction::LocalGet(i));
1333        }
1334        func.instruction(&Instruction::I32Const(func_index as i32));
1335        func.instruction(&Instruction::CallIndirect {
1336            ty: type_index,
1337            table: 0,
1338        });
1339        func.instruction(&Instruction::End);
1340        code.function(&func);
1341    }
1342
1343    fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1344        if shims.list.is_empty() {
1345            return Ok(());
1346        }
1347
1348        let shim_instance_index = self
1349            .shim_instance_index
1350            .expect("must have an instantiated shim");
1351
1352        let table_index = self.component.core_alias_export(
1353            shim_instance_index,
1354            INDIRECT_TABLE_NAME,
1355            ExportKind::Table,
1356        );
1357
1358        let mut exports = Vec::new();
1359        exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1360
1361        for shim in shims.list.iter() {
1362            let core_func_index = match &shim.kind {
1363                // Indirect lowerings are a `canon lower`'d function with
1364                // options specified from a previously instantiated instance.
1365                // This previous instance could either be the main module or an
1366                // adapter module, which affects the `realloc` option here.
1367                // Currently only one linear memory is supported so the linear
1368                // memory always comes from the main module.
1369                ShimKind::IndirectLowering {
1370                    interface,
1371                    index,
1372                    realloc,
1373                    encoding,
1374                } => {
1375                    let interface = &self.info.import_map[interface];
1376                    let (name, _) = interface.lowerings.get_index(*index).unwrap();
1377                    let func_index = match &interface.interface {
1378                        Some(interface_id) => {
1379                            let instance_index = self.imported_instances[interface_id];
1380                            self.component.alias_export(
1381                                instance_index,
1382                                name,
1383                                ComponentExportKind::Func,
1384                            )
1385                        }
1386                        None => self.imported_funcs[name],
1387                    };
1388
1389                    let realloc = match realloc {
1390                        CustomModule::Main => self.realloc_index,
1391                        CustomModule::Adapter(name) => self.adapter_import_reallocs[name],
1392                    };
1393
1394                    self.component.lower_func(
1395                        func_index,
1396                        shim.options
1397                            .into_iter(*encoding, self.memory_index, realloc)?,
1398                    )
1399                }
1400
1401                // Adapter shims are defined by an export from an adapter
1402                // instance, so use the specified name here and the previously
1403                // created instances to get the core item that represents the
1404                // shim.
1405                ShimKind::Adapter { adapter, func } => self.component.core_alias_export(
1406                    self.adapter_instances[adapter],
1407                    func,
1408                    ExportKind::Func,
1409                ),
1410
1411                // Resources are required for a module to be instantiated
1412                // meaning that any destructor for the resource must be called
1413                // indirectly due to the otherwise circular dependency between
1414                // the module and the resource itself.
1415                ShimKind::ResourceDtor {
1416                    module,
1417                    import,
1418                    resource,
1419                } => {
1420                    let funcs = match module {
1421                        CustomModule::Main => &self.info.info.required_resource_funcs,
1422                        CustomModule::Adapter(name) => {
1423                            &self.info.adapters[name].info.required_resource_funcs
1424                        }
1425                    };
1426
1427                    self.component.core_alias_export(
1428                        self.instance_index.unwrap(),
1429                        funcs[*import][*resource].dtor_export.as_deref().unwrap(),
1430                        ExportKind::Func,
1431                    )
1432                }
1433            };
1434
1435            exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1436        }
1437
1438        let instance_index = self.component.core_instantiate_exports(exports);
1439        self.component.core_instantiate(
1440            self.fixups_module_index.expect("must have fixup module"),
1441            [("", ModuleArg::Instance(instance_index))],
1442        );
1443        Ok(())
1444    }
1445
1446    fn instantiate_core_module<'b, A>(&mut self, args: A, info: &ValidatedModule<'_>)
1447    where
1448        A: IntoIterator<Item = (&'b str, ModuleArg)>,
1449        A::IntoIter: ExactSizeIterator,
1450    {
1451        assert!(self.instance_index.is_none());
1452
1453        let instance_index = self
1454            .component
1455            .core_instantiate(self.module_index.expect("core module encoded"), args);
1456
1457        if info.has_memory {
1458            self.memory_index = Some(self.component.core_alias_export(
1459                instance_index,
1460                "memory",
1461                ExportKind::Memory,
1462            ));
1463        }
1464
1465        if let Some(name) = &info.realloc {
1466            self.realloc_index = Some(self.component.core_alias_export(
1467                instance_index,
1468                name,
1469                ExportKind::Func,
1470            ));
1471        }
1472
1473        self.instance_index = Some(instance_index);
1474    }
1475
1476    fn encode_resource_dtors<'b>(
1477        &mut self,
1478        module: CustomModule<'b>,
1479        funcs: &'b IndexMap<String, IndexMap<String, ResourceInfo>>,
1480        signatures: &mut Vec<WasmSignature>,
1481        shims: &mut Shims<'b>,
1482    ) {
1483        // Any resource destructors are encoded through the shim module. The
1484        // core wasm probably imports resource intrinsics which requires the
1485        // resource definition, but the resource definition requires
1486        // the destructor to be available. The shim module breaks this
1487        // circular dependency.
1488        for (import, info) in funcs.iter() {
1489            for (resource, info) in info {
1490                if info.dtor_export.is_none() {
1491                    continue;
1492                }
1493                signatures.push(WasmSignature {
1494                    params: vec![WasmType::I32],
1495                    results: Vec::new(),
1496                    indirect_params: false,
1497                    retptr: false,
1498                });
1499                let name = shims.list.len().to_string();
1500                shims.list.push(Shim {
1501                    name,
1502                    debug_name: format!("dtor-{import}-{resource}"),
1503                    options: RequiredOptions::empty(),
1504                    kind: ShimKind::ResourceDtor {
1505                        module,
1506                        import,
1507                        resource,
1508                    },
1509                });
1510            }
1511        }
1512    }
1513
1514    fn add_resource_funcs<'b>(
1515        &mut self,
1516        module: CustomModule<'b>,
1517        funcs: &'b IndexMap<String, IndexMap<String, ResourceInfo>>,
1518        shims: &Shims,
1519        args: &mut Vec<(&'b str, ModuleArg)>,
1520    ) {
1521        for (import, info) in funcs {
1522            let mut exports = Vec::new();
1523            for (resource, info) in info {
1524                // Destructors for resources live on the shim module previously
1525                // created, so if one is specified create the resource with
1526                // the shim module that currently exists. The shim will get
1527                // filled in later with the actual destructor after the main
1528                // module is instantiated.
1529                let dtor = info.dtor_export.as_deref().map(|_| {
1530                    self.component.core_alias_export(
1531                        self.shim_instance_index.unwrap(),
1532                        &shims.shim_names[&ShimKind::ResourceDtor {
1533                            module,
1534                            import,
1535                            resource,
1536                        }],
1537                        ExportKind::Func,
1538                    )
1539                });
1540                let resource_idx = self.component.type_resource(ValType::I32, dtor);
1541                let prev = self.export_type_map.insert(info.id, resource_idx);
1542                assert!(prev.is_none());
1543
1544                if let Some(name) = info.drop_import.as_deref() {
1545                    let index = self.component.resource_drop(resource_idx);
1546                    exports.push((name, ExportKind::Func, index));
1547                }
1548                if let Some(name) = info.rep_import.as_deref() {
1549                    let index = self.component.resource_rep(resource_idx);
1550                    exports.push((name, ExportKind::Func, index));
1551                }
1552                if let Some(name) = info.new_import.as_deref() {
1553                    let index = self.component.resource_new(resource_idx);
1554                    exports.push((name, ExportKind::Func, index));
1555                }
1556            }
1557            if !exports.is_empty() {
1558                let index = self.component.core_instantiate_exports(exports);
1559                args.push((import.as_str(), ModuleArg::Instance(index)));
1560            }
1561        }
1562    }
1563
1564    /// This function will instantiate the specified adapter module, which may
1565    /// depend on previously-instantiated modules.
1566    fn instantiate_adapter_module(
1567        &mut self,
1568        shims: &Shims<'_>,
1569        name: &'a str,
1570        adapter: &WorldAdapter,
1571    ) {
1572        let mut args = Vec::new();
1573
1574        let mut core_exports = Vec::new();
1575        for export_name in adapter.info.needs_core_exports.iter() {
1576            let mut core_export_name = export_name.as_str();
1577            // provide cabi_realloc_adapter as cabi_realloc to adapters
1578            // if it exists
1579            if export_name == "cabi_realloc" {
1580                if let Some(adapter_realloc) = self.info.info.adapter_realloc {
1581                    core_export_name = adapter_realloc;
1582                }
1583            }
1584            let index = self.component.core_alias_export(
1585                self.instance_index
1586                    .expect("adaptee index set at this point"),
1587                core_export_name,
1588                ExportKind::Func,
1589            );
1590            core_exports.push((export_name.as_str(), ExportKind::Func, index));
1591        }
1592        if !core_exports.is_empty() {
1593            let instance = self.component.core_instantiate_exports(core_exports);
1594            args.push((MAIN_MODULE_IMPORT_NAME, ModuleArg::Instance(instance)));
1595        }
1596        // The adapter may either be a library or a "minimal" adapter.  If it's
1597        // the former, we use `LibraryInfo::arguments` to populate inter-module
1598        // instantiation arguments.
1599        if let Some(library_info) = adapter.library_info {
1600            for (import_name, instance) in &library_info.arguments {
1601                let resolve = |which: &_| match which {
1602                    MainOrAdapter::Main => self.instance_index.unwrap(),
1603                    MainOrAdapter::Adapter(adapter_name) => *self
1604                        .adapter_instances
1605                        .get(adapter_name.as_str())
1606                        .unwrap_or_else(|| {
1607                            panic!(
1608                                "adapter {name} needs {adapter_name}, \
1609                                     which has not yet been instantiated"
1610                            )
1611                        }),
1612                };
1613
1614                args.push((
1615                    import_name,
1616                    ModuleArg::Instance(match instance {
1617                        Instance::MainOrAdapter(which) => resolve(which),
1618                        Instance::Items(items) => {
1619                            let exports = items
1620                                .iter()
1621                                .map(|item| {
1622                                    (
1623                                        item.alias.as_str(),
1624                                        item.kind,
1625                                        self.component.core_alias_export(
1626                                            resolve(&item.which),
1627                                            &item.name,
1628                                            item.kind,
1629                                        ),
1630                                    )
1631                                })
1632                                .collect::<Vec<_>>();
1633                            self.component.core_instantiate_exports(exports)
1634                        }
1635                    }),
1636                ));
1637            }
1638        } else {
1639            // If the adapter module requires a `memory` import then specify
1640            // that here. For now assume that the module name of the memory is
1641            // different from the imported interface. That's true enough for now
1642            // since it's `env::memory`.
1643            if let Some((module, name)) = &adapter.info.needs_memory {
1644                for (import_name, _) in adapter.info.required_imports.iter() {
1645                    assert!(module != import_name);
1646                }
1647                assert!(module != name);
1648                let memory = self.memory_index.unwrap();
1649                let instance = self.component.core_instantiate_exports([(
1650                    name.as_str(),
1651                    ExportKind::Memory,
1652                    memory,
1653                )]);
1654                args.push((module.as_str(), ModuleArg::Instance(instance)));
1655            }
1656        }
1657        for (import_name, _) in adapter.info.required_imports.iter() {
1658            let instance = self.import_instance_to_lowered_core_instance(
1659                CustomModule::Adapter(name),
1660                import_name,
1661                shims,
1662                adapter.info.metadata,
1663            );
1664            args.push((import_name, ModuleArg::Instance(instance)));
1665        }
1666
1667        self.add_resource_funcs(
1668            CustomModule::Adapter(name),
1669            &adapter.info.required_resource_funcs,
1670            shims,
1671            &mut args,
1672        );
1673
1674        let instance = self
1675            .component
1676            .core_instantiate(self.adapter_modules[name], args);
1677        self.adapter_instances.insert(name, instance);
1678
1679        let realloc = adapter.info.export_realloc.as_ref().map(|name| {
1680            self.component
1681                .core_alias_export(instance, name, ExportKind::Func)
1682        });
1683        self.adapter_export_reallocs.insert(name, realloc);
1684        let realloc = adapter.info.import_realloc.as_ref().map(|name| {
1685            self.component
1686                .core_alias_export(instance, name, ExportKind::Func)
1687        });
1688        self.adapter_import_reallocs.insert(name, realloc);
1689    }
1690}
1691
1692/// A list of "shims" which start out during the component instantiation process
1693/// as functions which immediately trap due to a `call_indirect`-to-`null` but
1694/// will get filled in by the time the component instantiation process
1695/// completes.
1696///
1697/// Shims currently include:
1698///
1699/// * "Indirect functions" lowered from imported instances where the lowering
1700///   requires an item exported from the main module. These are indirect due to
1701///   the circular dependency between the module needing an import and the
1702///   import needing the module.
1703///
1704/// * Adapter modules which convert from a historical ABI to the component
1705///   model's ABI (e.g. wasi preview1 to preview2) get a shim since the adapters
1706///   are currently indicated as always requiring the memory of the main module.
1707///
1708/// This structure is created by `encode_shim_instantiation`.
1709#[derive(Default)]
1710struct Shims<'a> {
1711    /// The list of all shims that a module will require.
1712    list: Vec<Shim<'a>>,
1713
1714    /// A map from a shim to the name of the shim in the shim instance.
1715    shim_names: IndexMap<ShimKind<'a>, String>,
1716}
1717
1718struct Shim<'a> {
1719    /// Canonical ABI options required by this shim, used during `canon lower`
1720    /// operations.
1721    options: RequiredOptions,
1722
1723    /// The name, in the shim instance, of this shim.
1724    ///
1725    /// Currently this is `"0"`, `"1"`, ...
1726    name: String,
1727
1728    /// A human-readable debugging name for this shim, used in a core wasm
1729    /// `name` section.
1730    debug_name: String,
1731
1732    /// Precise information about what this shim is a lowering of.
1733    kind: ShimKind<'a>,
1734}
1735
1736#[derive(Debug, Clone, Hash, Eq, PartialEq)]
1737enum ShimKind<'a> {
1738    /// This shim is a late indirect lowering of an imported function in a
1739    /// component which is only possible after prior core wasm modules are
1740    /// instantiated so their memories and functions are available.
1741    IndirectLowering {
1742        /// The name of the interface that's being lowered.
1743        interface: Option<String>,
1744        /// The index within the `lowerings` array of the function being lowered.
1745        index: usize,
1746        /// Which instance to pull the `realloc` function from, if necessary.
1747        realloc: CustomModule<'a>,
1748        /// The string encoding that this lowering is going to use.
1749        encoding: StringEncoding,
1750    },
1751    /// This shim is a core wasm function defined in an adapter module but isn't
1752    /// available until the adapter module is itself instantiated.
1753    Adapter {
1754        /// The name of the adapter module this shim comes from.
1755        adapter: &'a str,
1756        /// The name of the export in the adapter module this shim points to.
1757        func: &'a str,
1758    },
1759    /// A shim used as the destructor for a resource which allows defining the
1760    /// resource before the core module being instantiated.
1761    ResourceDtor {
1762        /// Which instance to pull the destructor function from.
1763        module: CustomModule<'a>,
1764        /// The import that the resource was defined for.
1765        import: &'a str,
1766        /// The name of the resource being destroyed.
1767        resource: &'a str,
1768    },
1769}
1770
1771/// Indicator for which module is being used for a lowering or where options
1772/// like `realloc` are drawn from.
1773///
1774/// This is necessary for situations such as an imported function being lowered
1775/// into the main module and additionally into an adapter module. For example an
1776/// adapter might adapt from preview1 to preview2 for the standard library of a
1777/// programming language but the main module's custom application code may also
1778/// explicitly import from preview2. These two different lowerings of a preview2
1779/// function are parameterized by this enumeration.
1780#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
1781enum CustomModule<'a> {
1782    /// This points to the "main module" which is generally the "output of LLVM"
1783    /// or what a user wrote.
1784    Main,
1785    /// This is selecting an adapter module, identified by name here, where
1786    /// something is being lowered into.
1787    Adapter(&'a str),
1788}
1789
1790impl<'a> Shims<'a> {
1791    /// Adds all shims necessary for the `import` provided, namely iterating
1792    /// over its indirect lowerings and appending a shim per lowering.
1793    fn append_indirect(
1794        &mut self,
1795        core_wasm_module: &'a str,
1796        for_module: CustomModule<'a>,
1797        import: &ImportedInterface,
1798        required: &IndexSet<String>,
1799        metadata: &ModuleMetadata,
1800        sigs: &mut Vec<WasmSignature>,
1801    ) -> Result<()> {
1802        let interface = if core_wasm_module == BARE_FUNC_MODULE_NAME {
1803            None
1804        } else {
1805            Some(core_wasm_module.to_string())
1806        };
1807        for (index, (name, lowering)) in import.lowerings.iter().enumerate() {
1808            if !required.contains(name.as_str()) {
1809                continue;
1810            }
1811            let shim_name = self.list.len().to_string();
1812            log::debug!(
1813                "shim {shim_name} is import `{core_wasm_module}` lowering {index} `{name}`",
1814            );
1815            match lowering {
1816                Lowering::Direct | Lowering::ResourceDrop(_) => {}
1817
1818                Lowering::Indirect { sig, options } => {
1819                    sigs.push(sig.clone());
1820                    let encoding = *metadata
1821                        .import_encodings
1822                        .get(&(core_wasm_module.to_string(), name.clone()))
1823                        .ok_or_else(|| {
1824                            anyhow::anyhow!(
1825                                "missing component metadata for import of \
1826                                `{core_wasm_module}::{name}`"
1827                            )
1828                        })?;
1829                    self.list.push(Shim {
1830                        name: shim_name,
1831                        debug_name: format!("indirect-{core_wasm_module}-{name}"),
1832                        options: *options,
1833                        kind: ShimKind::IndirectLowering {
1834                            interface: interface.clone(),
1835                            index,
1836                            realloc: for_module,
1837                            encoding,
1838                        },
1839                    });
1840                }
1841            }
1842        }
1843        Ok(())
1844    }
1845}
1846
1847/// Alias argument to an instantiation
1848#[derive(Clone)]
1849pub struct Item {
1850    pub alias: String,
1851    pub kind: ExportKind,
1852    pub which: MainOrAdapter,
1853    pub name: String,
1854}
1855
1856/// Module argument to an instantiation
1857#[derive(Clone)]
1858pub enum MainOrAdapter {
1859    Main,
1860    Adapter(String),
1861}
1862
1863/// Module instantiation argument
1864#[derive(Clone)]
1865pub enum Instance {
1866    /// Module argument
1867    MainOrAdapter(MainOrAdapter),
1868
1869    /// Alias argument
1870    Items(Vec<Item>),
1871}
1872
1873/// Provides fine-grained control of how a library module is instantiated
1874/// relative to other module instances
1875#[derive(Clone)]
1876pub struct LibraryInfo {
1877    /// If true, instantiate any shims prior to this module
1878    pub instantiate_after_shims: bool,
1879
1880    /// Instantiation arguments
1881    pub arguments: Vec<(String, Instance)>,
1882}
1883
1884/// Represents an adapter or library to be instantiated as part of the component
1885struct Adapter {
1886    /// The wasm of the module itself, with `component-type` sections stripped
1887    wasm: Vec<u8>,
1888
1889    /// The metadata for the adapter
1890    metadata: ModuleMetadata,
1891
1892    /// The set of exports from the final world which are defined by this
1893    /// adapter or library
1894    required_exports: IndexSet<WorldKey>,
1895
1896    /// If present, treat this module as a library rather than a "minimal" adapter
1897    ///
1898    /// TODO: We should refactor how various flavors of module are represented
1899    /// and differentiated to avoid mistaking one for another.
1900    library_info: Option<LibraryInfo>,
1901}
1902
1903/// An encoder of components based on `wit` interface definitions.
1904#[derive(Default)]
1905pub struct ComponentEncoder {
1906    module: Vec<u8>,
1907    metadata: Bindgen,
1908    validate: bool,
1909    main_module_exports: IndexSet<WorldKey>,
1910    adapters: IndexMap<String, Adapter>,
1911    import_name_map: HashMap<String, String>,
1912    realloc_via_memory_grow: bool,
1913}
1914
1915impl ComponentEncoder {
1916    /// Set the core module to encode as a component.
1917    /// This method will also parse any component type information stored in custom sections
1918    /// inside the module, and add them as the interface, imports, and exports.
1919    /// It will also add any producers information inside the component type information to the
1920    /// core module.
1921    pub fn module(mut self, module: &[u8]) -> Result<Self> {
1922        let (wasm, metadata) = metadata::decode(module)?;
1923        let world = self
1924            .metadata
1925            .merge(metadata)
1926            .context("failed merge WIT metadata for module with previous metadata")?;
1927        self.main_module_exports
1928            .extend(self.metadata.resolve.worlds[world].exports.keys().cloned());
1929        self.module = if let Some(producers) = &self.metadata.producers {
1930            producers.add_to_wasm(&wasm)?
1931        } else {
1932            wasm
1933        };
1934        Ok(self)
1935    }
1936
1937    /// Sets whether or not the encoder will validate its output.
1938    pub fn validate(mut self, validate: bool) -> Self {
1939        self.validate = validate;
1940        self
1941    }
1942
1943    /// Specifies a new adapter which is used to translate from a historical
1944    /// wasm ABI to the canonical ABI and the `interface` provided.
1945    ///
1946    /// This is primarily used to polyfill, for example,
1947    /// `wasi_snapshot_preview1` with a component-model using interface. The
1948    /// `name` provided is the module name of the adapter that is being
1949    /// polyfilled, for example `"wasi_snapshot_preview1"`.
1950    ///
1951    /// The `bytes` provided is a core wasm module which implements the `name`
1952    /// interface in terms of the `interface` interface. This core wasm module
1953    /// is severely restricted in its shape, for example it cannot have any data
1954    /// segments or element segments.
1955    ///
1956    /// The `interface` provided is the component-model-using-interface that the
1957    /// wasm module specified by `bytes` imports. The `bytes` will then import
1958    /// `interface` and export functions to get imported from the module `name`
1959    /// in the core wasm that's being wrapped.
1960    pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
1961        self.library_or_adapter(name, bytes, None)
1962    }
1963
1964    /// Specifies a shared-everything library to link into the component.
1965    ///
1966    /// Unlike adapters, libraries _may_ have data and/or element segments, but
1967    /// they must operate on an imported memory and table, respectively.  In
1968    /// this case, the correct amount of space is presumed to have been
1969    /// statically allocated in the main module's memory and table at the
1970    /// offsets which the segments target, e.g. as arranged by
1971    /// [super::linking::Linker].
1972    ///
1973    /// Libraries are treated similarly to adapters, except that they are not
1974    /// "minified" the way adapters are, and instantiation is controlled
1975    /// declaratively via the `library_info` parameter.
1976    pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
1977        self.library_or_adapter(name, bytes, Some(library_info))
1978    }
1979
1980    fn library_or_adapter(
1981        mut self,
1982        name: &str,
1983        bytes: &[u8],
1984        library_info: Option<LibraryInfo>,
1985    ) -> Result<Self> {
1986        let (wasm, metadata) = metadata::decode(bytes)?;
1987        // Merge the adapter's document into our own document to have one large
1988        // document, and then afterwards merge worlds as well.
1989        //
1990        // The first `merge` operation will interleave equivalent packages from
1991        // each adapter into packages that are stored within our own resolve.
1992        // The second `merge_worlds` operation will then ensure that both the
1993        // adapter and the main module have compatible worlds, meaning that they
1994        // either import the same items or they import disjoint items, for
1995        // example.
1996        let world = self
1997            .metadata
1998            .resolve
1999            .merge(metadata.resolve)
2000            .with_context(|| {
2001                format!("failed to merge WIT packages of adapter `{name}` into main packages")
2002            })?
2003            .worlds[metadata.world.index()];
2004        self.metadata
2005            .resolve
2006            .merge_worlds(world, self.metadata.world)
2007            .with_context(|| {
2008                format!("failed to merge WIT world of adapter `{name}` into main package")
2009            })?;
2010        let exports = self.metadata.resolve.worlds[world]
2011            .exports
2012            .keys()
2013            .cloned()
2014            .collect();
2015        if let Some(library_info) = &library_info {
2016            // Validate that all referenced modules can be resolved.
2017            for (_, instance) in &library_info.arguments {
2018                let resolve = |which: &_| match which {
2019                    MainOrAdapter::Main => Ok(()),
2020                    MainOrAdapter::Adapter(name) => {
2021                        if self.adapters.contains_key(name.as_str()) {
2022                            Ok(())
2023                        } else {
2024                            Err(anyhow!("instance refers to unknown adapter `{name}`"))
2025                        }
2026                    }
2027                };
2028
2029                match instance {
2030                    Instance::MainOrAdapter(which) => resolve(which)?,
2031                    Instance::Items(items) => {
2032                        for item in items {
2033                            resolve(&item.which)?;
2034                        }
2035                    }
2036                }
2037            }
2038        }
2039        self.adapters.insert(
2040            name.to_string(),
2041            Adapter {
2042                wasm,
2043                metadata: metadata.metadata,
2044                required_exports: exports,
2045                library_info,
2046            },
2047        );
2048        Ok(self)
2049    }
2050
2051    /// True if the realloc and stack allocation should use memory.grow
2052    /// The default is to use the main module realloc
2053    /// Can be useful if cabi_realloc cannot be called before the host
2054    /// runtime is initialized.
2055    pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
2056        self.realloc_via_memory_grow = value;
2057        self
2058    }
2059
2060    /// The instance import name map to use.
2061    ///
2062    /// This is used to rename instance imports in the final component.
2063    ///
2064    /// For example, if there is an instance import `foo:bar/baz` and it is
2065    /// desired that the import actually be an `unlocked-dep` name, then
2066    /// `foo:bar/baz` can be mapped to `unlocked-dep=<a:b/c@{>=x.y.z}>`.
2067    ///
2068    /// Note: the replacement names are not validated during encoding unless
2069    /// the `validate` option is set to true.
2070    pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
2071        self.import_name_map = map;
2072        self
2073    }
2074
2075    /// Encode the component and return the bytes.
2076    pub fn encode(&self) -> Result<Vec<u8>> {
2077        if self.module.is_empty() {
2078            bail!("a module is required when encoding a component");
2079        }
2080
2081        let world = ComponentWorld::new(self).context("failed to decode world from module")?;
2082        let mut state = EncodingState {
2083            component: ComponentBuilder::default(),
2084            module_index: None,
2085            instance_index: None,
2086            memory_index: None,
2087            realloc_index: None,
2088            shim_instance_index: None,
2089            fixups_module_index: None,
2090            adapter_modules: IndexMap::new(),
2091            adapter_instances: IndexMap::new(),
2092            adapter_import_reallocs: IndexMap::new(),
2093            adapter_export_reallocs: IndexMap::new(),
2094            import_type_map: HashMap::new(),
2095            import_func_type_map: HashMap::new(),
2096            export_type_map: HashMap::new(),
2097            export_func_type_map: HashMap::new(),
2098            imported_instances: Default::default(),
2099            imported_funcs: Default::default(),
2100            exported_instances: Default::default(),
2101            info: &world,
2102        };
2103        state.encode_imports(&self.import_name_map)?;
2104        state.encode_core_modules();
2105        state.encode_core_instantiation()?;
2106        state.encode_exports(CustomModule::Main)?;
2107        for name in self.adapters.keys() {
2108            state.encode_exports(CustomModule::Adapter(name))?;
2109        }
2110        state
2111            .component
2112            .raw_custom_section(&crate::base_producers().raw_custom_section());
2113        let bytes = state.component.finish();
2114
2115        if self.validate {
2116            let mut validator = Validator::new_with_features(
2117                WasmFeatures::default() | WasmFeatures::COMPONENT_MODEL,
2118            );
2119
2120            validator
2121                .validate_all(&bytes)
2122                .context("failed to validate component output")?;
2123        }
2124
2125        Ok(bytes)
2126    }
2127}
2128
2129#[cfg(all(test, feature = "dummy-module"))]
2130mod test {
2131    use crate::{dummy_module, embed_component_metadata};
2132
2133    use super::*;
2134    use std::path::Path;
2135    use wit_parser::UnresolvedPackage;
2136
2137    #[test]
2138    fn it_renames_imports() {
2139        let mut resolve = Resolve::new();
2140        let pkg = resolve
2141            .push(
2142                UnresolvedPackage::parse(
2143                    Path::new("test.wit"),
2144                    r#"
2145package test:wit;
2146
2147interface i {
2148    f: func();
2149}
2150
2151world test {
2152    import i;
2153    import foo: interface {
2154        f: func();
2155    }
2156}
2157"#,
2158                )
2159                .unwrap(),
2160            )
2161            .unwrap();
2162
2163        let world = resolve.select_world(pkg, None).unwrap();
2164
2165        let mut module = dummy_module(&resolve, world);
2166
2167        embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
2168
2169        let encoded = ComponentEncoder::default()
2170            .import_name_map(HashMap::from([
2171                (
2172                    "foo".to_string(),
2173                    "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
2174                ),
2175                (
2176                    "test:wit/i".to_string(),
2177                    "locked-dep=<foo:bar/i@1.2.3>".to_string(),
2178                ),
2179            ]))
2180            .module(&module)
2181            .unwrap()
2182            .validate(true)
2183            .encode()
2184            .unwrap();
2185
2186        let wat = wasmprinter::print_bytes(encoded).unwrap();
2187        assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
2188        assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
2189    }
2190}