wit_dylib/
lib.rs

1use crate::metadata::Metadata;
2use std::borrow::Cow;
3use std::collections::{HashMap, HashSet};
4use std::mem;
5use wasm_encoder::{
6    CodeSection, ConstExpr, CustomSection, DataSection, ElementSection, Elements, Encode,
7    EntityType, ExportKind, ExportSection, Function, FunctionSection, GlobalType, ImportSection,
8    MemoryType, Module, NameMap, NameSection, RefType, TableType, TypeSection, ValType,
9};
10use wit_parser::abi::{WasmSignature, WasmType};
11use wit_parser::{
12    Handle, LiftLowerAbi, LiveTypes, ManglingAndAbi, Resolve, ResourceIntrinsic, SizeAlign, Type,
13    TypeDefKind, TypeId, TypeOwner, WasmExport, WasmExportKind, WasmImport, WorldId, WorldItem,
14    WorldKey,
15};
16
17mod async_;
18mod bindgen;
19mod metadata;
20pub use crate::async_::AsyncFilterSet;
21
22pub const C_HEADER: &'static str = include_str!("../wit_dylib.h");
23
24#[derive(Default, Clone, Debug)]
25#[cfg_attr(feature = "clap", derive(clap::Parser))]
26pub struct DylibOpts {
27    /// The interpreter name to insert into the `WASM_DYLINK_NEEDED` section
28    /// encoded as `dylink.0`.
29    #[cfg_attr(feature = "clap", clap(long))]
30    pub interpreter: Option<String>,
31
32    #[cfg_attr(feature = "clap", clap(flatten))]
33    pub async_: AsyncFilterSet,
34}
35
36pub fn create(resolve: &Resolve, world_id: WorldId, mut opts: Option<&mut DylibOpts>) -> Vec<u8> {
37    let mut adapter = Adapter::default();
38    if let Some(opts) = &mut opts {
39        adapter.opts = opts.clone();
40    }
41    let result = adapter.encode(resolve, world_id);
42    if let Some(opts) = &mut opts {
43        **opts = adapter.opts;
44    }
45    result
46}
47
48#[derive(Default)]
49struct Adapter {
50    types: TypeSection,
51    wasm_type_map: HashMap<(Vec<ValType>, Vec<ValType>), u32>,
52    imports: ImportSection,
53    imports_done: bool,
54    global_index: u32,
55    table_base: Option<u32>,
56    memory_base: Option<u32>,
57    stack_pointer: Option<u32>,
58    func_index: u32,
59    functions: FunctionSection,
60    exports: ExportSection,
61    code: CodeSection,
62    global_names: NameMap,
63    function_names: NameMap,
64    metadata: Metadata,
65    type_map: HashMap<TypeId, metadata::Type>,
66    resource_map: HashMap<TypeId, usize>,
67    export_resource_map: HashMap<TypeId, usize>,
68    intrinsics: Option<bindgen::WitInterpreterIntrinsics>,
69    sizes: SizeAlign,
70    opts: DylibOpts,
71
72    /// Contents of the element segment of this module, which will start at
73    /// `__table_base`.
74    ///
75    /// Elements of this list are function indices in this module which will be
76    /// placed into the element segment.
77    elem_segment: Vec<u32>,
78}
79
80#[derive(Default)]
81struct Imports<'a> {
82    wit_imports: Vec<WitImport<'a>>,
83    wit_exports: Vec<WitExport<'a>>,
84}
85
86struct WitImport<'a> {
87    interface: Option<&'a WorldKey>,
88    func: &'a wit_parser::Function,
89    import_index: u32,
90}
91
92struct WitExport<'a> {
93    interface: Option<&'a WorldKey>,
94    func: &'a wit_parser::Function,
95    async_task_return_index: Option<u32>,
96}
97
98impl Adapter {
99    pub fn encode(&mut self, resolve: &Resolve, world_id: WorldId) -> Vec<u8> {
100        self.sizes.fill(resolve);
101
102        // First define all imports that will go into the wasm module since
103        // they're required to be first in their index spaces anyway. This will
104        // import intrinsics necessary for exported resources, for example, as
105        // well.
106        let imports = self.add_imports(resolve, world_id);
107        self.imports_done = true;
108
109        // Ensure that `cabi_realloc` is reexported from our module to indicate
110        // that our module's allocations are routed through the same
111        // `cabi_realloc` we're importing.
112        let cabi_realloc = self.intrinsics().cabi_realloc;
113        self.exports
114            .export("cabi_realloc", ExportKind::Func, cabi_realloc);
115
116        // Generate/add metadata for all functions that are either imported or
117        // exported.
118        self.bindgen_world(resolve, world_id, &imports);
119
120        // Now that all functions have been learned about the metadata data
121        // segment can be finalized and emitted. Here this additionally invokes
122        // the interpreter initialization function as part of a ctor to ensure
123        // that the interpreter is aware of where metadata ended up in linear
124        // memory.
125        let (metadata_offset, metadata) = self.encode_metadata();
126        let mut ctor = Function::new([]);
127        ctor.instructions().i32_const(metadata_offset as i32);
128        ctor.instructions().global_get(self.memory_base());
129        ctor.instructions().i32_add();
130        ctor.instructions().call(self.intrinsics().initialize);
131        ctor.instructions().end();
132        let ty = self.define_ty([], []);
133        self.define_func("__wasm_call_ctors", ty, ctor, true);
134
135        self.finish(&metadata)
136    }
137
138    fn mangling(
139        &mut self,
140        resolve: &Resolve,
141        interface: Option<&WorldKey>,
142        func: &wit_parser::Function,
143        is_import: bool,
144    ) -> ManglingAndAbi {
145        let abi = if self
146            .opts
147            .async_
148            .is_async(resolve, interface, func, is_import)
149        {
150            LiftLowerAbi::AsyncCallback
151        } else {
152            LiftLowerAbi::Sync
153        };
154        ManglingAndAbi::Legacy(abi)
155    }
156
157    fn resource_intrinsic_mangling(&mut self) -> ManglingAndAbi {
158        ManglingAndAbi::Legacy(LiftLowerAbi::Sync)
159    }
160
161    fn add_imports<'a>(&mut self, resolve: &'a Resolve, world_id: WorldId) -> Imports<'a> {
162        let mut ret = Imports::default();
163        let world = &resolve.worlds[world_id];
164
165        // First up import everything from the interpreter itself that we're
166        // going to possibly need.
167        self.intrinsics = Some(bindgen::WitInterpreterIntrinsics::new(self));
168
169        // Generate function imports for all world imports, in addition to
170        // intrinsics for all resources imported as well. This will additionally
171        // populate the `Imports` return value with all functions that were
172        // found.
173        for (interface, import) in world.imports.iter() {
174            match import {
175                WorldItem::Interface { id, .. } => {
176                    for (_, func) in resolve.interfaces[*id].functions.iter() {
177                        self.add_imported_func(resolve, Some(interface), func, &mut ret);
178                    }
179                    for (_, ty) in resolve.interfaces[*id].types.iter() {
180                        self.add_imported_type_intrinsics(resolve, Some(interface), *ty);
181                    }
182                }
183                WorldItem::Type(ty) => {
184                    self.add_imported_type_intrinsics(resolve, None, *ty);
185                }
186                WorldItem::Function(func) => {
187                    self.add_imported_func(resolve, None, func, &mut ret);
188                }
189            }
190        }
191
192        // Exported resources need to have intrinsics imported for manipulation,
193        // so do so here.
194        for (name, export) in world.exports.iter() {
195            match export {
196                WorldItem::Function(func) => {
197                    self.add_imported_func_intrinsics_for_export(resolve, None, func, &mut ret);
198                }
199                WorldItem::Interface { id: export, .. } => {
200                    for (_, ty) in resolve.interfaces[*export].types.iter() {
201                        self.add_imported_type_intrinsics_for_export(resolve, Some(name), *ty);
202                    }
203                    for (_, func) in resolve.interfaces[*export].functions.iter() {
204                        self.add_imported_func_intrinsics_for_export(
205                            resolve,
206                            Some(name),
207                            func,
208                            &mut ret,
209                        );
210                    }
211                }
212                WorldItem::Type(_) => unreachable!(),
213            }
214        }
215
216        let const_i32_global = GlobalType {
217            val_type: ValType::I32,
218            mutable: false,
219            shared: false,
220        };
221        let mut_i32_global = GlobalType {
222            val_type: ValType::I32,
223            mutable: true,
224            shared: false,
225        };
226
227        self.table_base = Some(self.import_global("env", "__table_base", const_i32_global));
228        self.memory_base = Some(self.import_global("env", "__memory_base", const_i32_global));
229        self.stack_pointer = Some(self.import_global("env", "__stack_pointer", mut_i32_global));
230
231        self.imports.import(
232            "env",
233            "memory",
234            EntityType::Memory(MemoryType {
235                minimum: 0,
236                maximum: None,
237                memory64: false,
238                shared: false,
239                page_size_log2: None,
240            }),
241        );
242
243        self.imports.import(
244            "env",
245            "__indirect_function_table",
246            EntityType::Table(TableType {
247                element_type: RefType::FUNCREF,
248                minimum: 0,
249                maximum: None,
250                table64: false,
251                shared: false,
252            }),
253        );
254        ret
255    }
256
257    fn add_imported_func<'a>(
258        &mut self,
259        resolve: &'a Resolve,
260        interface: Option<&'a WorldKey>,
261        func: &'a wit_parser::Function,
262        imports: &mut Imports<'a>,
263    ) {
264        let mangling = self.mangling(resolve, interface, func, true);
265        let (module, name) =
266            resolve.wasm_import_name(mangling, WasmImport::Func { interface, func });
267        let sig = resolve.wasm_signature(mangling.import_variant(), func);
268        let ty = self.define_wasm_sig(sig);
269        let import_index = self.import_func(&module, &name, ty);
270        imports.wit_imports.push(WitImport {
271            func,
272            interface,
273            import_index,
274        });
275    }
276
277    fn add_imported_type_intrinsics<'a>(
278        &mut self,
279        resolve: &Resolve,
280        interface: Option<&'a WorldKey>,
281        id: TypeId,
282    ) {
283        let mangling = self.resource_intrinsic_mangling();
284        let ty = &resolve.types[id];
285        match ty.kind {
286            TypeDefKind::Resource => {
287                let (module, name) = resolve.wasm_import_name(
288                    mangling,
289                    WasmImport::ResourceIntrinsic {
290                        interface,
291                        resource: id,
292                        intrinsic: ResourceIntrinsic::ImportedDrop,
293                    },
294                );
295                let core_ty = self.define_ty([ValType::I32], []);
296                let drop = self.import_func(&module, &name, core_ty);
297                let drop_elem_index = self.push_elem(drop);
298                let resource_index = self.metadata.resources.len();
299                self.metadata.resources.push(metadata::Resource {
300                    interface: interface.map(|i| resolve.name_world_key(i)),
301                    name: ty.name.clone().unwrap(),
302                    drop_elem_index,
303                    new_elem_index: None,
304                    rep_elem_index: None,
305                });
306                let prev = self.resource_map.insert(id, resource_index);
307                assert!(prev.is_none());
308            }
309
310            // No other types with intrinsics at this time (futures/streams are
311            // relative to where they show up in function types.
312            _ => {}
313        }
314    }
315
316    fn add_imported_type_intrinsics_for_export<'a>(
317        &mut self,
318        resolve: &Resolve,
319        interface: Option<&'a WorldKey>,
320        id: TypeId,
321    ) {
322        let ty = &resolve.types[id];
323        let mangling = self.resource_intrinsic_mangling();
324        match ty.kind {
325            TypeDefKind::Resource => {
326                let drop_ty = self.define_ty([ValType::I32], []);
327                let new_rep_ty = self.define_ty([ValType::I32], [ValType::I32]);
328
329                let mut import = |ty, intrinsic| {
330                    let (module, name) = resolve.wasm_import_name(
331                        mangling,
332                        WasmImport::ResourceIntrinsic {
333                            interface,
334                            resource: id,
335                            intrinsic,
336                        },
337                    );
338                    self.import_func(&module, &name, ty)
339                };
340
341                let drop = import(drop_ty, ResourceIntrinsic::ExportedDrop);
342                let new = import(new_rep_ty, ResourceIntrinsic::ExportedNew);
343                let rep = import(new_rep_ty, ResourceIntrinsic::ExportedRep);
344
345                let drop_elem_index = self.push_elem(drop);
346                let new_elem_index = Some(self.push_elem(new));
347                let rep_elem_index = Some(self.push_elem(rep));
348
349                let resource_index = self.metadata.resources.len();
350                self.metadata.resources.push(metadata::Resource {
351                    interface: interface.map(|i| resolve.name_world_key(i)),
352                    name: ty.name.clone().unwrap(),
353                    drop_elem_index,
354                    new_elem_index,
355                    rep_elem_index,
356                });
357
358                // Note that this populates an `export_resource_map` instead of
359                // `resource_map` to ensure that if an interface is both
360                // imported and exported that we don't clobber the import
361                // version here. The clobber here happens later when bindings
362                // are generated for exports.
363                let prev = self.export_resource_map.insert(id, resource_index);
364                assert!(prev.is_none());
365            }
366
367            // No other types with intrinsics at this time (futures/streams
368            // relative to where they are in a function).
369            _ => {}
370        }
371    }
372
373    /// Adds `task.return` imports for async functions, and appends all
374    /// functions to `ret.wit_exports`.
375    fn add_imported_func_intrinsics_for_export<'a>(
376        &mut self,
377        resolve: &Resolve,
378        interface: Option<&'a WorldKey>,
379        func: &'a wit_parser::Function,
380        ret: &mut Imports<'a>,
381    ) {
382        let mangling = self.mangling(resolve, interface, func, false);
383        let async_task_return_index = if mangling.is_async() {
384            let (module, name, sig) =
385                func.task_return_import(resolve, interface, mangling.mangling());
386            let ty = self.define_wasm_sig(sig);
387            Some(self.import_func(&module, &name, ty))
388        } else {
389            None
390        };
391        ret.wit_exports.push(WitExport {
392            interface,
393            func,
394            async_task_return_index,
395        });
396    }
397
398    fn bindgen_world(&mut self, resolve: &Resolve, world_id: WorldId, imports: &Imports<'_>) {
399        let world = &resolve.worlds[world_id];
400
401        // Build up a map for all types of all imports. This pushes all type
402        // information into the metadata section that the interpreter will end
403        // up learning about.
404        let mut import_types = LiveTypes::default();
405        let mut interface_names = HashMap::new();
406        for (interface, import) in world.imports.iter() {
407            import_types.add_world_item(resolve, import);
408            if let WorldItem::Interface { id, .. } = import {
409                interface_names.insert(*id, interface);
410            }
411        }
412        for (_, export) in world.exports.iter() {
413            match export {
414                WorldItem::Function(func) => import_types.add_func(resolve, func),
415                WorldItem::Interface { .. } => {}
416                WorldItem::Type(_) => unreachable!(),
417            }
418        }
419        for ty in import_types.iter() {
420            let key = match resolve.types[ty].owner {
421                TypeOwner::Interface(id) => Some(interface_names[&id]),
422                _ => None,
423            };
424            self.register_type(resolve, key, ty);
425        }
426
427        // Using the populated type map for imports generate functions to invoke
428        // these imports. Also generate exported functions in the world since
429        // they use imported types as well.
430        for import in imports.wit_imports.iter() {
431            self.bindgen_world_func_import(resolve, import);
432        }
433        for export in imports.wit_exports.iter().filter(|i| i.interface.is_none()) {
434            self.bindgen_world_func_export(resolve, export);
435        }
436
437        // Next handle exported interfaces. This is a bit tricky since an
438        // interface can be both exported and imported. To handle that first the
439        // `type_map` set is pruned to only include imported types required, and
440        // then all exported types are added. Export types skip over all
441        // types present in `self.type_map`, though, since those are already
442        // retained from imports.
443        let to_keep = imported_types_used_by_exported_interfaces(resolve, world_id);
444        self.type_map.retain(|id, _| to_keep.contains(*id));
445        let mut exported_types = LiveTypes::default();
446        let mut export_names = HashMap::new();
447        for (interface, import) in world.exports.iter() {
448            if let WorldItem::Interface { id, .. } = import {
449                exported_types.add_world_item(resolve, import);
450                export_names.insert(*id, interface);
451            }
452        }
453        for (ty, index) in mem::take(&mut self.export_resource_map) {
454            self.resource_map.insert(ty, index);
455        }
456        for ty in exported_types.iter() {
457            if self.type_map.contains_key(&ty) {
458                continue;
459            }
460            let key = match resolve.types[ty].owner {
461                TypeOwner::Interface(id) => Some(export_names[&id]),
462                _ => None,
463            };
464            self.register_type(resolve, key, ty);
465
466            if let Some(index) = self.resource_map.get(&ty) {
467                self.bindgen_world_export_resource_dtor(resolve, key.unwrap(), ty, *index);
468            }
469        }
470
471        // With export types all in place now run bindgen for all exported
472        // functions.
473        for export in imports.wit_exports.iter().filter(|i| i.interface.is_some()) {
474            self.bindgen_world_func_export(resolve, export);
475        }
476    }
477
478    /// Push WIT type information into metadata for the interpreter.
479    ///
480    /// This will insert `id` into metadata and build up the interpreter data
481    /// structures for it. The end-result is the population of `self.type_map`
482    /// here.
483    fn register_type(&mut self, resolve: &Resolve, key: Option<&WorldKey>, id: TypeId) {
484        let ty = &resolve.types[id];
485        let interface = key.map(|key| resolve.name_world_key(key));
486        let name = ty.name.clone();
487        let result = match &ty.kind {
488            TypeDefKind::Record(r) => {
489                let index = self.metadata.records.len();
490                let fields = r
491                    .fields
492                    .iter()
493                    .map(|field| (field.name.clone(), self.lookup_ty(&field.ty)))
494                    .collect();
495                self.metadata.records.push(metadata::Record {
496                    interface,
497                    name: name.unwrap(),
498                    fields,
499                });
500                metadata::Type::Record(index)
501            }
502            TypeDefKind::Flags(t) => {
503                let index = self.metadata.flags.len();
504                let names = t.flags.iter().map(|f| f.name.clone()).collect();
505                self.metadata.flags.push(metadata::Flags {
506                    interface,
507                    name: name.unwrap(),
508                    names,
509                });
510                metadata::Type::Flags(index)
511            }
512            TypeDefKind::Tuple(t) => {
513                let index = self.metadata.tuples.len();
514                let types = t.types.iter().map(|t| self.lookup_ty(t)).collect();
515                self.metadata.tuples.push(metadata::Tuple {
516                    interface,
517                    name,
518                    types,
519                });
520                metadata::Type::Tuple(index)
521            }
522            TypeDefKind::Variant(t) => {
523                let index = self.metadata.variants.len();
524                let cases = t
525                    .cases
526                    .iter()
527                    .map(|c| (c.name.clone(), c.ty.map(|t| self.lookup_ty(&t))))
528                    .collect();
529                self.metadata.variants.push(metadata::Variant {
530                    interface,
531                    name: name.unwrap(),
532                    cases,
533                });
534                metadata::Type::Variant(index)
535            }
536            TypeDefKind::Enum(t) => {
537                let index = self.metadata.enums.len();
538                let names = t.cases.iter().map(|f| f.name.clone()).collect();
539                self.metadata.enums.push(metadata::Enum {
540                    interface,
541                    name: name.unwrap(),
542                    names,
543                });
544                metadata::Type::Enum(index)
545            }
546            TypeDefKind::Option(t) => {
547                let index = self.metadata.options.len();
548                self.metadata.options.push(metadata::WitOption {
549                    interface,
550                    name,
551                    ty: self.lookup_ty(t),
552                });
553                metadata::Type::Option(index)
554            }
555            TypeDefKind::Result(t) => {
556                let index = self.metadata.results.len();
557                self.metadata.results.push(metadata::WitResult {
558                    interface,
559                    name,
560                    ok: t.ok.map(|t| self.lookup_ty(&t)),
561                    err: t.err.map(|t| self.lookup_ty(&t)),
562                });
563                metadata::Type::Result(index)
564            }
565            TypeDefKind::List(t) => {
566                let index = self.metadata.lists.len();
567                self.metadata.lists.push(metadata::List {
568                    interface,
569                    name,
570                    ty: self.lookup_ty(t),
571                });
572                metadata::Type::List(index)
573            }
574            TypeDefKind::FixedSizeList(t, len) => {
575                let index = self.metadata.fixed_size_lists.len();
576                self.metadata
577                    .fixed_size_lists
578                    .push(metadata::FixedSizeList {
579                        interface,
580                        name,
581                        len: *len,
582                        ty: self.lookup_ty(t),
583                    });
584                metadata::Type::FixedSizeList(index)
585            }
586            TypeDefKind::Future(t) => {
587                let index = self.metadata.futures.len();
588                self.metadata.futures.push(metadata::Future {
589                    interface,
590                    name,
591                    ty: t.map(|t| self.lookup_ty(&t)),
592                });
593                metadata::Type::Future(index)
594            }
595            TypeDefKind::Stream(t) => {
596                let index = self.metadata.streams.len();
597                self.metadata.streams.push(metadata::Stream {
598                    interface,
599                    name,
600                    ty: t.map(|t| self.lookup_ty(&t)),
601                });
602                metadata::Type::Stream(index)
603            }
604            TypeDefKind::Type(t) => {
605                let index = self.metadata.aliases.len();
606                self.metadata.aliases.push(metadata::Alias {
607                    interface,
608                    name: name.unwrap(),
609                    ty: self.lookup_ty(t),
610                });
611                metadata::Type::Alias(index)
612            }
613            TypeDefKind::Resource => metadata::Type::Own(self.resource_map[&id]),
614
615            // Own/Borrow handles should have already inserted the resource into
616            // `self.resource_map` so this is just a simple lookup.
617            TypeDefKind::Handle(Handle::Own(t)) => {
618                metadata::Type::Own(self.resource_map[&dealias(resolve, *t)])
619            }
620            TypeDefKind::Handle(Handle::Borrow(t)) => {
621                metadata::Type::Borrow(self.resource_map[&dealias(resolve, *t)])
622            }
623            TypeDefKind::Unknown => unreachable!(),
624        };
625        self.type_map.insert(id, result);
626    }
627
628    fn lookup_ty(&self, ty: &Type) -> metadata::Type {
629        match ty {
630            Type::U8 => metadata::Type::U8,
631            Type::U16 => metadata::Type::U16,
632            Type::U32 => metadata::Type::U32,
633            Type::U64 => metadata::Type::U64,
634            Type::S8 => metadata::Type::S8,
635            Type::S16 => metadata::Type::S16,
636            Type::S32 => metadata::Type::S32,
637            Type::S64 => metadata::Type::S64,
638            Type::F32 => metadata::Type::F32,
639            Type::F64 => metadata::Type::F64,
640            Type::Bool => metadata::Type::Bool,
641            Type::Char => metadata::Type::Char,
642            Type::String => metadata::Type::String,
643            Type::ErrorContext => metadata::Type::ErrorContext,
644            // All id-based types should already be registered via
645            // `register_type` so the hard work is already done and this is a
646            // simple lookup.
647            Type::Id(id) => self.type_map[id],
648        }
649    }
650
651    fn bindgen_world_func_import(&mut self, resolve: &Resolve, import: &WitImport<'_>) {
652        let func = import.func;
653        let mangling = self.mangling(resolve, import.interface, func, true);
654        let body = bindgen::import(
655            self,
656            resolve,
657            func,
658            mangling.import_variant(),
659            import.import_index,
660        );
661
662        let ty = if mangling.is_async() {
663            // [ cx abi_area_ptr ] -> [ status ]
664            self.define_ty([ValType::I32; 2], [ValType::I32])
665        } else {
666            // [ cx ] -> []
667            self.define_ty([ValType::I32], [])
668        };
669
670        let idx = self.define_func(&format!("adapter {}", func.name), ty, body, false);
671        let elem_index = self.push_elem(idx);
672
673        let sync_import_elem_index;
674        let async_import_elem_index;
675        let async_import_lift_results_elem_index;
676
677        if mangling.is_async() {
678            sync_import_elem_index = None;
679            async_import_elem_index = Some(elem_index);
680            let body =
681                bindgen::lift_async_import_results(self, resolve, func, mangling.import_variant());
682            let ty = self.define_ty([ValType::I32; 2], []);
683            let idx = self.define_func(&format!("lift results {}", func.name), ty, body, false);
684            async_import_lift_results_elem_index = Some(self.push_elem(idx));
685        } else {
686            sync_import_elem_index = Some(elem_index);
687            async_import_elem_index = None;
688            async_import_lift_results_elem_index = None;
689        }
690
691        self.metadata.funcs.push(metadata::Func {
692            interface: import.interface.map(|k| resolve.name_world_key(k)),
693            name: func.name.clone(),
694            sync_import_elem_index,
695            async_import_elem_index,
696            async_import_lift_results_elem_index,
697            async_export_task_return_elem_index: None,
698            args: func
699                .params
700                .iter()
701                .map(|(_, ty)| self.lookup_ty(ty))
702                .collect(),
703            result: func.result.map(|t| self.lookup_ty(&t)),
704            async_abi_area: self.async_import_abi_area(resolve, mangling, func),
705        })
706    }
707
708    /// Returns the `(size, align)` for the indirect params/results as necessary
709    /// for `func` if `func` is an async function.
710    fn async_import_abi_area(
711        &self,
712        resolve: &Resolve,
713        mangling: ManglingAndAbi,
714        func: &wit_parser::Function,
715    ) -> Option<(usize, usize)> {
716        if !mangling.is_async() {
717            return None;
718        }
719
720        let info = self
721            .sizes
722            .record(bindgen::async_import_abi_area_types(resolve, func));
723        Some((info.size.size_wasm32(), info.align.align_wasm32()))
724    }
725
726    fn bindgen_world_func_export(&mut self, resolve: &Resolve, export: &WitExport<'_>) {
727        let func = export.func;
728        let mangling = self.mangling(resolve, export.interface, func, false);
729        let sig = resolve.wasm_signature(mangling.export_variant(), func);
730        let ty = self.define_wasm_sig(sig);
731        let name = resolve.wasm_export_name(
732            mangling,
733            WasmExport::Func {
734                interface: export.interface,
735                func,
736                kind: WasmExportKind::Normal,
737            },
738        );
739
740        let metadata_func_index = self.metadata.funcs.len();
741        let body = bindgen::export(
742            self,
743            resolve,
744            func,
745            mangling.export_variant(),
746            metadata_func_index,
747        );
748        self.define_func(&name, ty, body, true);
749
750        let mut async_export_task_return_elem_index = None;
751        match mangling {
752            // For sync functions a post-return function is generated which
753            // cleans up the `cx` argument notably but also any list allocations
754            // and such as required.
755            ManglingAndAbi::Standard32 | ManglingAndAbi::Legacy(LiftLowerAbi::Sync) => {
756                let post_return_name = resolve.wasm_export_name(
757                    mangling,
758                    WasmExport::Func {
759                        interface: export.interface,
760                        func,
761                        kind: WasmExportKind::PostReturn,
762                    },
763                );
764                let post_return = bindgen::post_return(
765                    self,
766                    resolve,
767                    func,
768                    mangling.export_variant(),
769                    metadata_func_index,
770                );
771                let mut sig = resolve.wasm_signature(mangling.export_variant(), func);
772                sig.params = mem::take(&mut sig.results);
773                let post_return_ty = self.define_wasm_sig(sig);
774                self.define_func(&post_return_name, post_return_ty, post_return, true);
775            }
776
777            // For async exports in addition to the main entrypoint a
778            // `[callback]` function is generated which is invoked when progress
779            // is made on this function.
780            //
781            // Additionally a `task.return` function is generated to be invoked
782            // once the async export has completed.
783            ManglingAndAbi::Legacy(LiftLowerAbi::AsyncCallback) => {
784                let callback_name = resolve.wasm_export_name(
785                    mangling,
786                    WasmExport::Func {
787                        interface: export.interface,
788                        func,
789                        kind: WasmExportKind::Callback,
790                    },
791                );
792                // The `[callback]` function is pretty simple, just delegate to
793                // the `wit_dylib_*` implementation with one extra contextual
794                // argument. It's the responsibility of the implementation to
795                // call `context.{get,set}` as appropriate.
796                let mut callback = Function::new([]);
797                let mut ins = callback.instructions();
798                ins.local_get(0);
799                ins.local_get(1);
800                ins.local_get(2);
801                ins.i32_const(metadata_func_index.try_into().unwrap());
802                let export_async_callback = self.intrinsics().export_async_callback;
803                ins.call(export_async_callback);
804                ins.end();
805                let callback_ty = self.define_ty([ValType::I32; 3], [ValType::I32]);
806                self.define_func(&callback_name, callback_ty, callback, true);
807
808                let task_return = bindgen::task_return(
809                    self,
810                    resolve,
811                    func,
812                    mangling.export_variant(),
813                    export.async_task_return_index.unwrap(),
814                );
815                let task_return_ty = self.define_ty([ValType::I32], []);
816                let task_return = self.define_func(
817                    &format!("task.return {}", func.name),
818                    task_return_ty,
819                    task_return,
820                    false,
821                );
822                async_export_task_return_elem_index = Some(self.push_elem(task_return));
823            }
824
825            ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful) => unimplemented!(),
826        }
827
828        self.metadata.funcs.push(metadata::Func {
829            interface: export.interface.map(|k| resolve.name_world_key(k)),
830            name: func.name.clone(),
831            sync_import_elem_index: None,
832            async_import_elem_index: None,
833            async_import_lift_results_elem_index: None,
834            async_export_task_return_elem_index,
835            args: func
836                .params
837                .iter()
838                .map(|(_, ty)| self.lookup_ty(ty))
839                .collect(),
840            result: func.result.map(|t| self.lookup_ty(&t)),
841            async_abi_area: None,
842        })
843    }
844
845    fn bindgen_world_export_resource_dtor(
846        &mut self,
847        resolve: &Resolve,
848        interface: &WorldKey,
849        resource: TypeId,
850        index: usize,
851    ) {
852        let mangling = self.resource_intrinsic_mangling();
853        let name = resolve.wasm_export_name(
854            mangling,
855            WasmExport::ResourceDtor {
856                interface,
857                resource,
858            },
859        );
860        let dtor = self.intrinsics().resource_dtor;
861        let mut func = Function::new([]);
862        let mut ins = func.instructions();
863        ins.i32_const(index.try_into().unwrap());
864        ins.local_get(0);
865        ins.call(dtor);
866        ins.end();
867        let ty = self.define_ty([ValType::I32], []);
868        self.define_func(&name, ty, func, true);
869    }
870
871    fn encode_metadata(&mut self) -> (u32, Vec<u8>) {
872        let (metadata_offset, metadata, apply_relocs) =
873            self.metadata.encode(self.table_base(), self.memory_base());
874        if let Some(apply_relocs) = apply_relocs {
875            let ty = self.define_ty([], []);
876            self.define_func("__wasm_apply_data_relocs", ty, apply_relocs, true);
877        }
878        (metadata_offset, metadata)
879    }
880
881    fn table_base(&self) -> u32 {
882        self.table_base.unwrap()
883    }
884
885    fn intrinsics(&self) -> &bindgen::WitInterpreterIntrinsics {
886        self.intrinsics.as_ref().unwrap()
887    }
888
889    fn stack_pointer(&self) -> u32 {
890        self.stack_pointer.unwrap()
891    }
892
893    fn memory_base(&self) -> u32 {
894        self.memory_base.unwrap()
895    }
896
897    fn push_elem(&mut self, elem: u32) -> u32 {
898        let ret = self.elem_segment.len();
899        self.elem_segment.push(elem);
900        u32::try_from(ret).unwrap()
901    }
902
903    fn finish(&mut self, metadata: &[u8]) -> Vec<u8> {
904        // Create the element segment dynamically added to the table, if necessary.
905        let mut elements = ElementSection::new();
906        if !self.elem_segment.is_empty() {
907            elements.active(
908                Some(0),
909                &ConstExpr::global_get(self.table_base()),
910                Elements::Functions(Cow::Borrowed(&self.elem_segment)),
911            );
912        }
913
914        // Add a data segment for the interpreter metadata encoded data in-memory.
915        let mut data = DataSection::new();
916        data.active(
917            0,
918            &ConstExpr::global_get(self.memory_base()),
919            metadata.iter().copied(),
920        );
921
922        let mut names = NameSection::new();
923        names.functions(&self.function_names);
924        names.globals(&self.global_names);
925
926        let dylink0 = {
927            struct MemInfo {
928                memory_size: u32,
929                memory_alignment: u32,
930                table_size: u32,
931                table_alignment: u32,
932            }
933
934            let mem_info = MemInfo {
935                memory_size: metadata.len().try_into().unwrap(),
936                memory_alignment: 2,
937                table_size: self.elem_segment.len().try_into().unwrap(),
938                table_alignment: 0,
939            };
940
941            let mut mem_info_subsection = Vec::new();
942            mem_info.memory_size.encode(&mut mem_info_subsection);
943            mem_info.memory_alignment.encode(&mut mem_info_subsection);
944            mem_info.table_size.encode(&mut mem_info_subsection);
945            mem_info.table_alignment.encode(&mut mem_info_subsection);
946
947            let mut needed_subsection = Vec::new();
948            if let Some(name) = &self.opts.interpreter {
949                [name.as_str()].encode(&mut needed_subsection);
950            }
951
952            const WASM_DYLINK_MEM_INFO: u8 = 1;
953            const WASM_DYLINK_NEEDED: u8 = 2;
954
955            let mut dylink0 = Vec::new();
956            dylink0.push(WASM_DYLINK_MEM_INFO);
957            mem_info_subsection.encode(&mut dylink0);
958            if self.opts.interpreter.is_some() {
959                dylink0.push(WASM_DYLINK_NEEDED);
960                needed_subsection.encode(&mut dylink0);
961            }
962            dylink0
963        };
964
965        let mut result = Module::new();
966        result.section(&CustomSection {
967            name: Cow::Borrowed("dylink.0"),
968            data: Cow::Borrowed(&dylink0),
969        });
970        result.section(&self.types);
971        result.section(&self.imports);
972        result.section(&self.functions);
973        result.section(&self.exports);
974        if !elements.is_empty() {
975            result.section(&elements);
976        }
977        result.section(&self.code);
978        result.section(&data);
979        result.section(&names);
980
981        result.finish()
982    }
983
984    fn define_wasm_sig(&mut self, sig: WasmSignature) -> u32 {
985        let ret = self.define_ty(
986            sig.params
987                .iter()
988                .map(|t| self.map_wasm_type(*t))
989                .collect::<Vec<_>>(),
990            sig.results
991                .iter()
992                .map(|t| self.map_wasm_type(*t))
993                .collect::<Vec<_>>(),
994        );
995        return ret;
996    }
997
998    fn map_wasm_type(&self, a: WasmType) -> ValType {
999        match a {
1000            WasmType::I32 => ValType::I32,
1001            WasmType::I64 => ValType::I64,
1002            WasmType::F32 => ValType::F32,
1003            WasmType::F64 => ValType::F64,
1004            WasmType::PointerOrI64 => ValType::I64,
1005            WasmType::Length | WasmType::Pointer => ValType::I32,
1006        }
1007    }
1008
1009    fn import_global(&mut self, module: &str, name: &str, ty: GlobalType) -> u32 {
1010        assert!(!self.imports_done);
1011        self.imports.import(module, name, ty);
1012        let ret = self.global_index;
1013        self.global_index += 1;
1014        self.global_names.append(ret, name);
1015        ret
1016    }
1017
1018    fn import_func(&mut self, module: &str, name: &str, ty: u32) -> u32 {
1019        assert!(!self.imports_done);
1020        self.imports.import(module, name, EntityType::Function(ty));
1021        let ret = self.func_index;
1022        self.func_index += 1;
1023        self.function_names.append(ret, name);
1024        ret
1025    }
1026
1027    fn define_func(&mut self, name: &str, ty: u32, body: Function, export: bool) -> u32 {
1028        assert!(self.imports_done);
1029        let ret = self.func_index;
1030        self.func_index += 1;
1031        self.functions.function(ty);
1032        self.code.function(&body);
1033        self.function_names.append(ret, name);
1034        if export {
1035            self.exports.export(name, ExportKind::Func, ret);
1036        }
1037        ret
1038    }
1039
1040    fn define_ty<P, R>(&mut self, params: P, results: R) -> u32
1041    where
1042        P: IntoIterator<Item = ValType> + Clone,
1043        P::IntoIter: ExactSizeIterator,
1044        R: IntoIterator<Item = ValType> + Clone,
1045        R::IntoIter: ExactSizeIterator,
1046    {
1047        let param_vec = params.clone().into_iter().collect::<Vec<_>>();
1048        let result_vec = results.clone().into_iter().collect::<Vec<_>>();
1049        *self
1050            .wasm_type_map
1051            .entry((param_vec, result_vec))
1052            .or_insert_with(|| {
1053                let ret = self.types.len();
1054                self.types.ty().function(params, results);
1055                ret
1056            })
1057    }
1058}
1059
1060fn imported_types_used_by_exported_interfaces(resolve: &Resolve, world: WorldId) -> LiveTypes {
1061    // First build up a set of all types used by exported interfaces which
1062    // define their own types.
1063    let mut live_export_types = LiveTypes::default();
1064    let mut exported_interfaces = HashSet::new();
1065    for (_, export) in resolve.worlds[world].exports.iter() {
1066        match export {
1067            WorldItem::Function(_) => {}
1068            WorldItem::Interface { id, .. } => {
1069                exported_interfaces.insert(*id);
1070                live_export_types.add_interface(resolve, *id)
1071            }
1072            WorldItem::Type(_) => unreachable!(),
1073        }
1074    }
1075
1076    // Using the above sets a new set is built of all types that aren't
1077    // reexported. All types used by exports, which are defined by an interface
1078    // that is NOT an export, is an imported type used by an export.
1079    let mut live_import_types = LiveTypes::default();
1080    for ty in live_export_types.iter() {
1081        if let TypeOwner::Interface(id) = resolve.types[ty].owner {
1082            if !exported_interfaces.contains(&id) {
1083                live_import_types.add_interface(resolve, id);
1084            }
1085        }
1086    }
1087
1088    live_import_types
1089}
1090
1091fn dealias(resolve: &Resolve, mut id: TypeId) -> TypeId {
1092    loop {
1093        match resolve.types[id].kind {
1094            TypeDefKind::Type(Type::Id(other)) => id = other,
1095            _ => break id,
1096        }
1097    }
1098}