wit_component/
encoding.rs

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