wit_component/
encoding.rs

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