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
7pub 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 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 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}