Skip to main content

wit_component/
encoding.rs

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