Coverage Report

Created: 2026-10-31 07:49

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