1pub mod component_type_object;
2
3use anyhow::Result;
4use heck::*;
5use indexmap::IndexSet;
6use std::collections::{HashMap, HashSet};
7use std::fmt::Write;
8use std::mem;
9use wit_bindgen_core::abi::{
10 self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmSignature, WasmType,
11};
12use wit_bindgen_core::{
13 AnonymousTypeGenerator, AsyncFilterSet, Direction, Files, InterfaceGenerator as _, Ns,
14 WorldGenerator, dealias, uwrite, uwriteln, wit_parser::*,
15};
16use wit_component::StringEncoding;
17
18#[derive(Default)]
19struct C {
20 src: Source,
21 opts: Opts,
22 h_includes: Vec<String>,
23 c_includes: Vec<String>,
24 return_pointer_area_size: ArchitectureSize,
25 return_pointer_area_align: Alignment,
26 names: Ns,
27 needs_string: bool,
28 needs_union_int32_float: bool,
29 needs_union_float_int32: bool,
30 needs_union_int64_double: bool,
31 needs_union_double_int64: bool,
32 needs_async: bool,
33 prim_names: HashSet<String>,
34 world: String,
35 sizes: SizeAlign,
36 renamed_interfaces: HashMap<WorldKey, String>,
37
38 world_id: Option<WorldId>,
39 dtor_funcs: HashMap<TypeId, String>,
40 type_names: HashMap<TypeId, String>,
41 resources: HashMap<TypeId, ResourceInfo>,
42 futures: IndexSet<TypeId>,
43}
44
45#[derive(Default)]
46pub struct ResourceInfo {
47 pub direction: Direction,
48 own: String,
49 borrow: String,
50 drop_fn: String,
51}
52
53#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
54#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
55pub enum Enabled {
56 #[default]
57 No,
58 Yes,
59}
60
61impl std::fmt::Display for Enabled {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 Self::Yes => write!(f, "yes"),
65 Self::No => write!(f, "no"),
66 }
67 }
68}
69
70#[derive(Default, Debug, Clone)]
71#[cfg_attr(feature = "clap", derive(clap::Parser))]
72pub struct Opts {
73 #[cfg_attr(feature = "clap", arg(long))]
75 pub no_helpers: bool,
76
77 #[cfg_attr(
79 feature = "clap",
80 arg(
81 long,
82 default_value_t = StringEncoding::default(),
83 value_name = "ENCODING",
84 ),
85 )]
86 pub string_encoding: StringEncoding,
87
88 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
91 pub no_sig_flattening: bool,
92
93 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
96 pub no_object_file: bool,
97
98 #[cfg_attr(feature = "clap", arg(long, name = "K=V", value_parser = parse_rename))]
100 pub rename: Vec<(String, String)>,
101
102 #[cfg_attr(feature = "clap", arg(long, value_name = "NAME"))]
104 pub rename_world: Option<String>,
105
106 #[cfg_attr(feature = "clap", arg(long, value_name = "STRING"))]
109 pub type_section_suffix: Option<String>,
110
111 #[cfg_attr(
113 feature = "clap",
114 arg(
115 long,
116 default_value_t = Enabled::default(),
117 value_name = "ENABLED",
118 ),
119 )]
120 pub autodrop_borrows: Enabled,
121
122 #[cfg_attr(feature = "clap", clap(flatten))]
123 pub async_: AsyncFilterSet,
124
125 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
127 pub generate_async_helpers: bool,
128
129 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
131 pub generate_threading_helpers: bool,
132}
133
134#[cfg(feature = "clap")]
135fn parse_rename(name: &str) -> Result<(String, String)> {
136 let mut parts = name.splitn(2, '=');
137 let to_rename = parts.next().unwrap();
138 match parts.next() {
139 Some(part) => Ok((to_rename.to_string(), part.to_string())),
140 None => anyhow::bail!("`--rename` option must have an `=` in it (e.g. `--rename a=b`)"),
141 }
142}
143
144impl Opts {
145 pub fn build(&self) -> Box<dyn WorldGenerator> {
146 let mut r = C::default();
147 r.opts = self.clone();
148 Box::new(r)
149 }
150}
151
152#[derive(Clone, Debug, Default)]
153struct Return {
154 scalar: Option<Scalar>,
155 retptrs: Vec<Type>,
156}
157
158#[derive(Clone)]
159struct CSig {
160 name: String,
161 sig: String,
162 params: Vec<(bool, String)>,
163 ret: Return,
164 retptrs: Vec<String>,
165}
166
167#[derive(Clone, Debug)]
168enum Scalar {
169 Void,
170 OptionBool(Type),
171 ResultBool(Option<Type>, Option<Type>),
172 Type(Type),
173}
174
175impl WorldGenerator for C {
176 fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
177 self.world = self
178 .opts
179 .rename_world
180 .clone()
181 .unwrap_or_else(|| resolve.worlds[world].name.clone());
182 self.sizes.fill(resolve);
183 self.world_id = Some(world);
184
185 let mut interfaces = HashMap::new();
186 let world = &resolve.worlds[world];
187 for (key, _item) in world.imports.iter().chain(world.exports.iter()) {
188 let name = resolve.name_world_key(key);
189 interfaces.insert(name, key.clone());
190 }
191
192 for (from, to) in self.opts.rename.iter() {
193 match interfaces.get(from) {
194 Some(key) => {
195 self.renamed_interfaces.insert(key.clone(), to.clone());
196 }
197 None => {
198 eprintln!("warning: rename of `{from}` did not match any interfaces");
199 }
200 }
201 }
202 }
203
204 fn import_interface(
205 &mut self,
206 resolve: &Resolve,
207 name: &WorldKey,
208 id: InterfaceId,
209 _files: &mut Files,
210 ) -> Result<()> {
211 let wasm_import_module = resolve.name_world_key(name);
212 let mut r#gen = self.interface(resolve, true, Some(&wasm_import_module));
213 r#gen.interface = Some((id, name));
214 r#gen.define_interface_types(id);
215
216 for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() {
217 if i == 0 {
218 let name = resolve.name_world_key(name);
219 uwriteln!(r#gen.src.h_fns, "\n// Imported Functions from `{name}`");
220 uwriteln!(r#gen.src.c_fns, "\n// Imported Functions from `{name}`");
221 }
222 r#gen.import(Some(name), func);
223 }
224
225 r#gen.r#gen.src.append(&r#gen.src);
226
227 Ok(())
228 }
229
230 fn import_funcs(
231 &mut self,
232 resolve: &Resolve,
233 world: WorldId,
234 funcs: &[(&str, &Function)],
235 _files: &mut Files,
236 ) {
237 let name = &resolve.worlds[world].name;
238 let mut r#gen = self.interface(resolve, true, Some("$root"));
239 r#gen.define_function_types(funcs);
240
241 for (i, (_name, func)) in funcs.iter().enumerate() {
242 if i == 0 {
243 uwriteln!(r#gen.src.h_fns, "\n// Imported Functions from `{name}`");
244 uwriteln!(r#gen.src.c_fns, "\n// Imported Functions from `{name}`");
245 }
246 r#gen.import(None, func);
247 }
248
249 r#gen.r#gen.src.append(&r#gen.src);
250 }
251
252 fn export_interface(
253 &mut self,
254 resolve: &Resolve,
255 name: &WorldKey,
256 id: InterfaceId,
257 _files: &mut Files,
258 ) -> Result<()> {
259 let mut r#gen = self.interface(resolve, false, None);
260 r#gen.interface = Some((id, name));
261 r#gen.define_interface_types(id);
262
263 for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() {
264 if i == 0 {
265 let name = resolve.name_world_key(name);
266 uwriteln!(r#gen.src.h_fns, "\n// Exported Functions from `{name}`");
267 uwriteln!(r#gen.src.c_fns, "\n// Exported Functions from `{name}`");
268 }
269 r#gen.export(func, Some(name));
270 }
271
272 r#gen.r#gen.src.append(&r#gen.src);
273 Ok(())
274 }
275
276 fn export_funcs(
277 &mut self,
278 resolve: &Resolve,
279 world: WorldId,
280 funcs: &[(&str, &Function)],
281 _files: &mut Files,
282 ) -> Result<()> {
283 let name = &resolve.worlds[world].name;
284 let mut r#gen = self.interface(resolve, false, None);
285 r#gen.define_function_types(funcs);
286
287 for (i, (_name, func)) in funcs.iter().enumerate() {
288 if i == 0 {
289 uwriteln!(r#gen.src.h_fns, "\n// Exported Functions from `{name}`");
290 uwriteln!(r#gen.src.c_fns, "\n// Exported Functions from `{name}`");
291 }
292 r#gen.export(func, None);
293 }
294
295 r#gen.r#gen.src.append(&r#gen.src);
296 Ok(())
297 }
298
299 fn import_types(
300 &mut self,
301 resolve: &Resolve,
302 _world: WorldId,
303 types: &[(&str, TypeId)],
304 _files: &mut Files,
305 ) {
306 let mut r#gen = self.interface(resolve, true, Some("$root"));
307 let mut live = LiveTypes::default();
308 for (_, id) in types {
309 live.add_type_id(resolve, *id);
310 }
311 r#gen.define_live_types(live);
312 r#gen.r#gen.src.append(&r#gen.src);
313 }
314
315 fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
316 let linking_symbol = component_type_object::linking_symbol(&self.world);
317 self.c_include("<stdlib.h>");
318 let snake = self.world.to_snake_case();
319 uwriteln!(
320 self.src.c_adapters,
321 "\n// Ensure that the *_component_type.o object is linked in"
322 );
323 uwrite!(
324 self.src.c_adapters,
325 "
326 extern void {linking_symbol}(void);
327 __attribute__((used))
328 void {linking_symbol}_public_use_in_this_compilation_unit(void) {{
329 {linking_symbol}();
330 }}
331 ",
332 );
333
334 self.print_intrinsics();
335
336 if self.needs_string {
337 self.c_include("<string.h>");
338 let (strlen, size) = match self.opts.string_encoding {
339 StringEncoding::UTF8 => (format!("strlen(s)"), 1),
340 StringEncoding::UTF16 => {
341 self.h_include("<uchar.h>");
342 uwrite!(
343 self.src.h_helpers,
344 "
345 // Returns the length of the UTF-16 string `s` in code units
346 size_t {snake}_string_len(const char16_t* s);
347 ",
348 );
349 uwrite!(
350 self.src.c_helpers,
351 "
352 size_t {snake}_string_len(const char16_t* s) {{
353 char16_t* c = (char16_t*)s;
354 for (; *c; ++c);
355 return c-s;
356 }}
357 ",
358 );
359 (format!("{snake}_string_len(s)"), 2)
360 }
361 StringEncoding::CompactUTF16 => unimplemented!(),
362 };
363 let ty = self.char_type();
364 let c_string_ty = match self.opts.string_encoding {
365 StringEncoding::UTF8 => "char",
366 StringEncoding::UTF16 => "char16_t",
367 StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"),
368 };
369 uwrite!(
370 self.src.h_helpers,
371 "
372 // Sets the string `ret` to reference the input string `s` without copying it
373 void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s);
374
375 // Creates a copy of the input nul-terminated string `s` and
376 // stores it into the component model string `ret`.
377 void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s);
378
379 // Creates a copy of the input string `s` with length `len` and
380 // stores it into the component model string `ret`.
381 // The length is specified in code units (bytes for UTF-8, 16-bit values for UTF-16).
382 void {snake}_string_dup_n({snake}_string_t *ret, const {c_string_ty} *s, size_t len);
383
384 // Deallocates the string pointed to by `ret`, deallocating
385 // the memory behind the string.
386 void {snake}_string_free({snake}_string_t *ret);\
387 ",
388 );
389 uwrite!(
390 self.src.c_helpers,
391 "
392 void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s) {{
393 ret->ptr = ({ty}*) s;
394 ret->len = {strlen};
395 }}
396
397 void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s) {{
398 ret->len = {strlen};
399 ret->ptr = ({ty}*) cabi_realloc(NULL, 0, {size}, ret->len * {size});
400 memcpy(ret->ptr, s, ret->len * {size});
401 }}
402
403 void {snake}_string_dup_n({snake}_string_t *ret, const {c_string_ty} *s, size_t len) {{
404 ret->len = len;
405 ret->ptr = ({ty}*) cabi_realloc(NULL, 0, {size}, ret->len * {size});
406 memcpy(ret->ptr, s, ret->len * {size});
407 }}
408
409 void {snake}_string_free({snake}_string_t *ret) {{
410 if (ret->len > 0) {{
411 free(ret->ptr);
412 }}
413 ret->ptr = NULL;
414 ret->len = 0;
415 }}
416 ",
417 );
418 }
419 if self.needs_union_int32_float {
420 uwriteln!(
421 self.src.c_defs,
422 "\nunion int32_float {{ int32_t a; float b; }};"
423 );
424 }
425 if self.needs_union_float_int32 {
426 uwriteln!(
427 self.src.c_defs,
428 "\nunion float_int32 {{ float a; int32_t b; }};"
429 );
430 }
431 if self.needs_union_int64_double {
432 uwriteln!(
433 self.src.c_defs,
434 "\nunion int64_double {{ int64_t a; double b; }};"
435 );
436 }
437 if self.needs_union_double_int64 {
438 uwriteln!(
439 self.src.c_defs,
440 "\nunion double_int64 {{ double a; int64_t b; }};"
441 );
442 }
443 if self.needs_async
444 || self.futures.len() > 0
445 || self.opts.generate_async_helpers
446 || self.opts.generate_threading_helpers
447 {
448 self.generate_async_helpers();
449 }
450 if self.opts.generate_threading_helpers {
451 self.generate_threading_helpers();
452 }
453 let version = env!("CARGO_PKG_VERSION");
454 let mut h_str = wit_bindgen_core::Source::default();
455
456 wit_bindgen_core::generated_preamble(&mut h_str, version);
457
458 uwrite!(
459 h_str,
460 "#ifndef __BINDINGS_{0}_H
461 #define __BINDINGS_{0}_H
462 #ifdef __cplusplus
463 extern \"C\" {{",
464 self.world.to_shouty_snake_case(),
465 );
466
467 h_str.deindent(1);
469 uwriteln!(h_str, "\n#endif\n");
470
471 uwriteln!(h_str, "#include <stdint.h>");
472 uwriteln!(h_str, "#include <stdbool.h>");
473 uwriteln!(h_str, "#include <stddef.h>");
474 for include in self.h_includes.iter() {
475 uwriteln!(h_str, "#include {include}");
476 }
477
478 let mut c_str = wit_bindgen_core::Source::default();
479 wit_bindgen_core::generated_preamble(&mut c_str, version);
480 uwriteln!(c_str, "#include \"{snake}.h\"");
481 for include in self.c_includes.iter() {
482 uwriteln!(c_str, "#include {include}");
483 }
484 c_str.push_str(&self.src.c_defs);
485 c_str.push_str(&self.src.c_fns);
486
487 if !self.return_pointer_area_size.is_empty() {
491 uwrite!(
493 c_str,
494 "
495 __attribute__((__aligned__({})))
496 static uint8_t RET_AREA[{}];
497 ",
498 self.return_pointer_area_align
499 .format(POINTER_SIZE_EXPRESSION),
500 self.return_pointer_area_size
501 .format(POINTER_SIZE_EXPRESSION),
502 );
503 }
504
505 if self.needs_string {
506 uwriteln!(
507 h_str,
508 "
509 typedef struct {snake}_string_t {{\n\
510 {ty} *ptr;\n\
511 size_t len;\n\
512 }} {snake}_string_t;",
513 ty = self.char_type(),
514 );
515 }
516
517 if self.src.h_async.len() > 0 {
518 uwriteln!(h_str, "\n// Async Helper Functions");
519 h_str.push_str(&self.src.h_async);
520 h_str.push_str("\n");
521 }
522
523 if self.src.h_defs.len() > 0 {
524 h_str.push_str(&self.src.h_defs);
525 }
526
527 h_str.push_str(&self.src.h_fns);
528
529 if !self.opts.no_helpers && self.src.h_helpers.len() > 0 {
530 uwriteln!(h_str, "\n// Helper Functions");
531 h_str.push_str(&self.src.h_helpers);
532 h_str.push_str("\n");
533 }
534
535 if !self.opts.no_helpers && self.src.c_helpers.len() > 0 {
536 uwriteln!(c_str, "\n// Helper Functions");
537 c_str.push_str(self.src.c_helpers.as_mut_string());
538 }
539
540 if self.src.c_async.len() > 0 {
541 uwriteln!(c_str, "\n// Async Helper Functions");
542 c_str.push_str(&self.src.c_async);
543 c_str.push_str("\n");
544 }
545
546 uwriteln!(c_str, "\n// Component Adapters");
547
548 c_str.push_str(&self.src.c_adapters);
549
550 uwriteln!(
551 h_str,
552 "
553 #ifdef __cplusplus
554 }}
555 #endif
556 #endif"
557 );
558
559 files.push(&format!("{snake}.h"), h_str.as_bytes());
560 files.push(&format!("{snake}.c"), c_str.as_bytes());
561 if !self.opts.no_object_file {
562 files.push(
563 &format!("{snake}_component_type.o",),
564 component_type_object::object(
565 resolve,
566 id,
567 &self.world,
568 self.opts.string_encoding,
569 self.opts.type_section_suffix.as_deref(),
570 )
571 .unwrap()
572 .as_slice(),
573 );
574 }
575
576 Ok(())
577 }
578
579 fn pre_export_interface(&mut self, resolve: &Resolve, _files: &mut Files) -> Result<()> {
580 self.remove_types_redefined_by_exports(resolve, self.world_id.unwrap());
581 Ok(())
582 }
583}
584
585impl C {
586 fn interface<'a>(
587 &'a mut self,
588 resolve: &'a Resolve,
589 in_import: bool,
590 wasm_import_module: Option<&'a str>,
591 ) -> InterfaceGenerator<'a> {
592 InterfaceGenerator {
593 src: Source::default(),
594 r#gen: self,
595 resolve,
596 interface: None,
597 in_import,
598 wasm_import_module,
599 }
600 }
601
602 fn h_include(&mut self, s: &str) {
603 self.h_includes.push(s.to_string());
604 }
605
606 fn c_include(&mut self, s: &str) {
607 self.c_includes.push(s.to_string());
608 }
609
610 fn char_type(&self) -> &'static str {
611 match self.opts.string_encoding {
612 StringEncoding::UTF8 => "uint8_t",
613 StringEncoding::UTF16 => "uint16_t",
614 StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"),
615 }
616 }
617
618 fn type_name(&mut self, ty: &Type) -> String {
619 let mut name = String::new();
620 self.push_type_name(ty, &mut name);
621 name
622 }
623
624 fn push_type_name(&mut self, ty: &Type, dst: &mut String) {
625 match ty {
626 Type::Bool => dst.push_str("bool"),
627 Type::Char => dst.push_str("uint32_t"), Type::U8 => dst.push_str("uint8_t"),
629 Type::S8 => dst.push_str("int8_t"),
630 Type::U16 => dst.push_str("uint16_t"),
631 Type::S16 => dst.push_str("int16_t"),
632 Type::U32 => dst.push_str("uint32_t"),
633 Type::S32 => dst.push_str("int32_t"),
634 Type::U64 => dst.push_str("uint64_t"),
635 Type::S64 => dst.push_str("int64_t"),
636 Type::F32 => dst.push_str("float"),
637 Type::F64 => dst.push_str("double"),
638 Type::String => {
639 dst.push_str(&self.world.to_snake_case());
640 dst.push_str("_");
641 dst.push_str("string_t");
642 self.needs_string = true;
643 }
644 Type::ErrorContext => dst.push_str("error_context"),
645 Type::Id(id) => {
646 if let Some(name) = self.type_names.get(id) {
647 dst.push_str(name);
648 return;
649 }
650
651 panic!("failed to find type name for {id:?}");
652 }
653 }
654 }
655
656 fn remove_types_redefined_by_exports(&mut self, resolve: &Resolve, world: WorldId) {
670 let live_import_types = imported_types_used_by_exported_interfaces(resolve, world);
671 self.dtor_funcs.retain(|k, _| live_import_types.contains(k));
672 self.type_names.retain(|k, _| live_import_types.contains(k));
673 self.resources.retain(|k, _| live_import_types.contains(k));
674 }
675
676 fn perform_cast(&mut self, op: &str, cast: &Bitcast) -> String {
677 match cast {
678 Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
679 self.needs_union_int32_float = true;
680 format!("((union int32_float){{ (int32_t) {op} }}).b")
681 }
682 Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
683 self.needs_union_float_int32 = true;
684 format!("((union float_int32){{ {op} }}).b")
685 }
686 Bitcast::I64ToF64 => {
687 self.needs_union_int64_double = true;
688 format!("((union int64_double){{ (int64_t) {op} }}).b")
689 }
690 Bitcast::F64ToI64 => {
691 self.needs_union_double_int64 = true;
692 format!("((union double_int64){{ {op} }}).b")
693 }
694 Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
695 format!("(int64_t) {op}")
696 }
697 Bitcast::I64ToI32 | Bitcast::I64ToL => {
698 format!("(int32_t) {op}")
699 }
700 Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
702 format!("{op}")
703 }
704 Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
705 format!("(uint8_t *) {op}")
706 }
707
708 Bitcast::PToI32 | Bitcast::PToL => format!("(uintptr_t) {op}"),
710
711 Bitcast::I32ToL | Bitcast::LToI32 | Bitcast::None => op.to_string(),
712
713 Bitcast::Sequence(sequence) => {
714 let [first, second] = &**sequence;
715 let inner = self.perform_cast(op, first);
716 self.perform_cast(&inner, second)
717 }
718 }
719 }
720
721 fn generate_threading_helpers(&mut self) {
722 let snake = self.world.to_snake_case();
723 uwriteln!(
724 self.src.h_async,
725 "
726void* {snake}_context_get_1(void);
727void {snake}_context_set_1(void* value);
728uint32_t {snake}_thread_yield_cancellable(void);
729uint32_t {snake}_thread_index(void);
730uint32_t {snake}_thread_new_indirect(void (*start_function)(void*), void* arg);
731void {snake}_thread_switch_to(uint32_t thread);
732uint32_t {snake}_thread_switch_to_cancellable(uint32_t thread);
733void {snake}_thread_resume_later(uint32_t thread);
734void {snake}_thread_yield_to(uint32_t thread);
735uint32_t {snake}_thread_yield_to_cancellable(uint32_t thread);
736void {snake}_thread_suspend(void);
737uint32_t {snake}_thread_suspend_cancellable(void);
738 "
739 );
740 uwriteln!(
741 self.src.c_async,
742 r#"
743__attribute__((__import_module__("$root"), __import_name__("[context-get-1]")))
744extern void* __context_get_1(void);
745
746void* {snake}_context_get_1(void) {{
747 return __context_get_1();
748}}
749
750__attribute__((__import_module__("$root"), __import_name__("[context-set-1]")))
751extern void __context_set_1(void*);
752
753void {snake}_context_set_1(void* value) {{
754 __context_set_1(value);
755}}
756
757__attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-yield]")))
758extern uint32_t __thread_yield_cancellable(void);
759
760uint32_t {snake}_thread_yield_cancellable(void) {{
761 return __thread_yield_cancellable();
762}}
763
764__attribute__((__import_module__("$root"), __import_name__("[thread-index]")))
765extern uint32_t __thread_index(void);
766
767uint32_t {snake}_thread_index(void) {{
768 return __thread_index();
769}}
770
771__attribute__((__import_module__("$root"), __import_name__("[thread-new-indirect-v0]")))
772extern uint32_t __thread_new_indirect(uint32_t, void*);
773
774uint32_t {snake}_thread_new_indirect(void (*start_function)(void*), void* arg) {{
775 return __thread_new_indirect((uint32_t)(uintptr_t)start_function, arg
776);
777}}
778
779__attribute__((__import_module__("$root"), __import_name__("[thread-switch-to]")))
780extern uint32_t __thread_switch_to(uint32_t);
781
782void {snake}_thread_switch_to(uint32_t thread) {{
783 __thread_switch_to(thread);
784}}
785
786__attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-switch-to]")))
787extern uint32_t __thread_switch_to_cancellable(uint32_t);
788
789uint32_t {snake}_thread_switch_to_cancellable(uint32_t thread) {{
790 return __thread_switch_to_cancellable(thread);
791}}
792
793__attribute__((__import_module__("$root"), __import_name__("[thread-resume-later]")))
794extern void __thread_resume_later(uint32_t);
795
796void {snake}_thread_resume_later(uint32_t thread) {{
797 __thread_resume_later(thread);
798}}
799
800__attribute__((__import_module__("$root"), __import_name__("[thread-yield-to]")))
801extern uint32_t __thread_yield_to(uint32_t);
802
803void {snake}_thread_yield_to(uint32_t thread) {{
804 __thread_yield_to(thread);
805}}
806
807__attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-yield-to]")))
808extern uint32_t __thread_yield_to_cancellable(uint32_t);
809
810uint32_t {snake}_thread_yield_to_cancellable(uint32_t thread) {{
811 return __thread_yield_to_cancellable(thread);
812}}
813
814__attribute__((__import_module__("$root"), __import_name__("[thread-suspend]")))
815extern uint32_t __thread_suspend(void);
816
817void {snake}_thread_suspend(void) {{
818 __thread_suspend();
819}}
820
821__attribute__((__import_module__("$root"), __import_name__("[cancellable][thread-suspend]")))
822extern uint32_t __thread_suspend_cancellable(void);
823uint32_t {snake}_thread_suspend_cancellable(void) {{
824 return __thread_suspend_cancellable();
825}}
826 "#
827 );
828 }
829
830 fn generate_async_helpers(&mut self) {
831 let snake = self.world.to_snake_case();
832 let shouty = self.world.to_shouty_snake_case();
833 uwriteln!(
834 self.src.h_async,
835 "
836typedef uint32_t {snake}_subtask_status_t;
837typedef uint32_t {snake}_subtask_t;
838#define {shouty}_SUBTASK_STATE(status) (({snake}_subtask_state_t) ((status) & 0xf))
839#define {shouty}_SUBTASK_HANDLE(status) (({snake}_subtask_t) ((status) >> 4))
840
841typedef enum {snake}_subtask_state {{
842 {shouty}_SUBTASK_STARTING,
843 {shouty}_SUBTASK_STARTED,
844 {shouty}_SUBTASK_RETURNED,
845 {shouty}_SUBTASK_STARTED_CANCELLED,
846 {shouty}_SUBTASK_RETURNED_CANCELLED,
847}} {snake}_subtask_state_t;
848
849{snake}_subtask_status_t {snake}_subtask_cancel({snake}_subtask_t subtask);
850void {snake}_subtask_drop({snake}_subtask_t subtask);
851
852typedef uint32_t {snake}_callback_code_t;
853#define {shouty}_CALLBACK_CODE_EXIT 0
854#define {shouty}_CALLBACK_CODE_YIELD 1
855#define {shouty}_CALLBACK_CODE_WAIT(set) (2 | (set << 4))
856
857typedef enum {snake}_event_code {{
858 {shouty}_EVENT_NONE,
859 {shouty}_EVENT_SUBTASK,
860 {shouty}_EVENT_STREAM_READ,
861 {shouty}_EVENT_STREAM_WRITE,
862 {shouty}_EVENT_FUTURE_READ,
863 {shouty}_EVENT_FUTURE_WRITE,
864 {shouty}_EVENT_CANCEL,
865}} {snake}_event_code_t;
866
867typedef struct {snake}_event {{
868 {snake}_event_code_t event;
869 uint32_t waitable;
870 uint32_t code;
871}} {snake}_event_t;
872
873typedef uint32_t {snake}_waitable_set_t;
874{snake}_waitable_set_t {snake}_waitable_set_new(void);
875void {snake}_waitable_join(uint32_t waitable, {snake}_waitable_set_t set);
876void {snake}_waitable_set_drop({snake}_waitable_set_t set);
877void {snake}_waitable_set_wait({snake}_waitable_set_t set, {snake}_event_t *event);
878void {snake}_waitable_set_poll({snake}_waitable_set_t set, {snake}_event_t *event);
879
880void {snake}_task_cancel(void);
881
882typedef uint32_t {snake}_waitable_status_t;
883#define {shouty}_WAITABLE_STATE(status) (({snake}_waitable_state_t) ((status) & 0xf))
884#define {shouty}_WAITABLE_COUNT(status) ((uint32_t) ((status) >> 4))
885#define {shouty}_WAITABLE_STATUS_BLOCKED (({snake}_waitable_status_t) -1)
886
887typedef enum {snake}_waitable_state {{
888 {shouty}_WAITABLE_COMPLETED,
889 {shouty}_WAITABLE_DROPPED,
890 {shouty}_WAITABLE_CANCELLED,
891}} {snake}_waitable_state_t;
892
893void {snake}_backpressure_inc(void);
894void {snake}_backpressure_dec(void);
895void* {snake}_context_get_0(void);
896void {snake}_context_set_0(void* value);
897void {snake}_thread_yield(void);
898 "
899 );
900 uwriteln!(
901 self.src.c_async,
902 r#"
903__attribute__((__import_module__("$root"), __import_name__("[subtask-cancel]")))
904extern uint32_t __subtask_cancel(uint32_t handle);
905
906{snake}_subtask_status_t {snake}_subtask_cancel({snake}_subtask_t subtask) {{
907 return __subtask_cancel(subtask);
908}}
909
910__attribute__((__import_module__("$root"), __import_name__("[subtask-drop]")))
911extern void __subtask_drop(uint32_t handle);
912
913void {snake}_subtask_drop({snake}_subtask_t subtask) {{
914 __subtask_drop(subtask);
915}}
916
917__attribute__((__import_module__("$root"), __import_name__("[waitable-set-new]")))
918extern uint32_t __waitable_set_new(void);
919
920{snake}_waitable_set_t {snake}_waitable_set_new(void) {{
921 return __waitable_set_new();
922}}
923
924__attribute__((__import_module__("$root"), __import_name__("[waitable-join]")))
925extern void __waitable_join(uint32_t, uint32_t);
926
927void {snake}_waitable_join(uint32_t waitable, {snake}_waitable_set_t set) {{
928 __waitable_join(waitable, set);
929}}
930
931__attribute__((__import_module__("$root"), __import_name__("[waitable-set-drop]")))
932extern void __waitable_set_drop(uint32_t);
933
934void {snake}_waitable_set_drop({snake}_waitable_set_t set) {{
935 __waitable_set_drop(set);
936}}
937
938__attribute__((__import_module__("$root"), __import_name__("[waitable-set-wait]")))
939extern uint32_t __waitable_set_wait(uint32_t, uint32_t*);
940__attribute__((__import_module__("$root"), __import_name__("[waitable-set-poll]")))
941extern uint32_t __waitable_set_poll(uint32_t, uint32_t*);
942
943void {snake}_waitable_set_wait({snake}_waitable_set_t set, {snake}_event_t *event) {{
944 event->event = ({snake}_event_code_t) __waitable_set_wait(set, &event->waitable);
945}}
946
947void {snake}_waitable_set_poll({snake}_waitable_set_t set, {snake}_event_t *event) {{
948 event->event = ({snake}_event_code_t) __waitable_set_poll(set, &event->waitable);
949}}
950
951__attribute__((__import_module__("[export]$root"), __import_name__("[task-cancel]")))
952extern void __task_cancel(void);
953
954void {snake}_task_cancel() {{
955 __task_cancel();
956}}
957
958__attribute__((__import_module__("$root"), __import_name__("[backpressure-inc]")))
959extern void __backpressure_inc(void);
960
961void {snake}_backpressure_inc(void) {{
962 __backpressure_inc();
963}}
964
965__attribute__((__import_module__("$root"), __import_name__("[backpressure-dec]")))
966extern void __backpressure_dec(void);
967
968void {snake}_backpressure_dec(void) {{
969 __backpressure_dec();
970}}
971
972__attribute__((__import_module__("$root"), __import_name__("[context-get-0]")))
973extern void* __context_get_0(void);
974
975void* {snake}_context_get_0(void) {{
976 return __context_get_0();
977}}
978
979__attribute__((__import_module__("$root"), __import_name__("[context-set-0]")))
980extern void __context_set_0(void*);
981
982
983void {snake}_context_set_0(void *value) {{
984 __context_set_0(value);
985}}
986
987__attribute__((__import_module__("$root"), __import_name__("[thread-yield]")))
988extern uint32_t __thread_yield(void);
989
990void {snake}_thread_yield(void) {{
991 __thread_yield();
992}}
993 "#
994 );
995 }
996}
997
998pub fn imported_types_used_by_exported_interfaces(
999 resolve: &Resolve,
1000 world: WorldId,
1001) -> HashSet<TypeId> {
1002 let mut live_export_types = LiveTypes::default();
1005 let mut exported_interfaces = HashSet::new();
1006 for (_, export) in resolve.worlds[world].exports.iter() {
1007 match export {
1008 WorldItem::Function(_) => {}
1009 WorldItem::Interface { id, .. } => {
1010 exported_interfaces.insert(*id);
1011 live_export_types.add_interface(resolve, *id)
1012 }
1013 WorldItem::Type(_) => unreachable!(),
1014 }
1015 }
1016
1017 let mut imports_used = HashSet::new();
1022 for ty in live_export_types.iter() {
1023 if let TypeOwner::Interface(id) = resolve.types[ty].owner {
1024 if !exported_interfaces.contains(&id) {
1025 imports_used.insert(id);
1026 }
1027 }
1028 }
1029
1030 let mut live_import_types = LiveTypes::default();
1034 for import in imports_used {
1035 live_import_types.add_interface(resolve, import);
1036 }
1037 let live_import_types = live_import_types.iter().collect::<HashSet<_>>();
1038 live_import_types
1039}
1040
1041fn is_prim_type(resolve: &Resolve, ty: &Type) -> bool {
1042 if let Type::Id(id) = ty {
1043 is_prim_type_id(resolve, *id)
1044 } else {
1045 true
1046 }
1047}
1048
1049fn is_prim_type_id(resolve: &Resolve, id: TypeId) -> bool {
1050 match &resolve.types[id].kind {
1051 TypeDefKind::List(elem) => is_prim_type(resolve, elem),
1052
1053 TypeDefKind::Option(ty) => is_prim_type(resolve, ty),
1054
1055 TypeDefKind::Tuple(tuple) => tuple.types.iter().all(|ty| is_prim_type(resolve, ty)),
1056
1057 TypeDefKind::Type(ty) => is_prim_type(resolve, ty),
1058
1059 TypeDefKind::Record(_)
1060 | TypeDefKind::Resource
1061 | TypeDefKind::Handle(_)
1062 | TypeDefKind::Flags(_)
1063 | TypeDefKind::Variant(_)
1064 | TypeDefKind::Enum(_)
1065 | TypeDefKind::Result(_)
1066 | TypeDefKind::Future(_)
1067 | TypeDefKind::Stream(_)
1068 | TypeDefKind::Unknown => false,
1069 TypeDefKind::FixedSizeList(..) => todo!(),
1070 TypeDefKind::Map(..) => todo!(),
1071 }
1072}
1073
1074pub fn push_ty_name(resolve: &Resolve, ty: &Type, src: &mut String) {
1075 match ty {
1076 Type::Bool => src.push_str("bool"),
1077 Type::Char => src.push_str("char32"),
1078 Type::U8 => src.push_str("u8"),
1079 Type::S8 => src.push_str("s8"),
1080 Type::U16 => src.push_str("u16"),
1081 Type::S16 => src.push_str("s16"),
1082 Type::U32 => src.push_str("u32"),
1083 Type::S32 => src.push_str("s32"),
1084 Type::U64 => src.push_str("u64"),
1085 Type::S64 => src.push_str("s64"),
1086 Type::F32 => src.push_str("f32"),
1087 Type::F64 => src.push_str("f64"),
1088 Type::String => src.push_str("string"),
1089 Type::ErrorContext => todo!(),
1090 Type::Id(id) => {
1091 let ty = &resolve.types[*id];
1092 if let Some(name) = &ty.name {
1093 return src.push_str(&name.to_snake_case());
1094 }
1095 match &ty.kind {
1096 TypeDefKind::Type(t) => push_ty_name(resolve, t, src),
1097 TypeDefKind::Record(_)
1098 | TypeDefKind::Resource
1099 | TypeDefKind::Flags(_)
1100 | TypeDefKind::Enum(_)
1101 | TypeDefKind::Variant(_) => {
1102 unimplemented!()
1103 }
1104 TypeDefKind::Tuple(t) => {
1105 src.push_str("tuple");
1106 src.push_str(&t.types.len().to_string());
1107 for ty in t.types.iter() {
1108 src.push_str("_");
1109 push_ty_name(resolve, ty, src);
1110 }
1111 }
1112 TypeDefKind::Option(ty) => {
1113 src.push_str("option_");
1114 push_ty_name(resolve, ty, src);
1115 }
1116 TypeDefKind::Result(r) => {
1117 src.push_str("result_");
1118 match &r.ok {
1119 Some(ty) => push_ty_name(resolve, ty, src),
1120 None => src.push_str("void"),
1121 }
1122 src.push_str("_");
1123 match &r.err {
1124 Some(ty) => push_ty_name(resolve, ty, src),
1125 None => src.push_str("void"),
1126 }
1127 }
1128 TypeDefKind::List(ty) => {
1129 src.push_str("list_");
1130 push_ty_name(resolve, ty, src);
1131 }
1132 TypeDefKind::Future(ty) => {
1133 src.push_str("future_");
1134 match ty {
1135 Some(ty) => push_ty_name(resolve, ty, src),
1136 None => src.push_str("void"),
1137 }
1138 }
1139 TypeDefKind::Stream(ty) => {
1140 src.push_str("stream_");
1141 match ty {
1142 Some(ty) => push_ty_name(resolve, ty, src),
1143 None => src.push_str("void"),
1144 }
1145 }
1146 TypeDefKind::Handle(Handle::Own(resource)) => {
1147 src.push_str("own_");
1148 push_ty_name(resolve, &Type::Id(*resource), src);
1149 }
1150 TypeDefKind::Handle(Handle::Borrow(resource)) => {
1151 src.push_str("borrow_");
1152 push_ty_name(resolve, &Type::Id(*resource), src);
1153 }
1154 TypeDefKind::Unknown => unreachable!(),
1155 TypeDefKind::FixedSizeList(..) => todo!(),
1156 TypeDefKind::Map(..) => todo!(),
1157 }
1158 }
1159 }
1160}
1161
1162pub fn owner_namespace<'a>(
1163 interface: Option<(InterfaceId, &'a WorldKey)>,
1164 in_import: bool,
1165 world: String,
1166 resolve: &Resolve,
1167 id: TypeId,
1168 renamed_interfaces: &HashMap<WorldKey, String>,
1169) -> String {
1170 let ty = &resolve.types[id];
1171 match (ty.owner, interface) {
1172 (TypeOwner::Interface(a), Some((b, key))) if a == b => {
1175 interface_identifier(key, resolve, !in_import, renamed_interfaces)
1176 }
1177 (TypeOwner::Interface(_), None) => unreachable!(),
1178 (TypeOwner::Interface(_), Some(_)) => unreachable!(),
1179
1180 (TypeOwner::World(_), None) => world.to_snake_case(),
1183 (TypeOwner::World(_), Some(_)) => unreachable!(),
1184
1185 (TypeOwner::None, Some((_, key))) => {
1188 interface_identifier(key, resolve, !in_import, renamed_interfaces)
1189 }
1190 (TypeOwner::None, None) => world.to_snake_case(),
1191 }
1192}
1193
1194fn interface_identifier(
1195 interface_id: &WorldKey,
1196 resolve: &Resolve,
1197 in_export: bool,
1198 renamed_interfaces: &HashMap<WorldKey, String>,
1199) -> String {
1200 if let Some(rename) = renamed_interfaces.get(interface_id) {
1201 let mut ns = String::new();
1202 if in_export && matches!(interface_id, WorldKey::Interface(_)) {
1203 ns.push_str("exports_");
1204 }
1205 ns.push_str(rename);
1206 return ns;
1207 }
1208
1209 match interface_id {
1210 WorldKey::Name(name) => name.to_snake_case(),
1211 WorldKey::Interface(id) => {
1212 let mut ns = String::new();
1213 if in_export {
1214 ns.push_str("exports_");
1215 }
1216 let iface = &resolve.interfaces[*id];
1217 let pkg = &resolve.packages[iface.package.unwrap()];
1218 ns.push_str(&pkg.name.namespace.to_snake_case());
1219 ns.push_str("_");
1220 ns.push_str(&pkg.name.name.to_snake_case());
1221 ns.push_str("_");
1222 let pkg_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
1223 p.name.namespace == pkg.name.namespace
1224 && p.name.name == pkg.name.name
1225 && p.name.version != pkg.name.version
1226 });
1227 if pkg_has_multiple_versions {
1228 if let Some(version) = &pkg.name.version {
1229 let version = version
1230 .to_string()
1231 .replace('.', "_")
1232 .replace('-', "_")
1233 .replace('+', "_");
1234 ns.push_str(&version);
1235 ns.push_str("_");
1236 }
1237 }
1238 ns.push_str(&iface.name.as_ref().unwrap().to_snake_case());
1239 ns
1240 }
1241 }
1242}
1243
1244pub fn c_func_name(
1245 in_import: bool,
1246 resolve: &Resolve,
1247 world: &str,
1248 interface_id: Option<&WorldKey>,
1249 func: &Function,
1250 renamed_interfaces: &HashMap<WorldKey, String>,
1251) -> String {
1252 let mut name = String::new();
1253 match interface_id {
1254 Some(id) => name.push_str(&interface_identifier(
1255 id,
1256 resolve,
1257 !in_import,
1258 renamed_interfaces,
1259 )),
1260 None => {
1261 if !in_import {
1262 name.push_str("exports_");
1263 }
1264 name.push_str(&world.to_snake_case());
1265 }
1266 }
1267 name.push_str("_");
1268 name.push_str(&func.name.to_snake_case().replace('.', "_"));
1269 name
1270}
1271
1272struct InterfaceGenerator<'a> {
1273 src: Source,
1274 in_import: bool,
1275 r#gen: &'a mut C,
1276 resolve: &'a Resolve,
1277 interface: Option<(InterfaceId, &'a WorldKey)>,
1278 wasm_import_module: Option<&'a str>,
1279}
1280
1281impl C {
1282 fn print_intrinsics(&mut self) {
1283 self.src.c_fns("\n// Canonical ABI intrinsics");
1286 self.src.c_fns("\n");
1287 self.src.c_fns(
1288 r#"
1289 __attribute__((__weak__, __export_name__("cabi_realloc")))
1290 void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
1291 (void) old_size;
1292 if (new_size == 0) return (void*) align;
1293 void *ret = realloc(ptr, new_size);
1294 if (!ret) abort();
1295 return ret;
1296 }
1297 "#,
1298 );
1299 }
1300}
1301
1302impl Return {
1303 fn return_single(
1304 &mut self,
1305 resolve: &Resolve,
1306 ty: &Type,
1307 orig_ty: &Type,
1308 sig_flattening: bool,
1309 ) {
1310 let id = match ty {
1311 Type::Id(id) => *id,
1312 Type::String => {
1313 self.retptrs.push(*orig_ty);
1314 return;
1315 }
1316 Type::ErrorContext => todo!("return_single for error-context"),
1317 _ => {
1318 self.scalar = Some(Scalar::Type(*orig_ty));
1319 return;
1320 }
1321 };
1322 match &resolve.types[id].kind {
1323 TypeDefKind::Type(t) => return self.return_single(resolve, t, orig_ty, sig_flattening),
1324
1325 TypeDefKind::Flags(_)
1327 | TypeDefKind::Enum(_)
1328 | TypeDefKind::Handle(_)
1329 | TypeDefKind::Future(_)
1330 | TypeDefKind::Stream(_) => {
1331 self.scalar = Some(Scalar::Type(*orig_ty));
1332 return;
1333 }
1334
1335 TypeDefKind::Option(ty) => {
1339 if sig_flattening {
1340 self.scalar = Some(Scalar::OptionBool(*ty));
1341 self.retptrs.push(*ty);
1342 return;
1343 }
1344 }
1345
1346 TypeDefKind::Result(r) => {
1349 if sig_flattening {
1350 if let Some(ok) = r.ok {
1351 self.retptrs.push(ok);
1352 }
1353 if let Some(err) = r.err {
1354 self.retptrs.push(err);
1355 }
1356 self.scalar = Some(Scalar::ResultBool(r.ok, r.err));
1357 return;
1358 }
1359 }
1360
1361 TypeDefKind::Tuple(_)
1363 | TypeDefKind::Record(_)
1364 | TypeDefKind::List(_)
1365 | TypeDefKind::Variant(_) => {}
1366
1367 TypeDefKind::Resource => todo!("return_single for resource"),
1368 TypeDefKind::Unknown => unreachable!(),
1369 TypeDefKind::FixedSizeList(..) => todo!(),
1370 TypeDefKind::Map(..) => todo!(),
1371 }
1372
1373 self.retptrs.push(*orig_ty);
1374 }
1375}
1376
1377impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1378 fn resolve(&self) -> &'a Resolve {
1379 self.resolve
1380 }
1381
1382 fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1383 self.src.h_defs("\n");
1384 self.docs(docs, SourceType::HDefs);
1385 self.start_typedef_struct(id);
1386 for field in record.fields.iter() {
1387 self.docs(&field.docs, SourceType::HDefs);
1388 self.print_ty(SourceType::HDefs, &field.ty);
1389 self.src.h_defs(" ");
1390 self.src.h_defs(&to_c_ident(&field.name));
1391 self.src.h_defs(";\n");
1392 }
1393 self.finish_typedef_struct(id);
1394 }
1395
1396 fn type_resource(&mut self, id: TypeId, name: &str, _docs: &Docs) {
1397 let ns = self.owner_namespace(id);
1398 let snake = name.to_snake_case();
1399 let mut own = ns.clone();
1400 let mut borrow = own.clone();
1401 own.push_str("_own");
1402 borrow.push_str("_borrow");
1403 own.push_str("_");
1404 borrow.push_str("_");
1405 own.push_str(&snake);
1406 borrow.push_str(&snake);
1407 own.push_str("_t");
1408 borrow.push_str("_t");
1409
1410 self.src.h_helpers(&format!(
1413 "
1414extern void {ns}_{snake}_drop_own({own} handle);
1415 "
1416 ));
1417 let import_module = if self.in_import {
1418 self.wasm_import_module.unwrap().to_string()
1419 } else {
1420 let module = match self.interface {
1421 Some((_, key)) => self.resolve.name_world_key(key),
1422 None => unimplemented!("resource exports from worlds"),
1423 };
1424 format!("[export]{module}")
1425 };
1426
1427 let drop_fn = format!("__wasm_import_{ns}_{snake}_drop");
1428
1429 self.src.c_helpers(&format!(
1430 r#"
1431__attribute__((__import_module__("{import_module}"), __import_name__("[resource-drop]{name}")))
1432extern void {drop_fn}(int32_t handle);
1433
1434void {ns}_{snake}_drop_own({own} handle) {{
1435 {drop_fn}(handle.__handle);
1436}}
1437 "#
1438 ));
1439
1440 self.src.h_defs(&format!(
1443 "\ntypedef struct {own} {{\nint32_t __handle;\n}} {own};\n"
1444 ));
1445
1446 if self.in_import {
1447 self.src.h_defs(&format!(
1451 "\ntypedef struct {borrow} {{\nint32_t __handle;\n}} {borrow};\n"
1452 ));
1453
1454 if !self.autodrop_enabled() {
1456 self.src.h_helpers(&format!(
1461 "\nextern void {ns}_{snake}_drop_borrow({borrow} handle);\n"
1462 ));
1463
1464 self.src.c_helpers(&format!(
1465 "
1466void {ns}_{snake}_drop_borrow({borrow} handle) {{
1467 __wasm_import_{ns}_{snake}_drop(handle.__handle);
1468}}
1469 "
1470 ));
1471 }
1472
1473 self.src.h_helpers(&format!(
1477 "
1478extern {borrow} {ns}_borrow_{snake}({own} handle);
1479 "
1480 ));
1481
1482 self.src.c_helpers(&format!(
1483 r#"
1484{borrow} {ns}_borrow_{snake}({own} arg) {{
1485 return ({borrow}) {{ arg.__handle }};
1486}}
1487 "#
1488 ));
1489 } else {
1490 self.src.h_defs("\n");
1493 self.src.h_defs("typedef struct ");
1494 let ty_name = self.r#gen.type_names[&id].clone();
1495 self.src.h_defs(&ty_name);
1496 self.src.h_defs(" ");
1497 self.print_typedef_target(id);
1498 let (_, key) = self.interface.unwrap();
1499 let module = self.resolve.name_world_key(key);
1500
1501 self.src
1505 .h_defs(&format!("\ntypedef {ty_name}* {borrow};\n"));
1506
1507 self.src.h_helpers(&format!(
1516 "
1517extern {own} {ns}_{snake}_new({ty_name} *rep);
1518extern {ty_name}* {ns}_{snake}_rep({own} handle);
1519void {ns}_{snake}_destructor({ty_name} *rep);
1520 "
1521 ));
1522
1523 self.src.c_helpers(&format!(
1524 r#"
1525__attribute__(( __import_module__("[export]{module}"), __import_name__("[resource-new]{name}")))
1526extern int32_t __wasm_import_{ns}_{snake}_new(int32_t);
1527
1528__attribute__((__import_module__("[export]{module}"), __import_name__("[resource-rep]{name}")))
1529extern int32_t __wasm_import_{ns}_{snake}_rep(int32_t);
1530
1531{own} {ns}_{snake}_new({ty_name} *rep) {{
1532 return ({own}) {{ __wasm_import_{ns}_{snake}_new((int32_t) rep) }};
1533}}
1534
1535{ty_name}* {ns}_{snake}_rep({own} handle) {{
1536 return ({ns}_{snake}_t*) __wasm_import_{ns}_{snake}_rep(handle.__handle);
1537}}
1538
1539__attribute__((__export_name__("{module}#[dtor]{snake}")))
1540void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
1541 {ns}_{snake}_destructor(arg);
1542}}
1543 "#
1544 ));
1545 }
1546
1547 self.r#gen.resources.insert(
1548 id,
1549 ResourceInfo {
1550 own,
1551 borrow,
1552 direction: if self.in_import {
1553 Direction::Import
1554 } else {
1555 Direction::Export
1556 },
1557 drop_fn,
1558 },
1559 );
1560 }
1561
1562 fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1563 self.src.h_defs("\n");
1564 self.docs(docs, SourceType::HDefs);
1565 self.start_typedef_struct(id);
1566 for (i, ty) in tuple.types.iter().enumerate() {
1567 self.print_ty(SourceType::HDefs, ty);
1568 uwriteln!(self.src.h_defs, " f{i};");
1569 }
1570 self.finish_typedef_struct(id);
1571 }
1572
1573 fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1574 self.src.h_defs("\n");
1575 self.docs(docs, SourceType::HDefs);
1576 self.src.h_defs("typedef ");
1577 let repr = flags_repr(flags);
1578 self.src.h_defs(int_repr(repr));
1579 self.src.h_defs(" ");
1580 self.print_typedef_target(id);
1581
1582 if flags.flags.len() > 0 {
1583 self.src.h_defs("\n");
1584 }
1585 let ns = self.owner_namespace(id).to_shouty_snake_case();
1586 for (i, flag) in flags.flags.iter().enumerate() {
1587 self.docs(&flag.docs, SourceType::HDefs);
1588 uwriteln!(
1589 self.src.h_defs,
1590 "#define {ns}_{}_{} (1 << {i})",
1591 name.to_shouty_snake_case(),
1592 flag.name.to_shouty_snake_case(),
1593 );
1594 }
1595 }
1596
1597 fn type_variant(&mut self, id: TypeId, name: &str, variant: &Variant, docs: &Docs) {
1598 self.src.h_defs("\n");
1599 self.docs(docs, SourceType::HDefs);
1600 self.start_typedef_struct(id);
1601 self.src.h_defs(int_repr(variant.tag()));
1602 self.src.h_defs(" tag;\n");
1603
1604 let cases_with_data = Vec::from_iter(
1605 variant
1606 .cases
1607 .iter()
1608 .filter_map(|case| case.ty.as_ref().map(|ty| (&case.name, ty))),
1609 );
1610
1611 if !cases_with_data.is_empty() {
1612 self.src.h_defs("union {\n");
1613 for (name, ty) in cases_with_data {
1614 self.print_ty(SourceType::HDefs, ty);
1615 self.src.h_defs(" ");
1616 self.src.h_defs(&to_c_ident(name));
1617 self.src.h_defs(";\n");
1618 }
1619 self.src.h_defs("} val;\n");
1620 }
1621 self.finish_typedef_struct(id);
1622
1623 if variant.cases.len() > 0 {
1624 self.src.h_defs("\n");
1625 }
1626 let ns = self.owner_namespace(id).to_shouty_snake_case();
1627 for (i, case) in variant.cases.iter().enumerate() {
1628 self.docs(&case.docs, SourceType::HDefs);
1629 uwriteln!(
1630 self.src.h_defs,
1631 "#define {ns}_{}_{} {i}",
1632 name.to_shouty_snake_case(),
1633 case.name.to_shouty_snake_case(),
1634 );
1635 }
1636 }
1637
1638 fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1639 self.src.h_defs("\n");
1640 self.docs(docs, SourceType::HDefs);
1641 self.start_typedef_struct(id);
1642 self.src.h_defs("bool is_some;\n");
1643 self.print_ty(SourceType::HDefs, payload);
1644 self.src.h_defs(" val;\n");
1645 self.finish_typedef_struct(id);
1646 }
1647
1648 fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
1649 self.src.h_defs("\n");
1650 self.docs(docs, SourceType::HDefs);
1651 self.start_typedef_struct(id);
1652 self.src.h_defs("bool is_err;\n");
1653 if result.ok.is_some() || result.err.is_some() {
1654 self.src.h_defs("union {\n");
1655 if let Some(ok) = result.ok.as_ref() {
1656 self.print_ty(SourceType::HDefs, ok);
1657 self.src.h_defs(" ok;\n");
1658 }
1659 if let Some(err) = result.err.as_ref() {
1660 self.print_ty(SourceType::HDefs, err);
1661 self.src.h_defs(" err;\n");
1662 }
1663 self.src.h_defs("} val;\n");
1664 }
1665 self.finish_typedef_struct(id);
1666 }
1667
1668 fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1669 uwrite!(self.src.h_defs, "\n");
1670 self.docs(docs, SourceType::HDefs);
1671 let int_t = int_repr(enum_.tag());
1672 uwrite!(self.src.h_defs, "typedef {int_t} ");
1673 self.print_typedef_target(id);
1674
1675 if enum_.cases.len() > 0 {
1676 self.src.h_defs("\n");
1677 }
1678 let ns = self.owner_namespace(id).to_shouty_snake_case();
1679 for (i, case) in enum_.cases.iter().enumerate() {
1680 self.docs(&case.docs, SourceType::HDefs);
1681 uwriteln!(
1682 self.src.h_defs,
1683 "#define {ns}_{}_{} {i}",
1684 name.to_shouty_snake_case(),
1685 case.name.to_shouty_snake_case(),
1686 );
1687 }
1688 }
1689
1690 fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
1691 let target = dealias(self.resolve, id);
1695 if matches!(&self.resolve.types[target].kind, TypeDefKind::Resource) {
1696 return;
1697 }
1698
1699 self.src.h_defs("\n");
1700 self.docs(docs, SourceType::HDefs);
1701 self.src.h_defs("typedef ");
1702 self.print_ty(SourceType::HDefs, ty);
1703 self.src.h_defs(" ");
1704 self.print_typedef_target(id);
1705 }
1706
1707 fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
1708 self.src.h_defs("\n");
1709 self.docs(docs, SourceType::HDefs);
1710 self.start_typedef_struct(id);
1711 self.print_ty(SourceType::HDefs, ty);
1712 self.src.h_defs(" *ptr;\n");
1713 self.src.h_defs("size_t len;\n");
1714 self.finish_typedef_struct(id);
1715 }
1716
1717 fn type_future(&mut self, id: TypeId, _name: &str, _ty: &Option<Type>, docs: &Docs) {
1718 self.src.h_defs("\n");
1719 self.docs(docs, SourceType::HDefs);
1720 self.src.h_defs("\ntypedef uint32_t ");
1721 self.print_typedef_target(id);
1722 }
1723
1724 fn type_stream(&mut self, id: TypeId, _name: &str, _ty: &Option<Type>, docs: &Docs) {
1725 self.src.h_defs("\n");
1726 self.docs(docs, SourceType::HDefs);
1727 self.src.h_defs("\ntypedef uint32_t ");
1728 self.print_typedef_target(id);
1729 }
1730
1731 fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
1732 let _ = (id, name, ty, docs);
1733 }
1734}
1735
1736impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> {
1737 fn resolve(&self) -> &'a Resolve {
1738 self.resolve
1739 }
1740
1741 fn anonymous_type_handle(&mut self, id: TypeId, handle: &Handle, _docs: &Docs) {
1742 self.src.h_defs("\ntypedef ");
1743 let resource = match handle {
1744 Handle::Borrow(id) | Handle::Own(id) => id,
1745 };
1746 let info = &self.r#gen.resources[&dealias(self.resolve, *resource)];
1747 match handle {
1748 Handle::Borrow(_) => self.src.h_defs(&info.borrow),
1749 Handle::Own(_) => self.src.h_defs(&info.own),
1750 }
1751 self.src.h_defs(" ");
1752 self.print_typedef_target(id);
1753 }
1754
1755 fn anonymous_type_tuple(&mut self, id: TypeId, ty: &Tuple, _docs: &Docs) {
1756 self.src.h_defs("\ntypedef ");
1757 self.src.h_defs("struct {\n");
1758 for (i, t) in ty.types.iter().enumerate() {
1759 let ty = self.r#gen.type_name(t);
1760 uwriteln!(self.src.h_defs, "{ty} f{i};");
1761 }
1762 self.src.h_defs("}");
1763 self.src.h_defs(" ");
1764 self.print_typedef_target(id);
1765 }
1766
1767 fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, _docs: &Docs) {
1768 self.src.h_defs("\ntypedef ");
1769 self.src.h_defs("struct {\n");
1770 self.src.h_defs("bool is_some;\n");
1771 let ty = self.r#gen.type_name(ty);
1772 uwriteln!(self.src.h_defs, "{ty} val;");
1773 self.src.h_defs("}");
1774 self.src.h_defs(" ");
1775 self.print_typedef_target(id);
1776 }
1777
1778 fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, _docs: &Docs) {
1779 self.src.h_defs("\ntypedef ");
1780 self.src.h_defs(
1781 "struct {
1782 bool is_err;
1783 ",
1784 );
1785 let ok_ty = ty.ok.as_ref();
1786 let err_ty = ty.err.as_ref();
1787 if ok_ty.is_some() || err_ty.is_some() {
1788 self.src.h_defs("union {\n");
1789 if let Some(ok) = ok_ty {
1790 let ty = self.r#gen.type_name(ok);
1791 uwriteln!(self.src.h_defs, "{ty} ok;");
1792 }
1793 if let Some(err) = err_ty {
1794 let ty = self.r#gen.type_name(err);
1795 uwriteln!(self.src.h_defs, "{ty} err;");
1796 }
1797 self.src.h_defs("} val;\n");
1798 }
1799 self.src.h_defs("}");
1800 self.src.h_defs(" ");
1801 self.print_typedef_target(id);
1802 }
1803
1804 fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, _docs: &Docs) {
1805 self.src.h_defs("\ntypedef ");
1806 self.src.h_defs("struct {\n");
1807 let ty = self.r#gen.type_name(ty);
1808 uwriteln!(self.src.h_defs, "{ty} *ptr;");
1809 self.src.h_defs("size_t len;\n");
1810 self.src.h_defs("}");
1811 self.src.h_defs(" ");
1812 self.print_typedef_target(id);
1813 }
1814
1815 fn anonymous_type_future(&mut self, id: TypeId, _ty: &Option<Type>, _docs: &Docs) {
1816 self.src.h_defs("\ntypedef uint32_t ");
1817 self.print_typedef_target(id);
1818 }
1819
1820 fn anonymous_type_stream(&mut self, id: TypeId, _ty: &Option<Type>, _docs: &Docs) {
1821 self.src.h_defs("\ntypedef uint32_t ");
1822 self.print_typedef_target(id);
1823 }
1824
1825 fn anonymous_type_type(&mut self, _id: TypeId, _ty: &Type, _docs: &Docs) {
1826 todo!("print_anonymous_type for type");
1827 }
1828
1829 fn anonymous_type_fixed_length_list(
1830 &mut self,
1831 _id: TypeId,
1832 _ty: &Type,
1833 _size: u32,
1834 _docs: &Docs,
1835 ) {
1836 todo!("print_anonymous_type for fixed length list");
1837 }
1838}
1839
1840pub enum CTypeNameInfo<'a> {
1841 Named { name: &'a str },
1842 Anonymous { is_prim: bool },
1843}
1844
1845pub fn gen_type_name(resolve: &Resolve, ty: TypeId) -> (CTypeNameInfo<'_>, String) {
1848 let mut encoded = String::new();
1849 push_ty_name(resolve, &Type::Id(ty), &mut encoded);
1850 let info = if let Some(name) = &resolve.types[ty].name {
1851 CTypeNameInfo::Named {
1852 name: name.as_ref(),
1853 }
1854 } else {
1855 CTypeNameInfo::Anonymous {
1856 is_prim: is_prim_type_id(resolve, ty),
1857 }
1858 };
1859
1860 (info, encoded)
1861}
1862
1863impl InterfaceGenerator<'_> {
1864 fn define_interface_types(&mut self, id: InterfaceId) {
1865 let mut live = LiveTypes::default();
1866 live.add_interface(self.resolve, id);
1867 self.define_live_types(live);
1868 }
1869
1870 fn define_function_types(&mut self, funcs: &[(&str, &Function)]) {
1871 let mut live = LiveTypes::default();
1872 for (_, func) in funcs {
1873 live.add_func(self.resolve, func);
1874 }
1875 self.define_live_types(live);
1876 }
1877
1878 fn define_live_types(&mut self, live: LiveTypes) {
1879 for ty in live.iter() {
1880 if self.r#gen.type_names.contains_key(&ty) {
1881 continue;
1882 }
1883
1884 let (info, encoded) = gen_type_name(&self.resolve, ty);
1885 match info {
1886 CTypeNameInfo::Named { name } => {
1887 let typedef_name = format!("{}_{encoded}_t", self.owner_namespace(ty));
1888 let prev = self.r#gen.type_names.insert(ty, typedef_name.clone());
1889 assert!(prev.is_none());
1890
1891 self.define_type(name, ty)
1892 }
1893
1894 CTypeNameInfo::Anonymous { is_prim } => {
1895 let (defined, name) = if is_prim {
1896 let namespace = self.r#gen.world.to_snake_case();
1897 let name = format!("{namespace}_{encoded}_t");
1898 let new_prim = self.r#gen.prim_names.insert(name.clone());
1899 (!new_prim, name)
1900 } else {
1901 let namespace = self.owner_namespace(ty);
1902 (false, format!("{namespace}_{encoded}_t"))
1903 };
1904
1905 let prev = self.r#gen.type_names.insert(ty, name);
1906 assert!(prev.is_none());
1907
1908 if defined {
1909 continue;
1910 }
1911
1912 let kind = &self.resolve.types[ty].kind;
1913 if let TypeDefKind::Handle(handle) = kind {
1914 let resource = match handle {
1915 Handle::Borrow(id) | Handle::Own(id) => id,
1916 };
1917 let origin = dealias(self.resolve, *resource);
1918 if origin == *resource {
1919 continue;
1920 }
1921 }
1922
1923 self.define_anonymous_type(ty)
1924 }
1925 }
1926
1927 self.define_dtor(ty);
1928 }
1929 }
1930
1931 fn define_dtor(&mut self, id: TypeId) {
1932 let h_helpers_start = self.src.h_helpers.len();
1933 let c_helpers_start = self.src.c_helpers.len();
1934
1935 let name = self.r#gen.type_names[&id].clone();
1936 let prefix = name.strip_suffix("_t").unwrap();
1937
1938 self.src
1939 .h_helpers(&format!("\nvoid {prefix}_free({name} *ptr);\n"));
1940 self.src
1941 .c_helpers(&format!("\nvoid {prefix}_free({name} *ptr) {{\n"));
1942 let c_helpers_body_start = self.src.c_helpers.len();
1943 match &self.resolve.types[id].kind {
1944 TypeDefKind::Type(t) => self.free(t, "ptr"),
1945
1946 TypeDefKind::Flags(_) => {}
1947 TypeDefKind::Enum(_) => {}
1948
1949 TypeDefKind::Record(r) => {
1950 for field in r.fields.iter() {
1951 self.free(&field.ty, &format!("&ptr->{}", to_c_ident(&field.name)));
1952 }
1953 }
1954
1955 TypeDefKind::Tuple(t) => {
1956 for (i, ty) in t.types.iter().enumerate() {
1957 self.free(ty, &format!("&ptr->f{i}"));
1958 }
1959 }
1960
1961 TypeDefKind::List(t) => {
1962 self.src.c_helpers("size_t list_len = ptr->len;\n");
1963 uwriteln!(self.src.c_helpers, "if (list_len > 0) {{");
1964 let mut t_name = String::new();
1965 self.r#gen.push_type_name(t, &mut t_name);
1966 self.src
1967 .c_helpers(&format!("{t_name} *list_ptr = ptr->ptr;\n"));
1968 self.src
1969 .c_helpers("for (size_t i = 0; i < list_len; i++) {\n");
1970 self.free(t, "&list_ptr[i]");
1971 self.src.c_helpers("}\n");
1972 uwriteln!(self.src.c_helpers, "free(list_ptr);");
1973 uwriteln!(self.src.c_helpers, "}}");
1974 }
1975
1976 TypeDefKind::Variant(v) => {
1977 self.src.c_helpers("switch ((int32_t) ptr->tag) {\n");
1978 for (i, case) in v.cases.iter().enumerate() {
1979 if let Some(ty) = &case.ty {
1980 uwriteln!(self.src.c_helpers, "case {}: {{", i);
1981 let expr = format!("&ptr->val.{}", to_c_ident(&case.name));
1982 self.free(ty, &expr);
1983 self.src.c_helpers("break;\n");
1984 self.src.c_helpers("}\n");
1985 }
1986 }
1987 self.src.c_helpers("}\n");
1988 }
1989
1990 TypeDefKind::Option(t) => {
1991 self.src.c_helpers("if (ptr->is_some) {\n");
1992 self.free(t, "&ptr->val");
1993 self.src.c_helpers("}\n");
1994 }
1995
1996 TypeDefKind::Result(r) => {
1997 self.src.c_helpers("if (!ptr->is_err) {\n");
1998 if let Some(ok) = &r.ok {
1999 self.free(ok, "&ptr->val.ok");
2000 }
2001 if let Some(err) = &r.err {
2002 self.src.c_helpers("} else {\n");
2003 self.free(err, "&ptr->val.err");
2004 }
2005 self.src.c_helpers("}\n");
2006 }
2007 TypeDefKind::Future(_) | TypeDefKind::Stream(_) => {
2008 self.free(&Type::Id(id), "*ptr");
2009 }
2010 TypeDefKind::Resource => {}
2011 TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
2012 self.free(&Type::Id(*id), "*ptr");
2013 }
2014 TypeDefKind::Unknown => unreachable!(),
2015 TypeDefKind::FixedSizeList(..) => todo!(),
2016 TypeDefKind::Map(..) => todo!(),
2017 }
2018 if c_helpers_body_start == self.src.c_helpers.len() {
2019 self.src.c_helpers.as_mut_string().truncate(c_helpers_start);
2020 self.src.h_helpers.as_mut_string().truncate(h_helpers_start);
2021 return;
2022 }
2023 self.src.c_helpers("}\n");
2024 self.r#gen.dtor_funcs.insert(id, format!("{prefix}_free"));
2025 }
2026
2027 fn free(&mut self, ty: &Type, expr: &str) {
2028 match ty {
2029 Type::Id(id) => {
2030 if let Some(dtor) = self.r#gen.dtor_funcs.get(&id) {
2031 self.src.c_helpers(&format!("{dtor}({expr});\n"));
2032 }
2033 }
2034 Type::String => {
2035 let snake = self.r#gen.world.to_snake_case();
2036 self.src
2037 .c_helpers(&format!("{snake}_string_free({expr});\n"));
2038 }
2039 Type::Bool
2040 | Type::U8
2041 | Type::S8
2042 | Type::U16
2043 | Type::S16
2044 | Type::U32
2045 | Type::S32
2046 | Type::U64
2047 | Type::S64
2048 | Type::F32
2049 | Type::F64
2050 | Type::Char => {}
2051 Type::ErrorContext => todo!("error context free"),
2052 }
2053 }
2054
2055 fn c_func_name(&self, interface_id: Option<&WorldKey>, func: &Function) -> String {
2056 c_func_name(
2057 self.in_import,
2058 self.resolve,
2059 &self.r#gen.world,
2060 interface_id,
2061 func,
2062 &self.r#gen.renamed_interfaces,
2063 )
2064 }
2065
2066 fn import(&mut self, interface_name: Option<&WorldKey>, func: &Function) {
2067 let async_ = self
2068 .r#gen
2069 .opts
2070 .async_
2071 .is_async(self.resolve, interface_name, func, true);
2072 if async_ {
2073 self.r#gen.needs_async = true;
2074 }
2075
2076 self.docs(&func.docs, SourceType::HFns);
2077 let (variant, import_prefix) = if async_ {
2078 (AbiVariant::GuestImportAsync, "[async-lower]")
2079 } else {
2080 (AbiVariant::GuestImport, "")
2081 };
2082 let sig = self.resolve.wasm_signature(variant, func);
2083
2084 self.src.c_fns("\n");
2085
2086 uwriteln!(
2090 self.src.c_fns,
2091 "__attribute__((__import_module__(\"{}\"), __import_name__(\"{import_prefix}{}\")))",
2092 match interface_name {
2093 Some(name) => self.resolve.name_world_key(name),
2094 None => "$root".to_string(),
2095 },
2096 func.name
2097 );
2098 let name = self.c_func_name(interface_name, func);
2099 let import_name = self.r#gen.names.tmp(&format!("__wasm_import_{name}",));
2100 self.src.c_fns("extern ");
2101 match sig.results.len() {
2102 0 => self.src.c_fns("void"),
2103 1 => self.src.c_fns(wasm_type(sig.results[0])),
2104 _ => unimplemented!("multi-value return not supported"),
2105 }
2106 self.src.c_fns(" ");
2107 self.src.c_fns(&import_name);
2108 self.src.c_fns("(");
2109 for (i, param) in sig.params.iter().enumerate() {
2110 if i > 0 {
2111 self.src.c_fns(", ");
2112 }
2113 self.src.c_fns(wasm_type(*param));
2114 }
2115 if sig.params.len() == 0 {
2116 self.src.c_fns("void");
2117 }
2118 self.src.c_fns(");\n");
2119
2120 self.src.h_fns("extern ");
2123 let c_sig = self.print_sig(interface_name, func, &sig, async_);
2124 self.src.c_adapters("\n");
2125 self.src.c_adapters(&c_sig.sig);
2126 self.src.c_adapters(" {\n");
2127
2128 if async_ {
2129 self.import_body_async(func, c_sig, &sig, &import_name);
2130 } else {
2131 self.import_body_sync(func, c_sig, &import_name);
2132 }
2133
2134 self.src.c_adapters("}\n");
2135
2136 self.generate_async_futures_and_streams("", func, interface_name);
2137 }
2138
2139 fn import_body_sync(&mut self, func: &Function, c_sig: CSig, import_name: &str) {
2140 let mut optional_adapters = String::from("");
2143 if !self.r#gen.opts.no_sig_flattening {
2144 for (i, (_, param)) in c_sig.params.iter().enumerate() {
2145 let ty = &func.params[i].1;
2146 if let Type::Id(id) = ty {
2147 if let TypeDefKind::Option(_) = &self.resolve.types[*id].kind {
2148 let ty = self.r#gen.type_name(ty);
2149 uwrite!(
2150 optional_adapters,
2151 "{ty} {param};
2152 {param}.is_some = maybe_{param} != NULL;"
2153 );
2154 uwriteln!(
2155 optional_adapters,
2156 "if (maybe_{param}) {{
2157 {param}.val = *maybe_{param};
2158 }}",
2159 );
2160 }
2161 }
2162 }
2163 }
2164
2165 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
2166 for (pointer, param) in f.sig.params.iter() {
2167 if *pointer {
2168 f.params.push(format!("*{param}"));
2169 } else {
2170 f.params.push(param.clone());
2171 }
2172 }
2173 for ptr in f.sig.retptrs.iter() {
2174 f.locals.insert(ptr).unwrap();
2175 }
2176 f.src.push_str(&optional_adapters);
2177 abi::call(
2178 f.r#gen.resolve,
2179 AbiVariant::GuestImport,
2180 LiftLower::LowerArgsLiftResults,
2181 func,
2182 &mut f,
2183 false,
2184 );
2185
2186 let FunctionBindgen {
2187 src,
2188 import_return_pointer_area_size,
2189 import_return_pointer_area_align,
2190 ..
2191 } = f;
2192
2193 if !import_return_pointer_area_size.is_empty() {
2194 self.src.c_adapters(&format!(
2195 "\
2196 __attribute__((__aligned__({})))
2197 uint8_t ret_area[{}];
2198 ",
2199 import_return_pointer_area_align.format(POINTER_SIZE_EXPRESSION),
2200 import_return_pointer_area_size.format(POINTER_SIZE_EXPRESSION),
2201 ));
2202 }
2203
2204 self.src.c_adapters(&String::from(src));
2205 }
2206
2207 fn import_body_async(
2208 &mut self,
2209 func: &Function,
2210 c_sig: CSig,
2211 wasm_sig: &WasmSignature,
2212 import_name: &str,
2213 ) {
2214 let mut params = Vec::new();
2215 if wasm_sig.indirect_params {
2216 params.push(format!("(uint8_t*) {}", c_sig.params[0].1));
2217 } else {
2218 let mut f = FunctionBindgen::new(self, c_sig.clone(), "INVALID");
2219 for (i, (_, ty)) in func.params.iter().enumerate() {
2220 let param = &c_sig.params[i].1;
2221 params.extend(abi::lower_flat(f.r#gen.resolve, &mut f, param.clone(), ty));
2222 }
2223 f.r#gen.src.c_adapters.push_str(&f.src);
2224 }
2225 if func.result.is_some() {
2226 params.push(format!("(uint8_t*) {}", c_sig.params.last().unwrap().1));
2227 }
2228 uwriteln!(
2229 self.src.c_adapters,
2230 "return {import_name}({});",
2231 params.join(", "),
2232 );
2233 }
2234
2235 fn export(&mut self, func: &Function, interface_name: Option<&WorldKey>) {
2236 let async_ = self
2237 .r#gen
2238 .opts
2239 .async_
2240 .is_async(self.resolve, interface_name, func, false);
2241
2242 let (variant, prefix) = if async_ {
2243 self.r#gen.needs_async = true;
2244 (AbiVariant::GuestExportAsync, "[async-lift]")
2245 } else {
2246 (AbiVariant::GuestExport, "")
2247 };
2248
2249 let sig = self.resolve.wasm_signature(variant, func);
2250
2251 self.src.c_fns("\n");
2252
2253 let core_module_name = interface_name.map(|s| self.resolve.name_world_key(s));
2254 let export_name = func.legacy_core_export_name(core_module_name.as_deref());
2255
2256 let h_sig = self.print_sig(interface_name, func, &sig, async_);
2259
2260 uwriteln!(
2263 self.src.c_adapters,
2264 "\n__attribute__((__export_name__(\"{prefix}{export_name}\")))"
2265 );
2266 let name = self.c_func_name(interface_name, func);
2267 let import_name = self.r#gen.names.tmp(&format!("__wasm_export_{name}"));
2268
2269 let mut f = FunctionBindgen::new(self, h_sig, &import_name);
2270 match sig.results.len() {
2271 0 => f.r#gen.src.c_adapters("void"),
2272 1 => f.r#gen.src.c_adapters(wasm_type(sig.results[0])),
2273 _ => unimplemented!("multi-value return not supported"),
2274 }
2275 f.r#gen.src.c_adapters(" ");
2276 f.r#gen.src.c_adapters(&import_name);
2277 f.r#gen.src.c_adapters("(");
2278 for (i, param) in sig.params.iter().enumerate() {
2279 if i > 0 {
2280 f.r#gen.src.c_adapters(", ");
2281 }
2282 let name = f.locals.tmp("arg");
2283 uwrite!(f.r#gen.src.c_adapters, "{} {}", wasm_type(*param), name);
2284 f.params.push(name);
2285 }
2286 if sig.params.len() == 0 {
2287 f.r#gen.src.c_adapters("void");
2288 }
2289 f.r#gen.src.c_adapters(") {\n");
2290
2291 abi::call(
2293 f.r#gen.resolve,
2294 variant,
2295 LiftLower::LiftArgsLowerResults,
2296 func,
2297 &mut f,
2298 async_,
2299 );
2300 let FunctionBindgen {
2301 src,
2302 deferred_task_return,
2303 ..
2304 } = f;
2305 self.src.c_adapters(&src);
2306 self.src.c_adapters("}\n");
2307
2308 if async_ {
2309 let snake = self.r#gen.world.to_snake_case();
2310 let return_ty = match &func.result {
2311 Some(ty) => format!("{} ret", self.r#gen.type_name(ty)),
2312 None => "void".to_string(),
2313 };
2314 let DeferredTaskReturn::Emitted {
2315 body: mut task_return_body,
2316 name: task_return_name,
2317 params: task_return_params,
2318 } = deferred_task_return
2319 else {
2320 unreachable!()
2321 };
2322 let task_return_param_tys = task_return_params
2323 .iter()
2324 .map(|(ty, _expr)| wasm_type(*ty))
2325 .collect::<Vec<_>>()
2326 .join(", ");
2327 let task_return_param_exprs = task_return_params
2328 .iter()
2329 .map(|(_ty, expr)| expr.as_str())
2330 .collect::<Vec<_>>()
2331 .join(", ");
2332 let task_return_body = task_return_body.as_mut_string();
2333 uwriteln!(
2334 self.src.h_fns,
2335 "{snake}_callback_code_t {name}_callback({snake}_event_t *event);",
2336 );
2337 uwriteln!(self.src.h_helpers, "void {name}_return({return_ty});");
2338 let import_module = match interface_name {
2339 Some(name) => self.resolve.name_world_key(name),
2340 None => "$root".to_string(),
2341 };
2342 uwriteln!(
2343 self.src.c_helpers,
2344 r#"
2345__attribute__((__export_name__("[callback]{prefix}{export_name}")))
2346uint32_t {import_name}_callback(uint32_t event_raw, uint32_t waitable, uint32_t code) {{
2347 {snake}_event_t event;
2348 event.event = ({snake}_event_code_t) event_raw;
2349 event.waitable = waitable;
2350 event.code = code;
2351 return {name}_callback(&event);
2352}}
2353
2354__attribute__((__import_module__("[export]{import_module}"), __import_name__("{task_return_name}")))
2355void {import_name}__task_return({task_return_param_tys});
2356
2357void {name}_return({return_ty}) {{
2358 {task_return_body}
2359 {import_name}__task_return({task_return_param_exprs});
2360}}
2361 "#
2362 );
2363 } else if abi::guest_export_needs_post_return(self.resolve, func) {
2364 uwriteln!(
2365 self.src.c_fns,
2366 "__attribute__((__weak__, __export_name__(\"cabi_post_{export_name}\")))"
2367 );
2368 uwrite!(self.src.c_fns, "void {import_name}_post_return(");
2369
2370 let mut params = Vec::new();
2371 let mut c_sig = CSig {
2372 name: String::from("INVALID"),
2373 sig: String::from("INVALID"),
2374 params: Vec::new(),
2375 ret: Return::default(),
2376 retptrs: Vec::new(),
2377 };
2378 for (i, result) in sig.results.iter().enumerate() {
2379 let name = format!("arg{i}");
2380 uwrite!(self.src.c_fns, "{} {name}", wasm_type(*result));
2381 c_sig.params.push((false, name.clone()));
2382 params.push(name);
2383 }
2384 self.src.c_fns.push_str(") {\n");
2385
2386 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
2387 f.params = params;
2388 abi::post_return(f.r#gen.resolve, func, &mut f);
2389 let FunctionBindgen { src, .. } = f;
2390 self.src.c_fns(&src);
2391 self.src.c_fns("}\n");
2392 }
2393
2394 self.generate_async_futures_and_streams("[export]", func, interface_name);
2395 }
2396
2397 fn print_sig(
2398 &mut self,
2399 interface_name: Option<&WorldKey>,
2400 func: &Function,
2401 sig: &WasmSignature,
2402 async_: bool,
2403 ) -> CSig {
2404 let name = self.c_func_name(interface_name, func);
2405 self.r#gen.names.insert(&name).expect("duplicate symbols");
2406
2407 let start = self.src.h_fns.len();
2408 let mut result_rets = false;
2409 let mut result_rets_has_ok_type = false;
2410
2411 let ret = if async_ && !self.in_import {
2412 Return {
2413 scalar: func.result.map(Scalar::Type),
2414 retptrs: Vec::new(),
2415 }
2416 } else {
2417 self.classify_ret(func)
2418 };
2419 if async_ {
2420 let snake = self.r#gen.world.to_snake_case();
2421 if self.in_import {
2422 uwrite!(self.src.h_fns, "{snake}_subtask_status_t");
2423 } else {
2424 uwrite!(self.src.h_fns, "{snake}_callback_code_t");
2425 }
2426 } else {
2427 match &ret.scalar {
2428 None | Some(Scalar::Void) => self.src.h_fns("void"),
2429 Some(Scalar::OptionBool(_id)) => self.src.h_fns("bool"),
2430 Some(Scalar::ResultBool(ok, _err)) => {
2431 result_rets = true;
2432 result_rets_has_ok_type = ok.is_some();
2433 self.src.h_fns("bool");
2434 }
2435 Some(Scalar::Type(ty)) => self.print_ty(SourceType::HFns, ty),
2436 }
2437 }
2438 self.src.h_fns(" ");
2439 self.src.h_fns(&name);
2440 self.src.h_fns("(");
2441 let params;
2442 let mut retptrs = Vec::new();
2443 if async_ && self.in_import {
2444 params = self.print_sig_async_import_params(&name, func, sig);
2445 } else if async_ && !self.in_import {
2446 params = self.print_sig_params(func);
2447 } else {
2448 params = self.print_sig_params(func);
2449 let single_ret = ret.retptrs.len() == 1;
2450 for (i, ty) in ret.retptrs.iter().enumerate() {
2451 if i > 0 || func.params.len() > 0 {
2452 self.src.h_fns(", ");
2453 }
2454 self.print_ty(SourceType::HFns, ty);
2455 self.src.h_fns(" *");
2456 let name: String = if result_rets {
2457 assert!(i <= 1);
2458 if i == 0 && result_rets_has_ok_type {
2459 "ret".into()
2460 } else {
2461 "err".into()
2462 }
2463 } else if single_ret {
2464 "ret".into()
2465 } else {
2466 format!("ret{i}")
2467 };
2468 self.src.h_fns(&name);
2469 retptrs.push(name);
2470 }
2471 if func.params.len() == 0 && ret.retptrs.len() == 0 {
2472 self.src.h_fns("void");
2473 }
2474 }
2475 self.src.h_fns(")");
2476
2477 let sig = self.src.h_fns[start..].to_string();
2478 self.src.h_fns(";\n");
2479
2480 CSig {
2481 sig,
2482 name,
2483 params,
2484 ret,
2485 retptrs,
2486 }
2487 }
2488
2489 fn print_sig_params(&mut self, func: &Function) -> Vec<(bool, String)> {
2490 let mut params = Vec::new();
2491 for (i, (name, ty)) in func.params.iter().enumerate() {
2492 if i > 0 {
2493 self.src.h_fns(", ");
2494 }
2495 let pointer = is_arg_by_pointer(self.resolve, ty);
2496 let optional_type = if let Type::Id(id) = ty {
2498 if let TypeDefKind::Option(option_ty) = &self.resolve.types[*id].kind {
2499 if !self.r#gen.opts.no_sig_flattening {
2500 Some(option_ty)
2501 } else {
2502 None
2503 }
2504 } else {
2505 None
2506 }
2507 } else {
2508 None
2509 };
2510 let (print_ty, print_name) = if !self.r#gen.opts.no_sig_flattening {
2511 if let Some(option_ty) = optional_type {
2512 (option_ty, format!("maybe_{}", to_c_ident(name)))
2513 } else {
2514 (ty, to_c_ident(name))
2515 }
2516 } else {
2517 (ty, to_c_ident(name))
2518 };
2519 self.print_ty(SourceType::HFns, print_ty);
2520 self.src.h_fns(" ");
2521 if pointer {
2522 self.src.h_fns("*");
2523 }
2524 self.src.h_fns(&print_name);
2525 params.push((optional_type.is_none() && pointer, to_c_ident(name)));
2526 }
2527 params
2528 }
2529
2530 fn print_sig_async_import_params(
2531 &mut self,
2532 c_func_name: &str,
2533 func: &Function,
2534 sig: &WasmSignature,
2535 ) -> Vec<(bool, String)> {
2536 let mut params = Vec::new();
2537 let mut printed = false;
2538 if sig.indirect_params {
2539 match &func.params[..] {
2540 [] => {}
2541 [(_name, ty)] => {
2542 printed = true;
2543 let name = "arg".to_string();
2544 self.print_ty(SourceType::HFns, ty);
2545 self.src.h_fns(" *");
2546 self.src.h_fns(&name);
2547 params.push((true, name));
2548 }
2549 multiple => {
2550 printed = true;
2551 let names = multiple
2552 .iter()
2553 .map(|(name, ty)| (to_c_ident(name), self.r#gen.type_name(ty)))
2554 .collect::<Vec<_>>();
2555 uwriteln!(self.src.h_defs, "typedef struct {c_func_name}_args {{");
2556 for (name, ty) in names {
2557 uwriteln!(self.src.h_defs, "{ty} {name};");
2558 }
2559 uwriteln!(self.src.h_defs, "}} {c_func_name}_args_t;");
2560 uwrite!(self.src.h_fns, "{c_func_name}_args_t *args");
2561 params.push((true, "args".to_string()));
2562 }
2563 }
2564 } else {
2565 for (name, ty) in func.params.iter() {
2566 let name = to_c_ident(name);
2567 if printed {
2568 self.src.h_fns(", ");
2569 } else {
2570 printed = true;
2571 }
2572 self.print_ty(SourceType::HFns, ty);
2573 self.src.h_fns(" ");
2574 self.src.h_fns(&name);
2575 params.push((false, name));
2576 }
2577 }
2578 if let Some(ty) = &func.result {
2579 if printed {
2580 self.src.h_fns(", ");
2581 } else {
2582 printed = true;
2583 }
2584 let name = "result".to_string();
2585 self.print_ty(SourceType::HFns, ty);
2586 self.src.h_fns(" *");
2587 self.src.h_fns(&name);
2588 params.push((true, name));
2589 }
2590 if !printed {
2591 self.src.h_fns("void");
2592 }
2593 params
2594 }
2595
2596 fn classify_ret(&mut self, func: &Function) -> Return {
2597 let mut ret = Return::default();
2598 match &func.result {
2599 None => ret.scalar = Some(Scalar::Void),
2600 Some(ty) => {
2601 ret.return_single(self.resolve, ty, ty, !self.r#gen.opts.no_sig_flattening);
2602 }
2603 }
2604 return ret;
2605 }
2606
2607 fn print_typedef_target(&mut self, id: TypeId) {
2608 let name = &self.r#gen.type_names[&id];
2609 self.src.h_defs(&name);
2610 self.src.h_defs(";\n");
2611 }
2612
2613 fn start_typedef_struct(&mut self, id: TypeId) {
2614 let name = &self.r#gen.type_names[&id];
2615 self.src.h_defs("typedef struct ");
2616 self.src.h_defs(&name);
2617 self.src.h_defs(" {\n");
2618 }
2619
2620 fn finish_typedef_struct(&mut self, id: TypeId) {
2621 self.src.h_defs("} ");
2622 self.print_typedef_target(id);
2623 }
2624
2625 fn owner_namespace(&self, id: TypeId) -> String {
2626 owner_namespace(
2627 self.interface,
2628 self.in_import,
2629 self.r#gen.world.clone(),
2630 self.resolve,
2631 id,
2632 &self.r#gen.renamed_interfaces,
2633 )
2634 }
2635
2636 fn print_ty(&mut self, stype: SourceType, ty: &Type) {
2637 self.r#gen
2638 .push_type_name(ty, self.src.src(stype).as_mut_string());
2639 }
2640
2641 fn docs(&mut self, docs: &Docs, stype: SourceType) {
2642 let docs = match &docs.contents {
2643 Some(docs) => docs,
2644 None => return,
2645 };
2646 let src = self.src.src(stype);
2647 for line in docs.trim().lines() {
2648 src.push_str("// ");
2649 src.push_str(line);
2650 src.push_str("\n");
2651 }
2652 }
2653
2654 fn autodrop_enabled(&self) -> bool {
2655 self.r#gen.opts.autodrop_borrows == Enabled::Yes
2656 }
2657
2658 fn contains_droppable_borrow(&self, ty: &Type) -> bool {
2659 if let Type::Id(id) = ty {
2660 match &self.resolve.types[*id].kind {
2661 TypeDefKind::Handle(h) => match h {
2662 Handle::Borrow(id) => {
2665 !self.in_import
2666 && matches!(
2667 self.r#gen.resources[&dealias(self.resolve, *id)].direction,
2668 Direction::Import
2669 )
2670 }
2671
2672 Handle::Own(_) => false,
2673 },
2674
2675 TypeDefKind::Resource | TypeDefKind::Flags(_) | TypeDefKind::Enum(_) => false,
2676
2677 TypeDefKind::Record(r) => r
2678 .fields
2679 .iter()
2680 .any(|f| self.contains_droppable_borrow(&f.ty)),
2681
2682 TypeDefKind::Tuple(t) => {
2683 t.types.iter().any(|ty| self.contains_droppable_borrow(ty))
2684 }
2685
2686 TypeDefKind::Variant(v) => v.cases.iter().any(|case| {
2687 case.ty
2688 .as_ref()
2689 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2690 }),
2691
2692 TypeDefKind::Option(ty) => self.contains_droppable_borrow(ty),
2693
2694 TypeDefKind::Result(r) => {
2695 r.ok.as_ref()
2696 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2697 || r.err
2698 .as_ref()
2699 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2700 }
2701
2702 TypeDefKind::List(ty) => self.contains_droppable_borrow(ty),
2703
2704 TypeDefKind::Future(_) | TypeDefKind::Stream(_) => false,
2705
2706 TypeDefKind::Type(ty) => self.contains_droppable_borrow(ty),
2707
2708 TypeDefKind::Unknown => false,
2709 TypeDefKind::FixedSizeList(..) => todo!(),
2710 TypeDefKind::Map(..) => todo!(),
2711 }
2712 } else {
2713 false
2714 }
2715 }
2716
2717 fn generate_async_futures_and_streams(
2718 &mut self,
2719 prefix: &str,
2720 func: &Function,
2721 interface: Option<&WorldKey>,
2722 ) {
2723 let module = format!(
2724 "{prefix}{}",
2725 interface
2726 .map(|name| self.resolve.name_world_key(name))
2727 .unwrap_or_else(|| "$root".into())
2728 );
2729 for (index, ty) in func
2730 .find_futures_and_streams(self.resolve)
2731 .into_iter()
2732 .enumerate()
2733 {
2734 let func_name = &func.name;
2735
2736 match &self.resolve.types[ty].kind {
2737 TypeDefKind::Future(payload_type) => {
2738 self.generate_async_future_or_stream(
2739 PayloadFor::Future,
2740 &module,
2741 index,
2742 func_name,
2743 ty,
2744 payload_type.as_ref(),
2745 );
2746 }
2747 TypeDefKind::Stream(payload_type) => {
2748 self.generate_async_future_or_stream(
2749 PayloadFor::Stream,
2750 &module,
2751 index,
2752 func_name,
2753 ty,
2754 payload_type.as_ref(),
2755 );
2756 }
2757 _ => unreachable!(),
2758 }
2759 }
2760 }
2761
2762 fn generate_async_future_or_stream(
2763 &mut self,
2764 payload_for: PayloadFor,
2765 module: &str,
2766 index: usize,
2767 func_name: &str,
2768 ty: TypeId,
2769 payload_type: Option<&Type>,
2770 ) {
2771 if !self.r#gen.futures.insert(ty) {
2772 return;
2773 }
2774 let ty = self.r#gen.type_name(&Type::Id(ty));
2775 let name = ty.strip_suffix("_t").unwrap();
2776 let snake = self.r#gen.world.to_snake_case();
2777 let kind = match payload_for {
2778 PayloadFor::Future => "future",
2779 PayloadFor::Stream => "stream",
2780 };
2781 let payload_len_arg = match payload_for {
2782 PayloadFor::Future => "",
2783 PayloadFor::Stream => ", size_t",
2784 };
2785 let (read_arg_ty, read_arg_expr, write_arg_ty, write_arg_expr) =
2786 match (payload_for, payload_type) {
2787 (PayloadFor::Future, None) => ("".to_string(), "NULL", "".to_string(), "NULL"),
2788 (PayloadFor::Future, Some(ty)) => {
2789 let ty = self.r#gen.type_name(ty);
2790 (
2791 format!(", {ty} *buf"),
2792 "(uint8_t*) buf",
2793 format!(", const {ty} *buf"),
2794 "(const uint8_t*) buf",
2795 )
2796 }
2797 (PayloadFor::Stream, None) => (
2798 ", size_t amt".to_string(),
2799 "NULL, amt",
2800 ", size_t amt".to_string(),
2801 "NULL, amt",
2802 ),
2803 (PayloadFor::Stream, Some(ty)) => {
2804 let ty = self.r#gen.type_name(ty);
2805 (
2806 format!(", {ty} *buf, size_t amt"),
2807 "(uint8_t*) buf, amt",
2808 format!(", const {ty} *buf, size_t amt"),
2809 "(const uint8_t*) buf, amt",
2810 )
2811 }
2812 };
2813
2814 let empty = "";
2817 uwriteln!(
2818 self.src.h_helpers,
2819 r#"
2820typedef uint32_t {name}_writer_t;
2821
2822{ty} {name}_new({name}_writer_t *writer);
2823{snake}_waitable_status_t {name}_read({ty} reader{read_arg_ty});
2824{snake}_waitable_status_t {name}_write({name}_writer_t writer{write_arg_ty});
2825{snake}_waitable_status_t {name}_cancel_read({ty} reader);
2826{snake}_waitable_status_t {name}_cancel_write({name}_writer_t writer);
2827void {name}_drop_readable({ty} reader);{empty}
2828void {name}_drop_writable({name}_writer_t writer);
2829 "#,
2830 );
2831 uwriteln!(
2832 self.src.c_helpers,
2833 r#"
2834__attribute__((__import_module__("{module}"), __import_name__("[{kind}-new-{index}]{func_name}")))
2835extern uint64_t {name}__new(void);
2836__attribute__((__import_module__("{module}"), __import_name__("[async-lower][{kind}-read-{index}]{func_name}")))
2837extern uint32_t {name}__read(uint32_t, uint8_t*{payload_len_arg});
2838__attribute__((__import_module__("{module}"), __import_name__("[async-lower][{kind}-write-{index}]{func_name}")))
2839extern uint32_t {name}__write(uint32_t, const uint8_t*{payload_len_arg});
2840__attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-read-{index}]{func_name}")))
2841extern uint32_t {name}__cancel_read(uint32_t);
2842__attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-write-{index}]{func_name}")))
2843extern uint32_t {name}__cancel_write(uint32_t);
2844__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-readable-{index}]{func_name}")))
2845extern void {name}__drop_readable(uint32_t);
2846__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-writable-{index}]{func_name}")))
2847extern void {name}__drop_writable(uint32_t);
2848
2849{ty} {name}_new({name}_writer_t *writer) {{
2850 uint64_t packed = {name}__new();
2851 *writer = (uint32_t) (packed >> 32);
2852 return (uint32_t) packed;
2853}}
2854
2855{snake}_waitable_status_t {name}_read({ty} reader{read_arg_ty}) {{
2856 return {name}__read(reader, {read_arg_expr});
2857}}
2858
2859{snake}_waitable_status_t {name}_write({name}_writer_t writer{write_arg_ty}) {{
2860 return {name}__write(writer, {write_arg_expr});
2861}}
2862
2863{snake}_waitable_status_t {name}_cancel_read({ty} reader){empty} {{
2864 return {name}__cancel_read(reader);
2865}}
2866
2867{snake}_waitable_status_t {name}_cancel_write({name}_writer_t writer) {{
2868 return {name}__cancel_write(writer);
2869}}
2870
2871void {name}_drop_readable({ty} reader){empty} {{
2872 {name}__drop_readable(reader);
2873}}
2874
2875void {name}_drop_writable({name}_writer_t writer) {{
2876 {name}__drop_writable(writer);
2877}}
2878 "#,
2879 );
2880 }
2881}
2882
2883enum PayloadFor {
2884 Future,
2885 Stream,
2886}
2887
2888struct DroppableBorrow {
2889 name: String,
2890 ty: TypeId,
2891}
2892
2893struct FunctionBindgen<'a, 'b> {
2894 r#gen: &'a mut InterfaceGenerator<'b>,
2895 locals: Ns,
2896 src: wit_bindgen_core::Source,
2897 sig: CSig,
2898 func_to_call: &'a str,
2899 block_storage: Vec<wit_bindgen_core::Source>,
2900 blocks: Vec<(String, Vec<String>)>,
2901 payloads: Vec<String>,
2902 params: Vec<String>,
2903 wasm_return: Option<String>,
2904 ret_store_cnt: usize,
2905 import_return_pointer_area_size: ArchitectureSize,
2906 import_return_pointer_area_align: Alignment,
2907
2908 deferred_task_return: DeferredTaskReturn,
2916
2917 borrows: Vec<DroppableBorrow>,
2920
2921 borrow_decls: wit_bindgen_core::Source,
2923}
2924
2925enum DeferredTaskReturn {
2928 None,
2932
2933 Generating {
2940 prev_src: wit_bindgen_core::Source,
2945 },
2946
2947 Emitted {
2955 name: String,
2958 params: Vec<(WasmType, String)>,
2964 body: wit_bindgen_core::Source,
2968 },
2969}
2970
2971impl<'a, 'b> FunctionBindgen<'a, 'b> {
2972 fn new(
2973 r#gen: &'a mut InterfaceGenerator<'b>,
2974 sig: CSig,
2975 func_to_call: &'a str,
2976 ) -> FunctionBindgen<'a, 'b> {
2977 let mut locals = Ns::default();
2978 for (_, name) in sig.params.iter() {
2979 locals.insert(name).unwrap();
2980 }
2981 FunctionBindgen {
2982 r#gen,
2983 sig,
2984 locals,
2985 src: Default::default(),
2986 func_to_call,
2987 block_storage: Vec::new(),
2988 blocks: Vec::new(),
2989 payloads: Vec::new(),
2990 params: Vec::new(),
2991 wasm_return: None,
2992 ret_store_cnt: 0,
2993 import_return_pointer_area_size: Default::default(),
2994 import_return_pointer_area_align: Default::default(),
2995 borrow_decls: Default::default(),
2996 borrows: Vec::new(),
2997 deferred_task_return: DeferredTaskReturn::None,
2998 }
2999 }
3000
3001 fn store_op(&mut self, op: &str, loc: &str) {
3002 self.src.push_str(loc);
3003 self.src.push_str(" = ");
3004 self.src.push_str(op);
3005 self.src.push_str(";\n");
3006 }
3007
3008 fn load(
3009 &mut self,
3010 ty: &str,
3011 offset: ArchitectureSize,
3012 operands: &[String],
3013 results: &mut Vec<String>,
3014 ) {
3015 results.push(format!(
3016 "*(({}*) ({} + {}))",
3017 ty,
3018 operands[0],
3019 offset.format(POINTER_SIZE_EXPRESSION)
3020 ));
3021 }
3022
3023 fn load_ext(
3024 &mut self,
3025 ty: &str,
3026 offset: ArchitectureSize,
3027 operands: &[String],
3028 results: &mut Vec<String>,
3029 ) {
3030 self.load(ty, offset, operands, results);
3031 let result = results.pop().unwrap();
3032 results.push(format!("(int32_t) {result}"));
3033 }
3034
3035 fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) {
3036 uwriteln!(
3037 self.src,
3038 "*(({}*)({} + {})) = {};",
3039 ty,
3040 operands[1],
3041 offset.format(POINTER_SIZE_EXPRESSION),
3042 operands[0]
3043 );
3044 }
3045
3046 fn store_in_retptr(&mut self, operand: &String) {
3047 self.store_op(
3048 operand,
3049 &format!("*{}", self.sig.retptrs[self.ret_store_cnt]),
3050 );
3051 self.ret_store_cnt = self.ret_store_cnt + 1;
3052 }
3053
3054 fn empty_return_value(&mut self) {
3055 self.ret_store_cnt = self.ret_store_cnt + 1;
3058 }
3059
3060 fn assert_no_droppable_borrows(&self, context: &str, ty: &Type) {
3061 if !self.r#gen.in_import
3062 && self.r#gen.autodrop_enabled()
3063 && self.r#gen.contains_droppable_borrow(ty)
3064 {
3065 panic!("Unable to autodrop borrows in `{context}` values, please disable autodrop")
3066 }
3067 }
3068}
3069
3070impl Bindgen for FunctionBindgen<'_, '_> {
3071 type Operand = String;
3072
3073 fn sizes(&self) -> &SizeAlign {
3074 &self.r#gen.r#gen.sizes
3075 }
3076
3077 fn push_block(&mut self) {
3078 let prev = mem::take(&mut self.src);
3079 self.block_storage.push(prev);
3080 }
3081
3082 fn finish_block(&mut self, operands: &mut Vec<String>) {
3083 let to_restore = self.block_storage.pop().unwrap();
3084 let src = mem::replace(&mut self.src, to_restore);
3085 self.blocks.push((src.into(), mem::take(operands)));
3086 }
3087
3088 fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
3089 let ptr = self.locals.tmp("ptr");
3090
3091 if self.r#gen.in_import {
3094 self.import_return_pointer_area_size = self.import_return_pointer_area_size.max(size);
3095 self.import_return_pointer_area_align =
3096 self.import_return_pointer_area_align.max(align);
3097 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &ret_area;", ptr);
3098 } else {
3099 self.r#gen.r#gen.return_pointer_area_size =
3100 self.r#gen.r#gen.return_pointer_area_size.max(size);
3101 self.r#gen.r#gen.return_pointer_area_align =
3102 self.r#gen.r#gen.return_pointer_area_align.max(align);
3103 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &RET_AREA;", ptr);
3105 }
3106
3107 ptr
3108 }
3109
3110 fn is_list_canonical(&self, resolve: &Resolve, ty: &Type) -> bool {
3111 resolve.all_bits_valid(ty)
3112 }
3113
3114 fn emit(
3115 &mut self,
3116 resolve: &Resolve,
3117 inst: &Instruction<'_>,
3118 operands: &mut Vec<String>,
3119 results: &mut Vec<String>,
3120 ) {
3121 match inst {
3122 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
3123 Instruction::I32Const { val } => results.push(val.to_string()),
3124 Instruction::ConstZero { tys } => {
3125 for _ in tys.iter() {
3126 results.push("0".to_string());
3127 }
3128 }
3129
3130 Instruction::U8FromI32 => results.push(format!("(uint8_t) ({})", operands[0])),
3132 Instruction::S8FromI32 => results.push(format!("(int8_t) ({})", operands[0])),
3133 Instruction::U16FromI32 => results.push(format!("(uint16_t) ({})", operands[0])),
3134 Instruction::S16FromI32 => results.push(format!("(int16_t) ({})", operands[0])),
3135 Instruction::U32FromI32 => results.push(format!("(uint32_t) ({})", operands[0])),
3136 Instruction::S32FromI32 | Instruction::S64FromI64 => results.push(operands[0].clone()),
3137 Instruction::U64FromI64 => results.push(format!("(uint64_t) ({})", operands[0])),
3138
3139 Instruction::I32FromU8
3140 | Instruction::I32FromS8
3141 | Instruction::I32FromU16
3142 | Instruction::I32FromS16
3143 | Instruction::I32FromU32 => {
3144 results.push(format!("(int32_t) ({})", operands[0]));
3145 }
3146 Instruction::I32FromS32 | Instruction::I64FromS64 => results.push(operands[0].clone()),
3147 Instruction::I64FromU64 => {
3148 results.push(format!("(int64_t) ({})", operands[0]));
3149 }
3150
3151 Instruction::CoreF32FromF32
3154 | Instruction::CoreF64FromF64
3155 | Instruction::F32FromCoreF32
3156 | Instruction::F64FromCoreF64 => {
3157 results.push(operands[0].clone());
3158 }
3159
3160 Instruction::CharFromI32 => {
3162 results.push(format!("(uint32_t) ({})", operands[0]));
3163 }
3164 Instruction::I32FromChar => {
3165 results.push(format!("(int32_t) ({})", operands[0]));
3166 }
3167
3168 Instruction::Bitcasts { casts } => {
3169 for (cast, op) in casts.iter().zip(operands) {
3170 let op = self.r#gen.r#gen.perform_cast(op, cast);
3171 results.push(op);
3172 }
3173 }
3174
3175 Instruction::BoolFromI32 | Instruction::I32FromBool => {
3176 results.push(operands[0].clone());
3177 }
3178
3179 Instruction::RecordLower { record, .. } => {
3180 let op = &operands[0];
3181 for f in record.fields.iter() {
3182 results.push(format!("({}).{}", op, to_c_ident(&f.name)));
3183 }
3184 }
3185 Instruction::RecordLift { ty, record, .. } => {
3186 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3187 let mut result = format!("({name}) {{\n");
3188 for (field, op) in record.fields.iter().zip(operands.iter()) {
3189 let field_ty = self.r#gen.r#gen.type_name(&field.ty);
3190 uwriteln!(result, "({}) {},", field_ty, op);
3191 }
3192 result.push_str("}");
3193 results.push(result);
3194 }
3195
3196 Instruction::TupleLower { tuple, .. } => {
3197 let op = &operands[0];
3198 for i in 0..tuple.types.len() {
3199 results.push(format!("({op}).f{i}"));
3200 }
3201 }
3202 Instruction::TupleLift { ty, tuple, .. } => {
3203 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3204 let mut result = format!("({name}) {{\n");
3205 for (ty, op) in tuple.types.iter().zip(operands.iter()) {
3206 let ty = self.r#gen.r#gen.type_name(&ty);
3207 uwriteln!(result, "({}) {},", ty, op);
3208 }
3209 result.push_str("}");
3210 results.push(result);
3211 }
3212
3213 Instruction::HandleLower { .. } => {
3214 let op = &operands[0];
3215 results.push(format!("({op}).__handle"))
3216 }
3217
3218 Instruction::HandleLift { handle, ty, .. } => match handle {
3219 Handle::Borrow(resource)
3220 if matches!(
3221 self.r#gen.r#gen.resources[&dealias(resolve, *resource)].direction,
3222 Direction::Export
3223 ) =>
3224 {
3225 let op = &operands[0];
3228 let name = self
3229 .r#gen
3230 .r#gen
3231 .type_name(&Type::Id(dealias(resolve, *resource)));
3232 results.push(format!("(({name}*) {op})"))
3233 }
3234 _ => {
3235 let op = &operands[0];
3236 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3237 results.push(format!("({name}) {{ {op} }}"));
3238
3239 if let Handle::Borrow(id) = handle {
3240 if !self.r#gen.in_import && self.r#gen.autodrop_enabled() {
3241 let ty = dealias(self.r#gen.resolve, *id);
3244
3245 let name = self.locals.tmp("borrow");
3246 uwriteln!(self.borrow_decls, "int32_t {name} = 0;");
3247 uwriteln!(self.src, "{name} = {op};");
3248
3249 self.borrows.push(DroppableBorrow { name, ty });
3250 }
3251 }
3252 }
3253 },
3254
3255 Instruction::FlagsLower { flags, ty, .. } => match flags_repr(flags) {
3257 Int::U8 | Int::U16 | Int::U32 => {
3258 results.push(operands.pop().unwrap());
3259 }
3260 Int::U64 => {
3261 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3262 let tmp = self.locals.tmp("flags");
3263 uwriteln!(self.src, "{name} {tmp} = {};", operands[0]);
3264 results.push(format!("{tmp} & 0xffffffff"));
3265 results.push(format!("({tmp} >> 32) & 0xffffffff"));
3266 }
3267 },
3268
3269 Instruction::FlagsLift { flags, ty, .. } => match flags_repr(flags) {
3270 Int::U8 | Int::U16 | Int::U32 => {
3271 results.push(operands.pop().unwrap());
3272 }
3273 Int::U64 => {
3274 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3275 let op0 = &operands[0];
3276 let op1 = &operands[1];
3277 results.push(format!("(({name}) ({op0})) | ((({name}) ({op1})) << 32)"));
3278 }
3279 },
3280
3281 Instruction::VariantPayloadName => {
3282 let name = self.locals.tmp("payload");
3283 results.push(format!("*{name}"));
3284 self.payloads.push(name);
3285 }
3286
3287 Instruction::VariantLower {
3288 variant,
3289 results: result_types,
3290 ..
3291 } => {
3292 let blocks = self
3293 .blocks
3294 .drain(self.blocks.len() - variant.cases.len()..)
3295 .collect::<Vec<_>>();
3296 let payloads = self
3297 .payloads
3298 .drain(self.payloads.len() - variant.cases.len()..)
3299 .collect::<Vec<_>>();
3300
3301 let mut variant_results = Vec::with_capacity(result_types.len());
3302 for ty in result_types.iter() {
3303 let name = self.locals.tmp("variant");
3304 results.push(name.clone());
3305 self.src.push_str(wasm_type(*ty));
3306 self.src.push_str(" ");
3307 self.src.push_str(&name);
3308 self.src.push_str(";\n");
3309 variant_results.push(name);
3310 }
3311
3312 let expr_to_match = format!("({}).tag", operands[0]);
3313
3314 uwriteln!(self.src, "switch ((int32_t) {}) {{", expr_to_match);
3315 for (i, ((case, (block, block_results)), payload)) in
3316 variant.cases.iter().zip(blocks).zip(payloads).enumerate()
3317 {
3318 uwriteln!(self.src, "case {}: {{", i);
3319 if let Some(ty) = case.ty.as_ref() {
3320 let ty = self.r#gen.r#gen.type_name(ty);
3321 uwrite!(
3322 self.src,
3323 "const {} *{} = &({}).val",
3324 ty,
3325 payload,
3326 operands[0],
3327 );
3328 self.src.push_str(".");
3329 self.src.push_str(&to_c_ident(&case.name));
3330 self.src.push_str(";\n");
3331 }
3332 self.src.push_str(&block);
3333
3334 for (name, result) in variant_results.iter().zip(&block_results) {
3335 uwriteln!(self.src, "{} = {};", name, result);
3336 }
3337 self.src.push_str("break;\n}\n");
3338 }
3339 self.src.push_str("}\n");
3340 }
3341
3342 Instruction::VariantLift { variant, ty, .. } => {
3343 let blocks = self
3344 .blocks
3345 .drain(self.blocks.len() - variant.cases.len()..)
3346 .collect::<Vec<_>>();
3347
3348 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3349 let result = self.locals.tmp("variant");
3350 uwriteln!(self.src, "{} {};", ty, result);
3351 uwriteln!(self.src, "{}.tag = {};", result, operands[0]);
3352 uwriteln!(self.src, "switch ((int32_t) {}.tag) {{", result);
3353 for (i, (case, (block, block_results))) in
3354 variant.cases.iter().zip(blocks).enumerate()
3355 {
3356 uwriteln!(self.src, "case {}: {{", i);
3357 self.src.push_str(&block);
3358 assert!(block_results.len() == (case.ty.is_some() as usize));
3359
3360 if let Some(_) = case.ty.as_ref() {
3361 let mut dst = format!("{result}.val");
3362 dst.push_str(".");
3363 dst.push_str(&to_c_ident(&case.name));
3364 self.store_op(&block_results[0], &dst);
3365 }
3366 self.src.push_str("break;\n}\n");
3367 }
3368 self.src.push_str("}\n");
3369 results.push(result);
3370 }
3371
3372 Instruction::OptionLower {
3373 results: result_types,
3374 payload,
3375 ..
3376 } => {
3377 let (mut some, some_results) = self.blocks.pop().unwrap();
3378 let (mut none, none_results) = self.blocks.pop().unwrap();
3379 let some_payload = self.payloads.pop().unwrap();
3380 let _none_payload = self.payloads.pop().unwrap();
3381
3382 for (i, ty) in result_types.iter().enumerate() {
3383 let name = self.locals.tmp("option");
3384 results.push(name.clone());
3385 self.src.push_str(wasm_type(*ty));
3386 self.src.push_str(" ");
3387 self.src.push_str(&name);
3388 self.src.push_str(";\n");
3389 let some_result = &some_results[i];
3390 uwriteln!(some, "{name} = {some_result};");
3391 let none_result = &none_results[i];
3392 uwriteln!(none, "{name} = {none_result};");
3393 }
3394
3395 let op0 = &operands[0];
3396 let ty = self.r#gen.r#gen.type_name(payload);
3397 let bind_some = format!("const {ty} *{some_payload} = &({op0}).val;");
3398
3399 uwrite!(
3400 self.src,
3401 "\
3402 if (({op0}).is_some) {{
3403 {bind_some}
3404 {some}}} else {{
3405 {none}}}
3406 "
3407 );
3408 }
3409
3410 Instruction::OptionLift { ty, .. } => {
3411 let (mut some, some_results) = self.blocks.pop().unwrap();
3412 let (mut none, none_results) = self.blocks.pop().unwrap();
3413 assert!(none_results.len() == 0);
3414 assert!(some_results.len() == 1);
3415 let some_result = &some_results[0];
3416
3417 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3418 let result = self.locals.tmp("option");
3419 uwriteln!(self.src, "{ty} {result};");
3420 let op0 = &operands[0];
3421 let set_some = format!("{result}.val = {some_result};\n");
3422 if none.len() > 0 {
3423 none.push('\n');
3424 }
3425 if some.len() > 0 {
3426 some.push('\n');
3427 }
3428 uwrite!(
3429 self.src,
3430 "switch ({op0}) {{
3431 case 0: {{
3432 {result}.is_some = false;
3433 {none}\
3434 break;
3435 }}
3436 case 1: {{
3437 {result}.is_some = true;
3438 {some}\
3439 {set_some}\
3440 break;
3441 }}
3442 }}\n"
3443 );
3444 results.push(result);
3445 }
3446
3447 Instruction::ResultLower {
3448 results: result_types,
3449 result,
3450 ..
3451 } => {
3452 let (mut err, err_results) = self.blocks.pop().unwrap();
3453 let (mut ok, ok_results) = self.blocks.pop().unwrap();
3454 let err_payload = self.payloads.pop().unwrap();
3455 let ok_payload = self.payloads.pop().unwrap();
3456
3457 for (i, ty) in result_types.iter().enumerate() {
3458 let name = self.locals.tmp("result");
3459 results.push(name.clone());
3460 self.src.push_str(wasm_type(*ty));
3461 self.src.push_str(" ");
3462 self.src.push_str(&name);
3463 self.src.push_str(";\n");
3464 let ok_result = &ok_results[i];
3465 uwriteln!(ok, "{name} = {ok_result};");
3466 let err_result = &err_results[i];
3467 uwriteln!(err, "{name} = {err_result};");
3468 }
3469
3470 let op0 = &operands[0];
3471 let bind_ok = if let Some(ok) = result.ok.as_ref() {
3472 let ok_ty = self.r#gen.r#gen.type_name(ok);
3473 format!("const {ok_ty} *{ok_payload} = &({op0}).val.ok;")
3474 } else {
3475 String::new()
3476 };
3477 let bind_err = if let Some(err) = result.err.as_ref() {
3478 let err_ty = self.r#gen.r#gen.type_name(err);
3479 format!("const {err_ty} *{err_payload} = &({op0}).val.err;")
3480 } else {
3481 String::new()
3482 };
3483 uwrite!(
3484 self.src,
3485 "\
3486 if (({op0}).is_err) {{
3487 {bind_err}\
3488 {err}\
3489 }} else {{
3490 {bind_ok}\
3491 {ok}\
3492 }}
3493 "
3494 );
3495 }
3496
3497 Instruction::ResultLift { result, ty, .. } => {
3498 let (mut err, err_results) = self.blocks.pop().unwrap();
3499 assert!(err_results.len() == (result.err.is_some() as usize));
3500 let (mut ok, ok_results) = self.blocks.pop().unwrap();
3501 assert!(ok_results.len() == (result.ok.is_some() as usize));
3502
3503 if err.len() > 0 {
3504 err.push_str("\n");
3505 }
3506 if ok.len() > 0 {
3507 ok.push_str("\n");
3508 }
3509
3510 let result_tmp = self.locals.tmp("result");
3511 let set_ok = if let Some(_) = result.ok.as_ref() {
3512 let ok_result = &ok_results[0];
3513 format!("{result_tmp}.val.ok = {ok_result};\n")
3514 } else {
3515 String::new()
3516 };
3517 let set_err = if let Some(_) = result.err.as_ref() {
3518 let err_result = &err_results[0];
3519 format!("{result_tmp}.val.err = {err_result};\n")
3520 } else {
3521 String::new()
3522 };
3523
3524 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3525 uwriteln!(self.src, "{ty} {result_tmp};");
3526 let op0 = &operands[0];
3527 uwriteln!(
3528 self.src,
3529 "switch ({op0}) {{
3530 case 0: {{
3531 {result_tmp}.is_err = false;
3532 {ok}\
3533 {set_ok}\
3534 break;
3535 }}
3536 case 1: {{
3537 {result_tmp}.is_err = true;
3538 {err}\
3539 {set_err}\
3540 break;
3541 }}
3542 }}"
3543 );
3544 results.push(result_tmp);
3545 }
3546
3547 Instruction::EnumLower { .. } => results.push(format!("(int32_t) {}", operands[0])),
3548 Instruction::EnumLift { .. } => results.push(operands.pop().unwrap()),
3549
3550 Instruction::ListCanonLower { .. } | Instruction::StringLower { .. } => {
3551 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
3552 results.push(format!("({}).len", operands[0]));
3553 }
3554 Instruction::ListCanonLift { element, ty, .. } => {
3555 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
3556
3557 let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3558 let elem_name = self.r#gen.r#gen.type_name(element);
3559 results.push(format!(
3560 "({}) {{ ({}*)({}), ({}) }}",
3561 list_name, elem_name, operands[0], operands[1]
3562 ));
3563 }
3564 Instruction::StringLift { .. } => {
3565 let list_name = self.r#gen.r#gen.type_name(&Type::String);
3566 results.push(format!(
3567 "({}) {{ ({}*)({}), ({}) }}",
3568 list_name,
3569 self.r#gen.r#gen.char_type(),
3570 operands[0],
3571 operands[1]
3572 ));
3573 }
3574
3575 Instruction::ListLower { .. } => {
3576 let _body = self.blocks.pop().unwrap();
3577 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
3578 results.push(format!("({}).len", operands[0]));
3579 }
3580
3581 Instruction::ListLift { element, ty, .. } => {
3582 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
3583
3584 let _body = self.blocks.pop().unwrap();
3585 let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3586 let elem_name = self.r#gen.r#gen.type_name(element);
3587 results.push(format!(
3588 "({}) {{ ({}*)({}), ({}) }}",
3589 list_name, elem_name, operands[0], operands[1]
3590 ));
3591 }
3592 Instruction::IterElem { .. } => results.push("e".to_string()),
3593 Instruction::IterBasePointer => results.push("base".to_string()),
3594
3595 Instruction::CallWasm { sig, .. } => {
3596 match sig.results.len() {
3597 0 => {}
3598 1 => {
3599 self.src.push_str(wasm_type(sig.results[0]));
3600 let ret = self.locals.tmp("ret");
3601 self.wasm_return = Some(ret.clone());
3602 uwrite!(self.src, " {} = ", ret);
3603 results.push(ret);
3604 }
3605 _ => unimplemented!(),
3606 }
3607 self.src.push_str(self.func_to_call);
3608 self.src.push_str("(");
3609 for (i, op) in operands.iter().enumerate() {
3610 if i > 0 {
3611 self.src.push_str(", ");
3612 }
3613 self.src.push_str(op);
3614 }
3615 self.src.push_str(");\n");
3616 }
3617
3618 Instruction::CallInterface { func, async_ } => {
3619 let mut args = String::new();
3620 for (i, (op, (byref, _))) in operands.iter().zip(&self.sig.params).enumerate() {
3621 if i > 0 {
3622 args.push_str(", ");
3623 }
3624 let ty = &func.params[i].1;
3625 if *byref {
3626 let name = self.locals.tmp("arg");
3627 let ty = self.r#gen.r#gen.type_name(ty);
3628 uwriteln!(self.src, "{} {} = {};", ty, name, op);
3629 args.push_str("&");
3630 args.push_str(&name);
3631 } else {
3632 if !self.r#gen.in_import {
3633 if let Type::Id(id) = ty {
3634 if let TypeDefKind::Option(_) = &self.r#gen.resolve.types[*id].kind
3635 {
3636 uwrite!(args, "{op}.is_some ? &({op}.val) : NULL");
3637 continue;
3638 }
3639 }
3640 }
3641 args.push_str(op);
3642 }
3643 }
3644 if *async_ {
3645 let ret = self.locals.tmp("ret");
3646 let snake = self.r#gen.r#gen.world.to_snake_case();
3647 uwriteln!(
3648 self.src,
3649 "{snake}_callback_code_t {ret} = {}({args});",
3650 self.sig.name,
3651 );
3652 uwriteln!(self.src, "return {ret};");
3653 if func.result.is_some() {
3654 results.push("ret".to_string());
3655 }
3656 assert!(matches!(
3657 self.deferred_task_return,
3658 DeferredTaskReturn::None
3659 ));
3660 self.deferred_task_return = DeferredTaskReturn::Generating {
3661 prev_src: mem::take(&mut self.src),
3662 };
3663 return;
3664 }
3665 match &self.sig.ret.scalar {
3666 None => {
3667 let mut retptrs = Vec::new();
3668 for ty in self.sig.ret.retptrs.iter() {
3669 let name = self.locals.tmp("ret");
3670 let ty = self.r#gen.r#gen.type_name(ty);
3671 uwriteln!(self.src, "{} {};", ty, name);
3672 if args.len() > 0 {
3673 args.push_str(", ");
3674 }
3675 args.push_str("&");
3676 args.push_str(&name);
3677 retptrs.push(name);
3678 }
3679 uwriteln!(self.src, "{}({});", self.sig.name, args);
3680 results.extend(retptrs);
3681 }
3682 Some(Scalar::Void) => {
3683 uwriteln!(self.src, "{}({});", self.sig.name, args);
3684 }
3685 Some(Scalar::Type(_)) => {
3686 let ret = self.locals.tmp("ret");
3687 let ty = func.result.unwrap();
3688 let ty = self.r#gen.r#gen.type_name(&ty);
3689 uwriteln!(self.src, "{} {} = {}({});", ty, ret, self.sig.name, args);
3690 results.push(ret);
3691 }
3692 Some(Scalar::OptionBool(ty)) => {
3693 let ret = self.locals.tmp("ret");
3694 let val = self.locals.tmp("val");
3695 if args.len() > 0 {
3696 args.push_str(", ");
3697 }
3698 args.push_str("&");
3699 args.push_str(&val);
3700 let payload_ty = self.r#gen.r#gen.type_name(ty);
3701 uwriteln!(self.src, "{} {};", payload_ty, val);
3702 uwriteln!(self.src, "bool {} = {}({});", ret, self.sig.name, args);
3703 let ty = func.result.unwrap();
3704 let option_ty = self.r#gen.r#gen.type_name(&ty);
3705 let option_ret = self.locals.tmp("ret");
3706 uwrite!(
3707 self.src,
3708 "
3709 {option_ty} {option_ret};
3710 {option_ret}.is_some = {ret};
3711 {option_ret}.val = {val};
3712 ",
3713 );
3714 results.push(option_ret);
3715 }
3716 Some(Scalar::ResultBool(ok, err)) => {
3717 let ty = &func.result.unwrap();
3718 let result_ty = self.r#gen.r#gen.type_name(ty);
3719 let ret = self.locals.tmp("ret");
3720 let mut ret_iter = self.sig.ret.retptrs.iter();
3721 uwriteln!(self.src, "{result_ty} {ret};");
3722 let ok_name = if ok.is_some() {
3723 if let Some(ty) = ret_iter.next() {
3724 let val = self.locals.tmp("ok");
3725 if args.len() > 0 {
3726 uwrite!(args, ", ");
3727 }
3728 uwrite!(args, "&{val}");
3729 let ty = self.r#gen.r#gen.type_name(ty);
3730 uwriteln!(self.src, "{} {};", ty, val);
3731 Some(val)
3732 } else {
3733 None
3734 }
3735 } else {
3736 None
3737 };
3738 let err_name = if let Some(ty) = ret_iter.next() {
3739 let val = self.locals.tmp("err");
3740 if args.len() > 0 {
3741 uwrite!(args, ", ")
3742 }
3743 uwrite!(args, "&{val}");
3744 let ty = self.r#gen.r#gen.type_name(ty);
3745 uwriteln!(self.src, "{} {};", ty, val);
3746 Some(val)
3747 } else {
3748 None
3749 };
3750 assert!(ret_iter.next().is_none());
3751 uwrite!(self.src, "");
3752 uwriteln!(self.src, "{ret}.is_err = !{}({args});", self.sig.name);
3753 if err.is_some() {
3754 if let Some(err_name) = err_name {
3755 uwriteln!(
3756 self.src,
3757 "if ({ret}.is_err) {{
3758 {ret}.val.err = {err_name};
3759 }}",
3760 );
3761 }
3762 }
3763 if ok.is_some() {
3764 if let Some(ok_name) = ok_name {
3765 uwriteln!(
3766 self.src,
3767 "if (!{ret}.is_err) {{
3768 {ret}.val.ok = {ok_name};
3769 }}"
3770 );
3771 } else {
3772 uwrite!(self.src, "\n");
3773 }
3774 }
3775 results.push(ret);
3776 }
3777 }
3778 }
3779 Instruction::Return { .. } if self.r#gen.in_import => match self.sig.ret.scalar {
3780 None => {
3781 for op in operands.iter() {
3782 self.store_in_retptr(op);
3783 }
3784 }
3785 Some(Scalar::Void) => {
3786 assert!(operands.is_empty());
3787 }
3788 Some(Scalar::Type(_)) => {
3789 assert_eq!(operands.len(), 1);
3790 self.src.push_str("return ");
3791 self.src.push_str(&operands[0]);
3792 self.src.push_str(";\n");
3793 }
3794 Some(Scalar::OptionBool(_)) => {
3795 assert_eq!(operands.len(), 1);
3796 let variant = &operands[0];
3797 self.store_in_retptr(&format!("{variant}.val"));
3798 self.src.push_str("return ");
3799 self.src.push_str(&variant);
3800 self.src.push_str(".is_some;\n");
3801 }
3802 Some(Scalar::ResultBool(ok, err)) => {
3803 assert_eq!(operands.len(), 1);
3804 let variant = &operands[0];
3805 assert!(self.sig.retptrs.len() <= 2);
3806 uwriteln!(self.src, "if (!{}.is_err) {{", variant);
3807 if ok.is_some() {
3808 if ok.is_some() {
3809 self.store_in_retptr(&format!("{variant}.val.ok"));
3810 } else {
3811 self.empty_return_value();
3812 }
3813 }
3814 uwriteln!(
3815 self.src,
3816 " return 1;
3817 }} else {{"
3818 );
3819 if err.is_some() {
3820 if err.is_some() {
3821 self.store_in_retptr(&format!("{variant}.val.err"));
3822 } else {
3823 self.empty_return_value();
3824 }
3825 }
3826 uwriteln!(
3827 self.src,
3828 " return 0;
3829 }}"
3830 );
3831 assert_eq!(self.ret_store_cnt, self.sig.retptrs.len());
3832 }
3833 },
3834 Instruction::Return { amt, .. } => {
3835 let src = std::mem::replace(&mut self.src, std::mem::take(&mut self.borrow_decls));
3837 self.src.append_src(&src);
3838
3839 for DroppableBorrow { name, ty } in self.borrows.iter() {
3840 let drop_fn = self.r#gen.r#gen.resources[ty].drop_fn.as_str();
3841 uwriteln!(self.src, "if ({name} != 0) {{");
3842 uwriteln!(self.src, " {drop_fn}({name});");
3843 uwriteln!(self.src, "}}");
3844 }
3845
3846 assert!(*amt <= 1);
3847 if *amt == 1 {
3848 uwriteln!(self.src, "return {};", operands[0]);
3849 }
3850 }
3851
3852 Instruction::I32Load { offset } => self.load("int32_t", *offset, operands, results),
3853 Instruction::I64Load { offset } => self.load("int64_t", *offset, operands, results),
3854 Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
3855 Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
3856 Instruction::PointerLoad { offset } => {
3857 self.load("uint8_t *", *offset, operands, results)
3858 }
3859 Instruction::LengthLoad { offset } => self.load("size_t", *offset, operands, results),
3860 Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
3861 Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
3862 Instruction::F32Store { offset } => self.store("float", *offset, operands),
3863 Instruction::F64Store { offset } => self.store("double", *offset, operands),
3864 Instruction::I32Store8 { offset } => self.store("int8_t", *offset, operands),
3865 Instruction::I32Store16 { offset } => self.store("int16_t", *offset, operands),
3866 Instruction::PointerStore { offset } => self.store("uint8_t *", *offset, operands),
3867 Instruction::LengthStore { offset } => self.store("size_t", *offset, operands),
3868
3869 Instruction::I32Load8U { offset } => {
3870 self.load_ext("uint8_t", *offset, operands, results)
3871 }
3872 Instruction::I32Load8S { offset } => {
3873 self.load_ext("int8_t", *offset, operands, results)
3874 }
3875 Instruction::I32Load16U { offset } => {
3876 self.load_ext("uint16_t", *offset, operands, results)
3877 }
3878 Instruction::I32Load16S { offset } => {
3879 self.load_ext("int16_t", *offset, operands, results)
3880 }
3881
3882 Instruction::GuestDeallocate { .. } => {
3883 uwriteln!(self.src, "free({});", operands[0]);
3884 }
3885 Instruction::GuestDeallocateString => {
3886 uwriteln!(self.src, "if (({}) > 0) {{", operands[1]);
3887 uwriteln!(self.src, "free({});", operands[0]);
3888 uwriteln!(self.src, "}}");
3889 }
3890 Instruction::GuestDeallocateVariant { blocks } => {
3891 let blocks = self
3892 .blocks
3893 .drain(self.blocks.len() - blocks..)
3894 .collect::<Vec<_>>();
3895
3896 uwriteln!(self.src, "switch ((int32_t) {}) {{", operands[0]);
3897 for (i, (block, results)) in blocks.into_iter().enumerate() {
3898 assert!(results.is_empty());
3899 uwriteln!(self.src, "case {}: {{", i);
3900 self.src.push_str(&block);
3901 self.src.push_str("break;\n}\n");
3902 }
3903 self.src.push_str("}\n");
3904 }
3905 Instruction::GuestDeallocateList { element } => {
3906 let (body, results) = self.blocks.pop().unwrap();
3907 assert!(results.is_empty());
3908 let len = self.locals.tmp("len");
3909 uwriteln!(self.src, "size_t {len} = {};", operands[1]);
3910 uwriteln!(self.src, "if ({len} > 0) {{");
3911 let ptr = self.locals.tmp("ptr");
3912 uwriteln!(self.src, "uint8_t *{ptr} = {};", operands[0]);
3913 let i = self.locals.tmp("i");
3914 uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{");
3915 let size = self.r#gen.r#gen.sizes.size(element);
3916 uwriteln!(
3917 self.src,
3918 "uint8_t *base = {ptr} + {i} * {};",
3919 size.format(POINTER_SIZE_EXPRESSION)
3920 );
3921 uwriteln!(self.src, "(void) base;");
3922 uwrite!(self.src, "{body}");
3923 uwriteln!(self.src, "}}");
3924 uwriteln!(self.src, "free({ptr});");
3925 uwriteln!(self.src, "}}");
3926 }
3927
3928 Instruction::Flush { amt } => {
3929 results.extend(operands.iter().take(*amt).cloned());
3930 }
3931
3932 Instruction::AsyncTaskReturn { name, params } => {
3933 let body = match &mut self.deferred_task_return {
3934 DeferredTaskReturn::Generating { prev_src } => {
3935 mem::swap(&mut self.src, prev_src);
3936 mem::take(prev_src)
3937 }
3938 _ => unreachable!(),
3939 };
3940 assert_eq!(params.len(), operands.len());
3941 self.deferred_task_return = DeferredTaskReturn::Emitted {
3942 name: name.to_string(),
3943 body,
3944 params: params
3945 .iter()
3946 .zip(operands)
3947 .map(|(a, b)| (*a, b.clone()))
3948 .collect(),
3949 };
3950 }
3951
3952 Instruction::FutureLift { .. } => {
3953 results.push(format!("((uint32_t) {})", operands[0]));
3954 }
3955 Instruction::FutureLower { .. } => {
3956 results.push(format!("((int32_t) {})", operands[0]));
3957 }
3958 Instruction::StreamLift { .. } => {
3959 results.push(format!("((uint32_t) {})", operands[0]));
3960 }
3961 Instruction::StreamLower { .. } => {
3962 results.push(format!("((int32_t) {})", operands[0]));
3963 }
3964
3965 i => unimplemented!("{:?}", i),
3966 }
3967 }
3968}
3969
3970#[derive(Default, Clone, Copy)]
3971enum SourceType {
3972 #[default]
3973 HDefs,
3974 HFns,
3975 }
3981
3982#[derive(Default)]
3983struct Source {
3984 h_defs: wit_bindgen_core::Source,
3985 h_fns: wit_bindgen_core::Source,
3986 h_helpers: wit_bindgen_core::Source,
3987 h_async: wit_bindgen_core::Source,
3988 c_defs: wit_bindgen_core::Source,
3989 c_fns: wit_bindgen_core::Source,
3990 c_helpers: wit_bindgen_core::Source,
3991 c_adapters: wit_bindgen_core::Source,
3992 c_async: wit_bindgen_core::Source,
3993}
3994
3995impl Source {
3996 fn src(&mut self, stype: SourceType) -> &mut wit_bindgen_core::Source {
3997 match stype {
3998 SourceType::HDefs => &mut self.h_defs,
3999 SourceType::HFns => &mut self.h_fns,
4000 }
4001 }
4002 fn append(&mut self, append_src: &Source) {
4003 self.h_defs.push_str(&append_src.h_defs);
4004 self.h_fns.push_str(&append_src.h_fns);
4005 self.h_helpers.push_str(&append_src.h_helpers);
4006 self.h_async.push_str(&append_src.h_async);
4007 self.c_defs.push_str(&append_src.c_defs);
4008 self.c_fns.push_str(&append_src.c_fns);
4009 self.c_helpers.push_str(&append_src.c_helpers);
4010 self.c_adapters.push_str(&append_src.c_adapters);
4011 self.c_async.push_str(&append_src.c_async);
4012 }
4013 fn h_defs(&mut self, s: &str) {
4014 self.h_defs.push_str(s);
4015 }
4016 fn h_fns(&mut self, s: &str) {
4017 self.h_fns.push_str(s);
4018 }
4019 fn h_helpers(&mut self, s: &str) {
4020 self.h_helpers.push_str(s);
4021 }
4022 fn c_fns(&mut self, s: &str) {
4023 self.c_fns.push_str(s);
4024 }
4025 fn c_helpers(&mut self, s: &str) {
4026 self.c_helpers.push_str(s);
4027 }
4028 fn c_adapters(&mut self, s: &str) {
4029 self.c_adapters.push_str(s);
4030 }
4031}
4032
4033pub fn wasm_type(ty: WasmType) -> &'static str {
4034 match ty {
4035 WasmType::I32 => "int32_t",
4036 WasmType::I64 => "int64_t",
4037 WasmType::F32 => "float",
4038 WasmType::F64 => "double",
4039 WasmType::Pointer => "uint8_t *",
4040 WasmType::PointerOrI64 => "int64_t",
4041 WasmType::Length => "size_t",
4042 }
4043}
4044
4045pub fn int_repr(ty: Int) -> &'static str {
4046 match ty {
4047 Int::U8 => "uint8_t",
4048 Int::U16 => "uint16_t",
4049 Int::U32 => "uint32_t",
4050 Int::U64 => "uint64_t",
4051 }
4052}
4053
4054pub fn flags_repr(f: &Flags) -> Int {
4055 match f.repr() {
4056 FlagsRepr::U8 => Int::U8,
4057 FlagsRepr::U16 => Int::U16,
4058 FlagsRepr::U32(1) => Int::U32,
4059 FlagsRepr::U32(2) => Int::U64,
4060 repr => panic!("unimplemented flags {repr:?}"),
4061 }
4062}
4063
4064pub fn is_arg_by_pointer(resolve: &Resolve, ty: &Type) -> bool {
4065 match ty {
4066 Type::Id(id) => match resolve.types[*id].kind {
4067 TypeDefKind::Type(t) => is_arg_by_pointer(resolve, &t),
4068 TypeDefKind::Variant(_) => true,
4069 TypeDefKind::Option(_) => true,
4070 TypeDefKind::Result(_) => true,
4071 TypeDefKind::Enum(_) => false,
4072 TypeDefKind::Flags(_) => false,
4073 TypeDefKind::Handle(_) => false,
4074 TypeDefKind::Tuple(_) | TypeDefKind::Record(_) | TypeDefKind::List(_) => true,
4075 TypeDefKind::Future(_) => false,
4076 TypeDefKind::Stream(_) => false,
4077 TypeDefKind::Resource => todo!("is_arg_by_pointer for resource"),
4078 TypeDefKind::Unknown => unreachable!(),
4079 TypeDefKind::FixedSizeList(..) => todo!(),
4080 TypeDefKind::Map(..) => todo!(),
4081 },
4082 Type::String => true,
4083 _ => false,
4084 }
4085}
4086
4087pub fn to_c_ident(name: &str) -> String {
4088 match name {
4089 "alignas" => "alignas_".into(),
4092 "alignof" => "alignof_".into(),
4093 "and" => "and_".into(),
4094 "and_eq" => "and_eq_".into(),
4095 "asm" => "asm_".into(),
4096 "atomic_cancel" => "atomic_cancel_".into(),
4097 "atomic_commit" => "atomic_commit_".into(),
4098 "atomic_noexcept" => "atomic_noexcept_".into(),
4099 "auto" => "auto_".into(),
4100 "bitand" => "bitand_".into(),
4101 "bitor" => "bitor_".into(),
4102 "bool" => "bool_".into(),
4103 "break" => "break_".into(),
4104 "case" => "case_".into(),
4105 "catch" => "catch_".into(),
4106 "char" => "char_".into(),
4107 "char8_t" => "char8_t_".into(),
4108 "char16_t" => "char16_t_".into(),
4109 "char32_t" => "char32_t_".into(),
4110 "class" => "class_".into(),
4111 "compl" => "compl_".into(),
4112 "concept" => "concept_".into(),
4113 "const" => "const_".into(),
4114 "consteval" => "consteval_".into(),
4115 "constexpr" => "constexpr_".into(),
4116 "constinit" => "constinit_".into(),
4117 "const_cast" => "const_cast_".into(),
4118 "continue" => "continue_".into(),
4119 "co_await" => "co_await_".into(),
4120 "co_return" => "co_return_".into(),
4121 "co_yield" => "co_yield_".into(),
4122 "decltype" => "decltype_".into(),
4123 "default" => "default_".into(),
4124 "delete" => "delete_".into(),
4125 "do" => "do_".into(),
4126 "double" => "double_".into(),
4127 "dynamic_cast" => "dynamic_cast_".into(),
4128 "else" => "else_".into(),
4129 "enum" => "enum_".into(),
4130 "explicit" => "explicit_".into(),
4131 "export" => "export_".into(),
4132 "extern" => "extern_".into(),
4133 "false" => "false_".into(),
4134 "float" => "float_".into(),
4135 "for" => "for_".into(),
4136 "friend" => "friend_".into(),
4137 "goto" => "goto_".into(),
4138 "if" => "if_".into(),
4139 "inline" => "inline_".into(),
4140 "int" => "int_".into(),
4141 "long" => "long_".into(),
4142 "mutable" => "mutable_".into(),
4143 "namespace" => "namespace_".into(),
4144 "new" => "new_".into(),
4145 "noexcept" => "noexcept_".into(),
4146 "not" => "not_".into(),
4147 "not_eq" => "not_eq_".into(),
4148 "nullptr" => "nullptr_".into(),
4149 "operator" => "operator_".into(),
4150 "or" => "or_".into(),
4151 "or_eq" => "or_eq_".into(),
4152 "private" => "private_".into(),
4153 "protected" => "protected_".into(),
4154 "public" => "public_".into(),
4155 "reflexpr" => "reflexpr_".into(),
4156 "register" => "register_".into(),
4157 "reinterpret_cast" => "reinterpret_cast_".into(),
4158 "requires" => "requires_".into(),
4159 "return" => "return_".into(),
4160 "short" => "short_".into(),
4161 "signed" => "signed_".into(),
4162 "sizeof" => "sizeof_".into(),
4163 "static" => "static_".into(),
4164 "static_assert" => "static_assert_".into(),
4165 "static_cast" => "static_cast_".into(),
4166 "struct" => "struct_".into(),
4167 "switch" => "switch_".into(),
4168 "synchronized" => "synchronized_".into(),
4169 "template" => "template_".into(),
4170 "this" => "this_".into(),
4171 "thread_local" => "thread_local_".into(),
4172 "throw" => "throw_".into(),
4173 "true" => "true_".into(),
4174 "try" => "try_".into(),
4175 "typedef" => "typedef_".into(),
4176 "typeid" => "typeid_".into(),
4177 "typename" => "typename_".into(),
4178 "union" => "union_".into(),
4179 "unsigned" => "unsigned_".into(),
4180 "using" => "using_".into(),
4181 "virtual" => "virtual_".into(),
4182 "void" => "void_".into(),
4183 "volatile" => "volatile_".into(),
4184 "wchar_t" => "wchar_t_".into(),
4185 "while" => "while_".into(),
4186 "xor" => "xor_".into(),
4187 "xor_eq" => "xor_eq_".into(),
4188 "_Packed" => "_Packed_".into(),
4189 "ret" => "ret_".into(),
4192 "err" => "err_".into(),
4193 "stdin" => "stdin_".into(),
4195 "stdout" => "stdout_".into(),
4196 "stderr" => "stderr_".into(),
4197 s => s.to_snake_case(),
4198 }
4199}
4200
4201const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)";