Skip to main content

wit_component/
encoding.rs

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