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