wit_component/
dummy.rs

1use wit_parser::abi::WasmType;
2use wit_parser::{
3    Function, LiftLowerAbi, ManglingAndAbi, Resolve, ResourceIntrinsic, TypeDefKind, TypeId,
4    WasmExport, WasmExportKind, WasmImport, WorldId, WorldItem, WorldKey,
5};
6
7/// Generate a dummy implementation core Wasm module for a given WIT document
8pub fn dummy_module(resolve: &Resolve, world: WorldId, mangling: ManglingAndAbi) -> Vec<u8> {
9    let world = &resolve.worlds[world];
10    let mut wat = String::new();
11    wat.push_str("(module\n");
12    for (name, import) in world.imports.iter() {
13        match import {
14            WorldItem::Function(func) => {
15                let sig = resolve.wasm_signature(mangling.import_variant(), func);
16
17                let (module, name) = resolve.wasm_import_name(
18                    mangling,
19                    WasmImport::Func {
20                        interface: None,
21                        func,
22                    },
23                );
24
25                wat.push_str(&format!("(import {module:?} {name:?} (func"));
26                push_tys(&mut wat, "param", &sig.params);
27                push_tys(&mut wat, "result", &sig.results);
28                wat.push_str("))\n");
29            }
30            WorldItem::Interface { id: import, .. } => {
31                for (_, func) in resolve.interfaces[*import].functions.iter() {
32                    let sig = resolve.wasm_signature(mangling.import_variant(), func);
33
34                    let (module, name) = resolve.wasm_import_name(
35                        mangling,
36                        WasmImport::Func {
37                            interface: Some(name),
38                            func,
39                        },
40                    );
41                    wat.push_str(&format!("(import {module:?} {name:?} (func"));
42                    push_tys(&mut wat, "param", &sig.params);
43                    push_tys(&mut wat, "result", &sig.results);
44                    wat.push_str("))\n");
45                }
46                for (_, ty) in resolve.interfaces[*import].types.iter() {
47                    push_resource_func_imports(&mut wat, resolve, Some(name), *ty, mangling);
48                }
49            }
50            WorldItem::Type(id) => {
51                push_resource_func_imports(&mut wat, resolve, None, *id, mangling);
52            }
53        }
54    }
55
56    // Import any resource-related functions for exports.
57    for (name, export) in world.exports.iter() {
58        let export = match export {
59            WorldItem::Interface { id, .. } => *id,
60            _ => continue,
61        };
62        for resource in resolve.interfaces[export].types.values().copied() {
63            let ty = &resolve.types[resource];
64            match ty.kind {
65                TypeDefKind::Resource => {}
66                _ => continue,
67            }
68            let intrinsics = [
69                (ResourceIntrinsic::ExportedDrop, "(func (param i32))"),
70                (
71                    ResourceIntrinsic::ExportedNew,
72                    "(func (param i32) (result i32))",
73                ),
74                (
75                    ResourceIntrinsic::ExportedRep,
76                    "(func (param i32) (result i32))",
77                ),
78            ];
79            for (intrinsic, sig) in intrinsics {
80                let (module, name) = resolve.wasm_import_name(
81                    mangling,
82                    WasmImport::ResourceIntrinsic {
83                        interface: Some(name),
84                        resource,
85                        intrinsic,
86                    },
87                );
88                wat.push_str(&format!("(import {module:?} {name:?} {sig})\n"));
89            }
90        }
91    }
92
93    for (name, export) in world.exports.iter() {
94        match export {
95            WorldItem::Function(func) => {
96                push_func_export(&mut wat, resolve, None, func, mangling);
97            }
98            WorldItem::Interface { id: export, .. } => {
99                for (_, func) in resolve.interfaces[*export].functions.iter() {
100                    push_func_export(&mut wat, resolve, Some(name), func, mangling);
101                }
102
103                // Feign destructors for any resource that this interface
104                // exports
105                for resource in resolve.interfaces[*export].types.values().copied() {
106                    let ty = &resolve.types[resource];
107                    match ty.kind {
108                        TypeDefKind::Resource => {}
109                        _ => continue,
110                    }
111                    let name = resolve.wasm_export_name(
112                        mangling,
113                        WasmExport::ResourceDtor {
114                            interface: name,
115                            resource,
116                        },
117                    );
118                    wat.push_str(&format!("(func (export {name:?}) (param i32))"));
119                }
120            }
121            WorldItem::Type(_) => {}
122        }
123    }
124
125    let memory = resolve.wasm_export_name(mangling, WasmExport::Memory);
126    wat.push_str(&format!("(memory (export {memory:?}) 0)\n"));
127    let realloc = resolve.wasm_export_name(mangling, WasmExport::Realloc);
128    wat.push_str(&format!(
129        "(func (export {realloc:?}) (param i32 i32 i32 i32) (result i32) unreachable)\n"
130    ));
131    let initialize = resolve.wasm_export_name(mangling, WasmExport::Initialize);
132    wat.push_str(&format!("(func (export {initialize:?}))"));
133    wat.push_str(")\n");
134
135    return wat::parse_str(&wat).unwrap();
136
137    fn push_resource_func_imports(
138        wat: &mut String,
139        resolve: &Resolve,
140        interface: Option<&WorldKey>,
141        resource: TypeId,
142        mangling: ManglingAndAbi,
143    ) {
144        let ty = &resolve.types[resource];
145        match ty.kind {
146            TypeDefKind::Resource => {}
147            _ => return,
148        }
149        let (module, name) = resolve.wasm_import_name(
150            mangling,
151            WasmImport::ResourceIntrinsic {
152                interface,
153                resource,
154                intrinsic: ResourceIntrinsic::ImportedDrop,
155            },
156        );
157        wat.push_str(&format!("(import {module:?} {name:?} (func (param i32)))"));
158    }
159
160    fn push_func_export(
161        wat: &mut String,
162        resolve: &Resolve,
163        interface: Option<&WorldKey>,
164        func: &Function,
165        mangling: ManglingAndAbi,
166    ) {
167        let sig = resolve.wasm_signature(mangling.export_variant(), func);
168        let name = resolve.wasm_export_name(
169            mangling,
170            WasmExport::Func {
171                interface,
172                func,
173                kind: WasmExportKind::Normal,
174            },
175        );
176        wat.push_str(&format!("(func (export \"{name}\")"));
177        push_tys(wat, "param", &sig.params);
178        push_tys(wat, "result", &sig.results);
179        wat.push_str(" unreachable)\n");
180
181        match mangling {
182            ManglingAndAbi::Standard32 | ManglingAndAbi::Legacy(LiftLowerAbi::Sync) => {
183                let name = resolve.wasm_export_name(
184                    mangling,
185                    WasmExport::Func {
186                        interface,
187                        func,
188                        kind: WasmExportKind::PostReturn,
189                    },
190                );
191                wat.push_str(&format!("(func (export \"{name}\")"));
192                push_tys(wat, "param", &sig.results);
193                wat.push_str(")\n");
194            }
195            ManglingAndAbi::Legacy(LiftLowerAbi::AsyncCallback) => {
196                let name = resolve.wasm_export_name(
197                    mangling,
198                    WasmExport::Func {
199                        interface,
200                        func,
201                        kind: WasmExportKind::Callback,
202                    },
203                );
204                wat.push_str(&format!(
205                    "(func (export \"{name}\") (param i32 i32 i32 i32) (result i32) unreachable)\n"
206                ));
207            }
208            ManglingAndAbi::Legacy(LiftLowerAbi::AsyncStackful) => {}
209        }
210    }
211
212    fn push_tys(dst: &mut String, desc: &str, params: &[WasmType]) {
213        if params.is_empty() {
214            return;
215        }
216        dst.push_str(" (");
217        dst.push_str(desc);
218        for ty in params {
219            dst.push(' ');
220            match ty {
221                WasmType::I32 => dst.push_str("i32"),
222                WasmType::I64 => dst.push_str("i64"),
223                WasmType::F32 => dst.push_str("f32"),
224                WasmType::F64 => dst.push_str("f64"),
225                WasmType::Pointer => dst.push_str("i32"),
226                WasmType::PointerOrI64 => dst.push_str("i64"),
227                WasmType::Length => dst.push_str("i32"),
228            }
229        }
230        dst.push(')');
231    }
232}