]>
Commit | Line | Data |
---|---|---|
446cb3f1 DG |
1 | use heck::ShoutySnakeCase; |
2 | use witx::*; | |
3 | ||
c6f2c051 | 4 | pub fn to_c_header(doc: &Document, inputs_str: &str) -> String { |
cd74e1d9 DG |
5 | let mut ret = String::new(); |
6 | ||
7 | ret.push_str(&format!( | |
8 | r#"/** | |
9 | * THIS FILE IS AUTO-GENERATED from the following files: | |
10 | * {} | |
446cb3f1 DG |
11 | * |
12 | * @file | |
cd74e1d9 | 13 | * This file describes the [WASI] interface, consisting of functions, types, |
446cb3f1 DG |
14 | * and defined values (macros). |
15 | * | |
16 | * The interface described here is greatly inspired by [CloudABI]'s clean, | |
37c663f2 | 17 | * thoughtfully-designed, capability-oriented, POSIX-style API. |
446cb3f1 DG |
18 | * |
19 | * [CloudABI]: https://github.com/NuxiNL/cloudlibc | |
cd74e1d9 | 20 | * [WASI]: https://github.com/WebAssembly/WASI/ |
446cb3f1 DG |
21 | */ |
22 | ||
23 | #ifndef __wasi_api_h | |
24 | #define __wasi_api_h | |
25 | ||
26 | #ifndef __wasi__ | |
27 | #error <wasi/api.h> is only supported on WASI platforms. | |
28 | #endif | |
29 | ||
c6f2c051 PH |
30 | #ifndef __wasm32__ |
31 | #error <wasi/api.h> only supports wasm32; doesn't yet support wasm64 | |
32 | #endif | |
33 | ||
446cb3f1 DG |
34 | #include <stddef.h> |
35 | #include <stdint.h> | |
36 | ||
37 | _Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); | |
38 | _Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); | |
39 | _Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); | |
40 | _Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); | |
41 | _Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); | |
42 | _Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); | |
43 | _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); | |
44 | _Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); | |
c6f2c051 | 45 | _Static_assert(_Alignof(void*) == 4, "non-wasi data layout"); |
446cb3f1 DG |
46 | |
47 | #ifdef __cplusplus | |
cd74e1d9 | 48 | extern "C" {{ |
446cb3f1 DG |
49 | #endif |
50 | ||
51 | // TODO: Encoding this in witx. | |
52 | #define __WASI_DIRCOOKIE_START (UINT64_C(0)) | |
cd74e1d9 DG |
53 | "#, |
54 | inputs_str, | |
55 | )); | |
446cb3f1 | 56 | |
fe130532 PH |
57 | for nt in doc.typenames() { |
58 | print_datatype(&mut ret, &*nt); | |
446cb3f1 DG |
59 | } |
60 | ||
61 | for m in doc.modules() { | |
fe130532 | 62 | print_module(&mut ret, &m); |
446cb3f1 DG |
63 | } |
64 | ||
cd74e1d9 DG |
65 | ret.push_str( |
66 | r#"#ifdef __cplusplus | |
67 | } | |
68 | #endif | |
69 | ||
70 | #endif | |
71 | "#, | |
72 | ); | |
446cb3f1 DG |
73 | |
74 | ret | |
75 | } | |
76 | ||
fe130532 PH |
77 | fn print_datatype(ret: &mut String, nt: &NamedType) { |
78 | if !nt.docs.is_empty() { | |
446cb3f1 | 79 | ret.push_str("/**\n"); |
fe130532 | 80 | for line in nt.docs.lines() { |
446cb3f1 DG |
81 | ret.push_str(&format!(" * {}\n", line)); |
82 | } | |
83 | ret.push_str(" */\n"); | |
84 | } | |
85 | ||
ec86d4de | 86 | match &nt.tref { |
fe130532 PH |
87 | TypeRef::Value(v) => match &**v { |
88 | Type::Enum(e) => print_enum(ret, &nt.name, e), | |
ec86d4de | 89 | Type::Int(i) => print_int(ret, &nt.name, i), |
fe130532 PH |
90 | Type::Flags(f) => print_flags(ret, &nt.name, f), |
91 | Type::Struct(s) => print_struct(ret, &nt.name, s), | |
92 | Type::Union(u) => print_union(ret, &nt.name, u), | |
93 | Type::Handle(h) => print_handle(ret, &nt.name, h), | |
94 | Type::Builtin { .. } | |
95 | | Type::Array { .. } | |
96 | | Type::Pointer { .. } | |
ec86d4de | 97 | | Type::ConstPointer { .. } => print_alias(ret, &nt.name, &nt.tref), |
fe130532 | 98 | }, |
ec86d4de | 99 | TypeRef::Name(_) => print_alias(ret, &nt.name, &nt.tref), |
446cb3f1 DG |
100 | } |
101 | } | |
102 | ||
fe130532 PH |
103 | fn print_alias(ret: &mut String, name: &Id, dest: &TypeRef) { |
104 | match &*dest.type_() { | |
105 | Type::Array(_) => { | |
446cb3f1 DG |
106 | // Don't emit arrays as top-level types; instead we special-case |
107 | // them in places like parameter lists so that we can pass them | |
108 | // as pointer and length pairs. | |
109 | } | |
110 | _ => { | |
fe130532 | 111 | if name.as_str() == "size" { |
446cb3f1 DG |
112 | // Special-case "size" as "__SIZE_TYPE__" -- TODO: Encode this in witx. |
113 | ret.push_str(&format!( | |
114 | "typedef __SIZE_TYPE__ __wasi_{}_t;\n", | |
fe130532 | 115 | ident_name(name) |
446cb3f1 DG |
116 | )); |
117 | } else { | |
118 | ret.push_str(&format!( | |
119 | "typedef {} __wasi_{}_t;\n", | |
fe130532 PH |
120 | typeref_name(dest), |
121 | ident_name(name) | |
446cb3f1 DG |
122 | )); |
123 | } | |
124 | ret.push_str("\n"); | |
c6f2c051 PH |
125 | |
126 | ret.push_str(&format!( | |
127 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
128 | ident_name(name), | |
129 | dest.mem_size_align().size | |
130 | )); | |
131 | ret.push_str(&format!( | |
132 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
133 | ident_name(name), | |
134 | dest.mem_size_align().align | |
135 | )); | |
136 | ||
137 | ret.push_str("\n"); | |
446cb3f1 DG |
138 | } |
139 | } | |
140 | } | |
141 | ||
fe130532 | 142 | fn print_enum(ret: &mut String, name: &Id, e: &EnumDatatype) { |
446cb3f1 DG |
143 | ret.push_str(&format!( |
144 | "typedef {} __wasi_{}_t;\n", | |
145 | intrepr_name(e.repr), | |
fe130532 | 146 | ident_name(name) |
446cb3f1 DG |
147 | )); |
148 | ret.push_str("\n"); | |
149 | ||
150 | for (index, variant) in e.variants.iter().enumerate() { | |
151 | if !variant.docs.is_empty() { | |
152 | ret.push_str("/**\n"); | |
153 | for line in variant.docs.lines() { | |
154 | ret.push_str(&format!(" * {}\n", line)); | |
155 | } | |
156 | ret.push_str(" */\n"); | |
157 | } | |
158 | ret.push_str(&format!( | |
dd010bee | 159 | "#define __WASI_{}_{} ({}({}))\n", |
fe130532 | 160 | ident_name(&name).to_shouty_snake_case(), |
446cb3f1 | 161 | ident_name(&variant.name).to_shouty_snake_case(), |
dd010bee | 162 | intrepr_const(e.repr), |
446cb3f1 DG |
163 | index |
164 | )); | |
165 | ret.push_str("\n"); | |
166 | } | |
c6f2c051 PH |
167 | |
168 | ret.push_str(&format!( | |
169 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
170 | ident_name(name), | |
171 | e.repr.mem_size() | |
172 | )); | |
173 | ret.push_str(&format!( | |
174 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
175 | ident_name(name), | |
176 | e.repr.mem_align() | |
177 | )); | |
178 | ||
179 | ret.push_str("\n"); | |
446cb3f1 DG |
180 | } |
181 | ||
ec86d4de PH |
182 | fn print_int(ret: &mut String, name: &Id, i: &IntDatatype) { |
183 | ret.push_str(&format!( | |
184 | "typedef {} __wasi_{}_t;\n", | |
185 | intrepr_name(i.repr), | |
186 | ident_name(name) | |
187 | )); | |
188 | ret.push_str("\n"); | |
189 | ||
190 | for (index, const_) in i.consts.iter().enumerate() { | |
191 | if !const_.docs.is_empty() { | |
192 | ret.push_str("/**\n"); | |
193 | for line in const_.docs.lines() { | |
194 | ret.push_str(&format!(" * {}\n", line)); | |
195 | } | |
196 | ret.push_str(" */\n"); | |
197 | } | |
198 | ret.push_str(&format!( | |
199 | "#define __WASI_{}_{} ({}({}))\n", | |
200 | ident_name(&name).to_shouty_snake_case(), | |
201 | ident_name(&const_.name).to_shouty_snake_case(), | |
202 | intrepr_const(i.repr), | |
203 | index | |
204 | )); | |
205 | ret.push_str("\n"); | |
206 | } | |
207 | ||
208 | ret.push_str(&format!( | |
209 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
210 | ident_name(name), | |
211 | i.repr.mem_size() | |
212 | )); | |
213 | ret.push_str(&format!( | |
214 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
215 | ident_name(name), | |
216 | i.repr.mem_align() | |
217 | )); | |
218 | ||
219 | ret.push_str("\n"); | |
220 | } | |
221 | ||
fe130532 | 222 | fn print_flags(ret: &mut String, name: &Id, f: &FlagsDatatype) { |
446cb3f1 DG |
223 | ret.push_str(&format!( |
224 | "typedef {} __wasi_{}_t;\n", | |
225 | intrepr_name(f.repr), | |
fe130532 | 226 | ident_name(name) |
446cb3f1 DG |
227 | )); |
228 | ret.push_str("\n"); | |
229 | ||
230 | for (index, flag) in f.flags.iter().enumerate() { | |
231 | if !flag.docs.is_empty() { | |
232 | ret.push_str("/**\n"); | |
233 | for line in flag.docs.lines() { | |
234 | ret.push_str(&format!(" * {}\n", line)); | |
235 | } | |
236 | ret.push_str(" */\n"); | |
237 | } | |
238 | ret.push_str(&format!( | |
dd010bee | 239 | "#define __WASI_{}_{} ({}({}))\n", |
fe130532 | 240 | ident_name(name).to_shouty_snake_case(), |
446cb3f1 | 241 | ident_name(&flag.name).to_shouty_snake_case(), |
dd010bee | 242 | intrepr_const(f.repr), |
446cb3f1 DG |
243 | 1u128 << index |
244 | )); | |
245 | ret.push_str("\n"); | |
246 | } | |
c6f2c051 PH |
247 | |
248 | ret.push_str(&format!( | |
249 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
250 | ident_name(name), | |
251 | f.repr.mem_size(), | |
252 | )); | |
253 | ret.push_str(&format!( | |
254 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
255 | ident_name(name), | |
256 | f.repr.mem_align(), | |
257 | )); | |
258 | ||
259 | ret.push_str("\n"); | |
446cb3f1 DG |
260 | } |
261 | ||
fe130532 | 262 | fn print_struct(ret: &mut String, name: &Id, s: &StructDatatype) { |
446cb3f1 DG |
263 | ret.push_str(&format!( |
264 | "typedef struct __wasi_{}_t {{\n", | |
fe130532 | 265 | ident_name(name) |
446cb3f1 DG |
266 | )); |
267 | ||
268 | for member in &s.members { | |
269 | if !member.docs.is_empty() { | |
270 | ret.push_str(" /**\n"); | |
271 | for line in member.docs.lines() { | |
272 | ret.push_str(&format!(" * {}\n", line)); | |
273 | } | |
274 | ret.push_str(" */\n"); | |
275 | } | |
276 | ret.push_str(&format!( | |
277 | " {} {};\n", | |
fe130532 | 278 | typeref_name(&member.tref), |
446cb3f1 DG |
279 | ident_name(&member.name) |
280 | )); | |
281 | ret.push_str("\n"); | |
282 | } | |
283 | ||
fe130532 | 284 | ret.push_str(&format!("}} __wasi_{}_t;\n", ident_name(name))); |
446cb3f1 | 285 | ret.push_str("\n"); |
c6f2c051 PH |
286 | |
287 | ret.push_str(&format!( | |
288 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
289 | ident_name(name), | |
290 | s.mem_size() | |
291 | )); | |
292 | ret.push_str(&format!( | |
293 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
294 | ident_name(name), | |
295 | s.mem_align() | |
296 | )); | |
297 | ||
298 | for layout in s.member_layout() { | |
299 | ret.push_str(&format!( | |
300 | "_Static_assert(offsetof(__wasi_{}_t, {}) == {}, \"witx calculated offset\");\n", | |
301 | ident_name(name), | |
302 | ident_name(&layout.member.name), | |
303 | layout.offset | |
304 | )); | |
305 | } | |
306 | ||
307 | ret.push_str("\n"); | |
446cb3f1 DG |
308 | } |
309 | ||
fe130532 | 310 | fn print_union(ret: &mut String, name: &Id, u: &UnionDatatype) { |
71d279a4 PH |
311 | ret.push_str(&format!( |
312 | "typedef union __wasi_{}_u_t {{\n", | |
313 | ident_name(name) | |
314 | )); | |
446cb3f1 DG |
315 | |
316 | for variant in &u.variants { | |
71d279a4 PH |
317 | if let Some(ref tref) = variant.tref { |
318 | if !variant.docs.is_empty() { | |
319 | ret.push_str(" /**\n"); | |
320 | for line in variant.docs.lines() { | |
321 | ret.push_str(&format!(" * {}\n", line)); | |
322 | } | |
323 | ret.push_str(" */\n"); | |
446cb3f1 | 324 | } |
71d279a4 PH |
325 | ret.push_str(&format!( |
326 | " {} {};\n", | |
327 | typeref_name(tref), | |
328 | ident_name(&variant.name) | |
329 | )); | |
446cb3f1 | 330 | } |
446cb3f1 | 331 | } |
71d279a4 PH |
332 | ret.push_str(&format!("}} __wasi_{}_u_t;\n", ident_name(name))); |
333 | ||
334 | ret.push_str(&format!( | |
335 | "typedef struct __wasi_{}_t {{\n", | |
336 | ident_name(name) | |
337 | )); | |
338 | ||
d415ae65 | 339 | ret.push_str(&format!(" {} tag;\n", namedtype_name(&u.tag))); |
71d279a4 | 340 | ret.push_str(&format!(" __wasi_{}_u_t u;\n", ident_name(name))); |
446cb3f1 | 341 | |
fe130532 | 342 | ret.push_str(&format!("}} __wasi_{}_t;\n", ident_name(name))); |
446cb3f1 | 343 | ret.push_str("\n"); |
c6f2c051 PH |
344 | |
345 | ret.push_str(&format!( | |
346 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
347 | ident_name(name), | |
348 | u.mem_size() | |
349 | )); | |
350 | ret.push_str(&format!( | |
351 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
352 | ident_name(name), | |
353 | u.mem_align() | |
354 | )); | |
355 | ||
71d279a4 PH |
356 | let l = u.union_layout(); |
357 | ret.push_str(&format!( | |
358 | "_Static_assert(offsetof(__wasi_{}_t, u) == {}, \"witx calculated union offset\");\n", | |
359 | ident_name(name), | |
360 | l.contents_offset, | |
361 | )); | |
362 | ret.push_str(&format!( | |
363 | "_Static_assert(sizeof(__wasi_{}_u_t) == {}, \"witx calculated union size\");\n", | |
364 | ident_name(name), | |
365 | l.contents_size, | |
366 | )); | |
367 | ret.push_str(&format!( | |
368 | "_Static_assert(_Alignof(__wasi_{}_u_t) == {}, \"witx calculated union align\");\n", | |
369 | ident_name(name), | |
370 | l.contents_align, | |
371 | )); | |
372 | ||
c6f2c051 | 373 | ret.push_str("\n"); |
446cb3f1 DG |
374 | } |
375 | ||
c6f2c051 | 376 | fn print_handle(ret: &mut String, name: &Id, h: &HandleDatatype) { |
e2bdce89 | 377 | ret.push_str(&format!("typedef int __wasi_{}_t;\n\n", ident_name(name))); |
c6f2c051 PH |
378 | |
379 | ret.push_str(&format!( | |
380 | "_Static_assert(sizeof(__wasi_{}_t) == {}, \"witx calculated size\");\n", | |
381 | ident_name(name), | |
382 | h.mem_size() | |
383 | )); | |
384 | ret.push_str(&format!( | |
385 | "_Static_assert(_Alignof(__wasi_{}_t) == {}, \"witx calculated align\");\n", | |
386 | ident_name(name), | |
387 | h.mem_align() | |
388 | )); | |
389 | ||
390 | ret.push_str("\n"); | |
446cb3f1 DG |
391 | } |
392 | ||
fe130532 | 393 | fn print_module(ret: &mut String, m: &Module) { |
446cb3f1 DG |
394 | ret.push_str("/**\n"); |
395 | ret.push_str(&format!(" * @defgroup {}\n", ident_name(&m.name),)); | |
396 | for line in m.docs.lines() { | |
397 | ret.push_str(&format!(" * {}\n", line)); | |
398 | } | |
399 | ret.push_str(" * @{\n"); | |
400 | ret.push_str(" */\n"); | |
401 | ret.push_str("\n"); | |
402 | ||
403 | for func in m.funcs() { | |
fe130532 | 404 | print_func(ret, &func, &m.name); |
446cb3f1 DG |
405 | } |
406 | ||
407 | ret.push_str("/** @} */\n"); | |
408 | ret.push_str("\n"); | |
409 | } | |
410 | ||
fe130532 | 411 | fn print_func(ret: &mut String, func: &InterfaceFunc, module_name: &Id) { |
446cb3f1 DG |
412 | if !func.docs.is_empty() { |
413 | ret.push_str("/**\n"); | |
414 | for line in func.docs.lines() { | |
415 | ret.push_str(&format!(" * {}\n", line)); | |
416 | } | |
417 | if !func.results.is_empty() { | |
418 | let first_result = &func.results[0]; | |
419 | if !first_result.docs.is_empty() { | |
420 | ret.push_str(" * @return\n"); | |
421 | for line in first_result.docs.lines() { | |
422 | ret.push_str(&format!(" * {}", line)); | |
423 | } | |
424 | } | |
425 | } | |
426 | ret.push_str(" */\n"); | |
427 | } | |
428 | if func.results.is_empty() { | |
429 | // Special-case "proc_exit" as _Noreturn -- TODO: Encode this in witx. | |
430 | if func.name.as_str() == "proc_exit" { | |
431 | ret.push_str("_Noreturn "); | |
432 | } | |
433 | ret.push_str("void "); | |
434 | } else { | |
435 | let first_result = &func.results[0]; | |
fe130532 | 436 | ret.push_str(&format!("{} ", typeref_name(&first_result.tref))); |
446cb3f1 DG |
437 | } |
438 | ||
439 | ret.push_str(&format!("__wasi_{}(\n", ident_name(&func.name))); | |
440 | ||
441 | if func.params.is_empty() && func.results.len() <= 1 { | |
442 | ret.push_str(" void\n"); | |
443 | } | |
444 | for (index, param) in func.params.iter().enumerate() { | |
445 | if !param.docs.is_empty() { | |
446 | ret.push_str(" /**\n"); | |
447 | for line in param.docs.lines() { | |
448 | ret.push_str(&format!(" * {}\n", line)); | |
449 | } | |
450 | ret.push_str(" */\n"); | |
451 | } | |
fe130532 | 452 | add_params(ret, &ident_name(¶m.name), ¶m.tref); |
446cb3f1 DG |
453 | ret.push_str(&format!( |
454 | "{}\n", | |
455 | if index + 1 < func.params.len() || func.results.len() > 1 { | |
456 | ",\n" | |
457 | } else { | |
458 | "" | |
459 | } | |
460 | )); | |
461 | } | |
462 | ||
463 | for (index, result) in func.results.iter().enumerate() { | |
464 | if index == 0 { | |
465 | // The first result is returned by value above. | |
466 | continue; | |
467 | } | |
468 | if !result.docs.is_empty() { | |
469 | ret.push_str(" /**\n"); | |
470 | for line in result.docs.lines() { | |
471 | ret.push_str(&format!(" * {}\n", line)); | |
472 | } | |
473 | ret.push_str(" */\n"); | |
474 | } | |
475 | ret.push_str(&format!( | |
476 | " {} *{}{}\n", | |
fe130532 | 477 | typeref_name(&result.tref), |
446cb3f1 DG |
478 | ident_name(&result.name), |
479 | if index + 1 < func.results.len() { | |
480 | "," | |
481 | } else { | |
482 | "" | |
483 | } | |
484 | )); | |
485 | } | |
486 | ||
487 | ret.push_str(") __attribute__((\n"); | |
488 | ret.push_str(&format!( | |
489 | " __import_module__(\"{}\"),\n", | |
490 | ident_name(module_name) | |
491 | )); | |
492 | ret.push_str(&format!( | |
493 | " __import_name__(\"{}\")", | |
494 | ident_name(&func.name) | |
495 | )); | |
496 | if !func.results.is_empty() { | |
497 | ret.push_str(",\n __warn_unused_result__\n"); | |
498 | } | |
499 | ret.push_str("));\n"); | |
500 | ret.push_str("\n"); | |
501 | } | |
502 | ||
fe130532 PH |
503 | fn add_params(ret: &mut String, name: &str, tref: &TypeRef) { |
504 | match &*tref.type_() { | |
505 | Type::Builtin(BuiltinType::String) => { | |
446cb3f1 DG |
506 | ret.push_str(&format!(" const char *{},\n", name)); |
507 | ret.push_str("\n"); | |
508 | ret.push_str(" /**\n"); | |
509 | ret.push_str(&format!( | |
510 | " * The length of the buffer pointed to by `{}`.\n", | |
511 | name, | |
512 | )); | |
513 | ret.push_str(" */\n"); | |
514 | ret.push_str(&format!(" size_t {}_len", name)); | |
515 | } | |
fe130532 | 516 | Type::Array(element) => { |
446cb3f1 DG |
517 | ret.push_str(&format!( |
518 | " const {} *{},\n", | |
fe130532 | 519 | typeref_name(&element), |
446cb3f1 DG |
520 | name |
521 | )); | |
522 | ret.push_str("\n"); | |
523 | ret.push_str(" /**\n"); | |
524 | ret.push_str(&format!( | |
525 | " * The length of the array pointed to by `{}`.\n", | |
526 | name, | |
527 | )); | |
528 | ret.push_str(" */\n"); | |
529 | ret.push_str(&format!(" size_t {}_len", name)); | |
530 | } | |
531 | _ => { | |
fe130532 | 532 | ret.push_str(&format!(" {} {}", typeref_name(tref), name)); |
446cb3f1 DG |
533 | } |
534 | } | |
535 | } | |
536 | ||
537 | fn ident_name(i: &Id) -> String { | |
538 | i.as_str().to_string() | |
539 | } | |
540 | ||
541 | fn builtin_type_name(b: BuiltinType) -> &'static str { | |
542 | match b { | |
ec86d4de PH |
543 | BuiltinType::String | BuiltinType::Char8 => { |
544 | panic!("no type name for string or char8 builtins") | |
545 | } | |
546 | BuiltinType::USize => "size_t", | |
446cb3f1 DG |
547 | BuiltinType::U8 => "uint8_t", |
548 | BuiltinType::U16 => "uint16_t", | |
549 | BuiltinType::U32 => "uint32_t", | |
550 | BuiltinType::U64 => "uint64_t", | |
551 | BuiltinType::S8 => "int8_t", | |
552 | BuiltinType::S16 => "int16_t", | |
553 | BuiltinType::S32 => "int32_t", | |
554 | BuiltinType::S64 => "int64_t", | |
555 | BuiltinType::F32 => "float", | |
556 | BuiltinType::F64 => "double", | |
557 | } | |
558 | } | |
559 | ||
fe130532 | 560 | fn typeref_name(tref: &TypeRef) -> String { |
ec86d4de PH |
561 | match &*tref.type_() { |
562 | Type::Builtin(BuiltinType::String) | Type::Builtin(BuiltinType::Char8) | Type::Array(_) => { | |
563 | panic!("unsupported grammar: cannot construct name of string or array",) | |
564 | } | |
565 | _ => {} | |
566 | } | |
567 | ||
fe130532 | 568 | match tref { |
d415ae65 | 569 | TypeRef::Name(named_type) => namedtype_name(&named_type), |
fe130532 | 570 | TypeRef::Value(anon_type) => match &**anon_type { |
ec86d4de | 571 | Type::Array(_) => unreachable!("arrays excluded above"), |
fe130532 | 572 | Type::Builtin(b) => builtin_type_name(*b).to_string(), |
fe130532 PH |
573 | Type::Pointer(p) => format!("{} *", typeref_name(&*p)), |
574 | Type::ConstPointer(p) => format!("const {} *", typeref_name(&*p)), | |
ec86d4de | 575 | Type::Int(i) => format!("{}", intrepr_name(i.repr)), |
fe130532 PH |
576 | Type::Struct { .. } |
577 | | Type::Union { .. } | |
578 | | Type::Enum { .. } | |
579 | | Type::Flags { .. } | |
580 | | Type::Handle { .. } => unreachable!( | |
581 | "wasi should not have anonymous structs, unions, enums, flags, handles" | |
582 | ), | |
583 | }, | |
446cb3f1 DG |
584 | } |
585 | } | |
586 | ||
d415ae65 PH |
587 | fn namedtype_name(named_type: &NamedType) -> String { |
588 | match &*named_type.type_() { | |
589 | Type::Pointer(p) => format!("{} *", typeref_name(&*p)), | |
590 | Type::ConstPointer(p) => format!("const {} *", typeref_name(&*p)), | |
591 | Type::Array(_) => unreachable!("arrays excluded above"), | |
592 | _ => format!("__wasi_{}_t", named_type.name.as_str()), | |
593 | } | |
594 | } | |
595 | ||
446cb3f1 DG |
596 | fn intrepr_name(i: IntRepr) -> &'static str { |
597 | match i { | |
598 | IntRepr::U8 => "uint8_t", | |
599 | IntRepr::U16 => "uint16_t", | |
600 | IntRepr::U32 => "uint32_t", | |
601 | IntRepr::U64 => "uint64_t", | |
602 | } | |
603 | } | |
dd010bee DG |
604 | |
605 | fn intrepr_const(i: IntRepr) -> &'static str { | |
606 | match i { | |
607 | IntRepr::U8 => "UINT8_C", | |
608 | IntRepr::U16 => "UINT16_C", | |
609 | IntRepr::U32 => "UINT32_C", | |
610 | IntRepr::U64 => "UINT64_C", | |
611 | } | |
612 | } |