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
1830pub enum CTypeNameInfo<'a> {
1831 Named { name: &'a str },
1832 Anonymous { is_prim: bool },
1833}
1834
1835pub fn gen_type_name(resolve: &Resolve, ty: TypeId) -> (CTypeNameInfo<'_>, String) {
1838 let mut encoded = String::new();
1839 push_ty_name(resolve, &Type::Id(ty), &mut encoded);
1840 let info = if let Some(name) = &resolve.types[ty].name {
1841 CTypeNameInfo::Named {
1842 name: name.as_ref(),
1843 }
1844 } else {
1845 CTypeNameInfo::Anonymous {
1846 is_prim: is_prim_type_id(resolve, ty),
1847 }
1848 };
1849
1850 (info, encoded)
1851}
1852
1853impl InterfaceGenerator<'_> {
1854 fn define_interface_types(&mut self, id: InterfaceId) {
1855 let mut live = LiveTypes::default();
1856 live.add_interface(self.resolve, id);
1857 self.define_live_types(live);
1858 }
1859
1860 fn define_function_types(&mut self, funcs: &[(&str, &Function)]) {
1861 let mut live = LiveTypes::default();
1862 for (_, func) in funcs {
1863 live.add_func(self.resolve, func);
1864 }
1865 self.define_live_types(live);
1866 }
1867
1868 fn define_live_types(&mut self, live: LiveTypes) {
1869 for ty in live.iter() {
1870 if self.r#gen.type_names.contains_key(&ty) {
1871 continue;
1872 }
1873
1874 let (info, encoded) = gen_type_name(&self.resolve, ty);
1875 match info {
1876 CTypeNameInfo::Named { name } => {
1877 let typedef_name = format!("{}_{encoded}_t", self.owner_namespace(ty));
1878 let prev = self.r#gen.type_names.insert(ty, typedef_name.clone());
1879 assert!(prev.is_none());
1880
1881 self.define_type(name, ty)
1882 }
1883
1884 CTypeNameInfo::Anonymous { is_prim } => {
1885 let (defined, name) = if is_prim {
1886 let namespace = self.r#gen.world.to_snake_case();
1887 let name = format!("{namespace}_{encoded}_t");
1888 let new_prim = self.r#gen.prim_names.insert(name.clone());
1889 (!new_prim, name)
1890 } else {
1891 let namespace = self.owner_namespace(ty);
1892 (false, format!("{namespace}_{encoded}_t"))
1893 };
1894
1895 let prev = self.r#gen.type_names.insert(ty, name);
1896 assert!(prev.is_none());
1897
1898 if defined {
1899 continue;
1900 }
1901
1902 let kind = &self.resolve.types[ty].kind;
1903 if let TypeDefKind::Handle(handle) = kind {
1904 let resource = match handle {
1905 Handle::Borrow(id) | Handle::Own(id) => id,
1906 };
1907 let origin = dealias(self.resolve, *resource);
1908 if origin == *resource {
1909 continue;
1910 }
1911 }
1912
1913 self.define_anonymous_type(ty)
1914 }
1915 }
1916
1917 self.define_dtor(ty);
1918 }
1919 }
1920
1921 fn define_dtor(&mut self, id: TypeId) {
1922 let h_helpers_start = self.src.h_helpers.len();
1923 let c_helpers_start = self.src.c_helpers.len();
1924
1925 let name = self.r#gen.type_names[&id].clone();
1926 let prefix = name.strip_suffix("_t").unwrap();
1927
1928 self.src
1929 .h_helpers(&format!("\nvoid {prefix}_free({name} *ptr);\n"));
1930 self.src
1931 .c_helpers(&format!("\nvoid {prefix}_free({name} *ptr) {{\n"));
1932 let c_helpers_body_start = self.src.c_helpers.len();
1933 match &self.resolve.types[id].kind {
1934 TypeDefKind::Type(t) => self.free(t, "ptr"),
1935
1936 TypeDefKind::Flags(_) => {}
1937 TypeDefKind::Enum(_) => {}
1938
1939 TypeDefKind::Record(r) => {
1940 for field in r.fields.iter() {
1941 self.free(&field.ty, &format!("&ptr->{}", to_c_ident(&field.name)));
1942 }
1943 }
1944
1945 TypeDefKind::Tuple(t) => {
1946 for (i, ty) in t.types.iter().enumerate() {
1947 self.free(ty, &format!("&ptr->f{i}"));
1948 }
1949 }
1950
1951 TypeDefKind::List(t) => {
1952 self.src.c_helpers("size_t list_len = ptr->len;\n");
1953 uwriteln!(self.src.c_helpers, "if (list_len > 0) {{");
1954 let mut t_name = String::new();
1955 self.r#gen.push_type_name(t, &mut t_name);
1956 self.src
1957 .c_helpers(&format!("{t_name} *list_ptr = ptr->ptr;\n"));
1958 self.src
1959 .c_helpers("for (size_t i = 0; i < list_len; i++) {\n");
1960 self.free(t, "&list_ptr[i]");
1961 self.src.c_helpers("}\n");
1962 uwriteln!(self.src.c_helpers, "free(list_ptr);");
1963 uwriteln!(self.src.c_helpers, "}}");
1964 }
1965
1966 TypeDefKind::Variant(v) => {
1967 self.src.c_helpers("switch ((int32_t) ptr->tag) {\n");
1968 for (i, case) in v.cases.iter().enumerate() {
1969 if let Some(ty) = &case.ty {
1970 uwriteln!(self.src.c_helpers, "case {}: {{", i);
1971 let expr = format!("&ptr->val.{}", to_c_ident(&case.name));
1972 self.free(ty, &expr);
1973 self.src.c_helpers("break;\n");
1974 self.src.c_helpers("}\n");
1975 }
1976 }
1977 self.src.c_helpers("}\n");
1978 }
1979
1980 TypeDefKind::Option(t) => {
1981 self.src.c_helpers("if (ptr->is_some) {\n");
1982 self.free(t, "&ptr->val");
1983 self.src.c_helpers("}\n");
1984 }
1985
1986 TypeDefKind::Result(r) => {
1987 self.src.c_helpers("if (!ptr->is_err) {\n");
1988 if let Some(ok) = &r.ok {
1989 self.free(ok, "&ptr->val.ok");
1990 }
1991 if let Some(err) = &r.err {
1992 self.src.c_helpers("} else {\n");
1993 self.free(err, "&ptr->val.err");
1994 }
1995 self.src.c_helpers("}\n");
1996 }
1997 TypeDefKind::Future(_) | TypeDefKind::Stream(_) => {
1998 self.free(&Type::Id(id), "*ptr");
1999 }
2000 TypeDefKind::Resource => {}
2001 TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
2002 self.free(&Type::Id(*id), "*ptr");
2003 }
2004 TypeDefKind::Unknown => unreachable!(),
2005 TypeDefKind::FixedSizeList(..) => todo!(),
2006 TypeDefKind::Map(..) => todo!(),
2007 }
2008 if c_helpers_body_start == self.src.c_helpers.len() {
2009 self.src.c_helpers.as_mut_string().truncate(c_helpers_start);
2010 self.src.h_helpers.as_mut_string().truncate(h_helpers_start);
2011 return;
2012 }
2013 self.src.c_helpers("}\n");
2014 self.r#gen.dtor_funcs.insert(id, format!("{prefix}_free"));
2015 }
2016
2017 fn free(&mut self, ty: &Type, expr: &str) {
2018 match ty {
2019 Type::Id(id) => {
2020 if let Some(dtor) = self.r#gen.dtor_funcs.get(&id) {
2021 self.src.c_helpers(&format!("{dtor}({expr});\n"));
2022 }
2023 }
2024 Type::String => {
2025 let snake = self.r#gen.world.to_snake_case();
2026 self.src
2027 .c_helpers(&format!("{snake}_string_free({expr});\n"));
2028 }
2029 Type::Bool
2030 | Type::U8
2031 | Type::S8
2032 | Type::U16
2033 | Type::S16
2034 | Type::U32
2035 | Type::S32
2036 | Type::U64
2037 | Type::S64
2038 | Type::F32
2039 | Type::F64
2040 | Type::Char => {}
2041 Type::ErrorContext => todo!("error context free"),
2042 }
2043 }
2044
2045 fn c_func_name(&self, interface_id: Option<&WorldKey>, func: &Function) -> String {
2046 c_func_name(
2047 self.in_import,
2048 self.resolve,
2049 &self.r#gen.world,
2050 interface_id,
2051 func,
2052 &self.r#gen.renamed_interfaces,
2053 )
2054 }
2055
2056 fn import(&mut self, interface_name: Option<&WorldKey>, func: &Function) {
2057 let async_ = self
2058 .r#gen
2059 .opts
2060 .async_
2061 .is_async(self.resolve, interface_name, func, true);
2062 if async_ {
2063 self.r#gen.needs_async = true;
2064 }
2065
2066 self.docs(&func.docs, SourceType::HFns);
2067 let (variant, import_prefix) = if async_ {
2068 (AbiVariant::GuestImportAsync, "[async-lower]")
2069 } else {
2070 (AbiVariant::GuestImport, "")
2071 };
2072 let sig = self.resolve.wasm_signature(variant, func);
2073
2074 self.src.c_fns("\n");
2075
2076 uwriteln!(
2080 self.src.c_fns,
2081 "__attribute__((__import_module__(\"{}\"), __import_name__(\"{import_prefix}{}\")))",
2082 match interface_name {
2083 Some(name) => self.resolve.name_world_key(name),
2084 None => "$root".to_string(),
2085 },
2086 func.name
2087 );
2088 let name = self.c_func_name(interface_name, func);
2089 let import_name = self.r#gen.names.tmp(&format!("__wasm_import_{name}",));
2090 self.src.c_fns("extern ");
2091 match sig.results.len() {
2092 0 => self.src.c_fns("void"),
2093 1 => self.src.c_fns(wasm_type(sig.results[0])),
2094 _ => unimplemented!("multi-value return not supported"),
2095 }
2096 self.src.c_fns(" ");
2097 self.src.c_fns(&import_name);
2098 self.src.c_fns("(");
2099 for (i, param) in sig.params.iter().enumerate() {
2100 if i > 0 {
2101 self.src.c_fns(", ");
2102 }
2103 self.src.c_fns(wasm_type(*param));
2104 }
2105 if sig.params.len() == 0 {
2106 self.src.c_fns("void");
2107 }
2108 self.src.c_fns(");\n");
2109
2110 self.src.h_fns("extern ");
2113 let c_sig = self.print_sig(interface_name, func, &sig, async_);
2114 self.src.c_adapters("\n");
2115 self.src.c_adapters(&c_sig.sig);
2116 self.src.c_adapters(" {\n");
2117
2118 if async_ {
2119 self.import_body_async(func, c_sig, &sig, &import_name);
2120 } else {
2121 self.import_body_sync(func, c_sig, &import_name);
2122 }
2123
2124 self.src.c_adapters("}\n");
2125
2126 self.generate_async_futures_and_streams("", func, interface_name);
2127 }
2128
2129 fn import_body_sync(&mut self, func: &Function, c_sig: CSig, import_name: &str) {
2130 let mut optional_adapters = String::from("");
2133 if !self.r#gen.opts.no_sig_flattening {
2134 for (i, (_, param)) in c_sig.params.iter().enumerate() {
2135 let ty = &func.params[i].1;
2136 if let Type::Id(id) = ty {
2137 if let TypeDefKind::Option(_) = &self.resolve.types[*id].kind {
2138 let ty = self.r#gen.type_name(ty);
2139 uwrite!(
2140 optional_adapters,
2141 "{ty} {param};
2142 {param}.is_some = maybe_{param} != NULL;"
2143 );
2144 uwriteln!(
2145 optional_adapters,
2146 "if (maybe_{param}) {{
2147 {param}.val = *maybe_{param};
2148 }}",
2149 );
2150 }
2151 }
2152 }
2153 }
2154
2155 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
2156 for (pointer, param) in f.sig.params.iter() {
2157 if *pointer {
2158 f.params.push(format!("*{param}"));
2159 } else {
2160 f.params.push(param.clone());
2161 }
2162 }
2163 for ptr in f.sig.retptrs.iter() {
2164 f.locals.insert(ptr).unwrap();
2165 }
2166 f.src.push_str(&optional_adapters);
2167 abi::call(
2168 f.r#gen.resolve,
2169 AbiVariant::GuestImport,
2170 LiftLower::LowerArgsLiftResults,
2171 func,
2172 &mut f,
2173 false,
2174 );
2175
2176 let FunctionBindgen {
2177 src,
2178 import_return_pointer_area_size,
2179 import_return_pointer_area_align,
2180 ..
2181 } = f;
2182
2183 if !import_return_pointer_area_size.is_empty() {
2184 self.src.c_adapters(&format!(
2185 "\
2186 __attribute__((__aligned__({})))
2187 uint8_t ret_area[{}];
2188 ",
2189 import_return_pointer_area_align.format(POINTER_SIZE_EXPRESSION),
2190 import_return_pointer_area_size.format(POINTER_SIZE_EXPRESSION),
2191 ));
2192 }
2193
2194 self.src.c_adapters(&String::from(src));
2195 }
2196
2197 fn import_body_async(
2198 &mut self,
2199 func: &Function,
2200 c_sig: CSig,
2201 wasm_sig: &WasmSignature,
2202 import_name: &str,
2203 ) {
2204 let mut params = Vec::new();
2205 if wasm_sig.indirect_params {
2206 params.push(format!("(uint8_t*) {}", c_sig.params[0].1));
2207 } else {
2208 let mut f = FunctionBindgen::new(self, c_sig.clone(), "INVALID");
2209 for (i, (_, ty)) in func.params.iter().enumerate() {
2210 let param = &c_sig.params[i].1;
2211 params.extend(abi::lower_flat(f.r#gen.resolve, &mut f, param.clone(), ty));
2212 }
2213 f.r#gen.src.c_adapters.push_str(&f.src);
2214 }
2215 if func.result.is_some() {
2216 params.push(format!("(uint8_t*) {}", c_sig.params.last().unwrap().1));
2217 }
2218 uwriteln!(
2219 self.src.c_adapters,
2220 "return {import_name}({});",
2221 params.join(", "),
2222 );
2223 }
2224
2225 fn export(&mut self, func: &Function, interface_name: Option<&WorldKey>) {
2226 let async_ = self
2227 .r#gen
2228 .opts
2229 .async_
2230 .is_async(self.resolve, interface_name, func, false);
2231
2232 let (variant, prefix) = if async_ {
2233 self.r#gen.needs_async = true;
2234 (AbiVariant::GuestExportAsync, "[async-lift]")
2235 } else {
2236 (AbiVariant::GuestExport, "")
2237 };
2238
2239 let sig = self.resolve.wasm_signature(variant, func);
2240
2241 self.src.c_fns("\n");
2242
2243 let core_module_name = interface_name.map(|s| self.resolve.name_world_key(s));
2244 let export_name = func.legacy_core_export_name(core_module_name.as_deref());
2245
2246 let h_sig = self.print_sig(interface_name, func, &sig, async_);
2249
2250 uwriteln!(
2253 self.src.c_adapters,
2254 "\n__attribute__((__export_name__(\"{prefix}{export_name}\")))"
2255 );
2256 let name = self.c_func_name(interface_name, func);
2257 let import_name = self.r#gen.names.tmp(&format!("__wasm_export_{name}"));
2258
2259 let mut f = FunctionBindgen::new(self, h_sig, &import_name);
2260 match sig.results.len() {
2261 0 => f.r#gen.src.c_adapters("void"),
2262 1 => f.r#gen.src.c_adapters(wasm_type(sig.results[0])),
2263 _ => unimplemented!("multi-value return not supported"),
2264 }
2265 f.r#gen.src.c_adapters(" ");
2266 f.r#gen.src.c_adapters(&import_name);
2267 f.r#gen.src.c_adapters("(");
2268 for (i, param) in sig.params.iter().enumerate() {
2269 if i > 0 {
2270 f.r#gen.src.c_adapters(", ");
2271 }
2272 let name = f.locals.tmp("arg");
2273 uwrite!(f.r#gen.src.c_adapters, "{} {}", wasm_type(*param), name);
2274 f.params.push(name);
2275 }
2276 if sig.params.len() == 0 {
2277 f.r#gen.src.c_adapters("void");
2278 }
2279 f.r#gen.src.c_adapters(") {\n");
2280
2281 abi::call(
2283 f.r#gen.resolve,
2284 variant,
2285 LiftLower::LiftArgsLowerResults,
2286 func,
2287 &mut f,
2288 async_,
2289 );
2290 let FunctionBindgen {
2291 src,
2292 deferred_task_return,
2293 ..
2294 } = f;
2295 self.src.c_adapters(&src);
2296 self.src.c_adapters("}\n");
2297
2298 if async_ {
2299 let snake = self.r#gen.world.to_snake_case();
2300 let return_ty = match &func.result {
2301 Some(ty) => format!("{} ret", self.r#gen.type_name(ty)),
2302 None => "void".to_string(),
2303 };
2304 let DeferredTaskReturn::Emitted {
2305 body: mut task_return_body,
2306 name: task_return_name,
2307 params: task_return_params,
2308 } = deferred_task_return
2309 else {
2310 unreachable!()
2311 };
2312 let task_return_param_tys = task_return_params
2313 .iter()
2314 .map(|(ty, _expr)| wasm_type(*ty))
2315 .collect::<Vec<_>>()
2316 .join(", ");
2317 let task_return_param_exprs = task_return_params
2318 .iter()
2319 .map(|(_ty, expr)| expr.as_str())
2320 .collect::<Vec<_>>()
2321 .join(", ");
2322 let task_return_body = task_return_body.as_mut_string();
2323 uwriteln!(
2324 self.src.h_fns,
2325 "{snake}_callback_code_t {name}_callback({snake}_event_t *event);",
2326 );
2327 uwriteln!(self.src.h_helpers, "void {name}_return({return_ty});");
2328 let import_module = match interface_name {
2329 Some(name) => self.resolve.name_world_key(name),
2330 None => "$root".to_string(),
2331 };
2332 uwriteln!(
2333 self.src.c_helpers,
2334 r#"
2335__attribute__((__export_name__("[callback]{prefix}{export_name}")))
2336uint32_t {import_name}_callback(uint32_t event_raw, uint32_t waitable, uint32_t code) {{
2337 {snake}_event_t event;
2338 event.event = ({snake}_event_code_t) event_raw;
2339 event.waitable = waitable;
2340 event.code = code;
2341 return {name}_callback(&event);
2342}}
2343
2344__attribute__((__import_module__("[export]{import_module}"), __import_name__("{task_return_name}")))
2345void {import_name}__task_return({task_return_param_tys});
2346
2347void {name}_return({return_ty}) {{
2348 {task_return_body}
2349 {import_name}__task_return({task_return_param_exprs});
2350}}
2351 "#
2352 );
2353 } else if abi::guest_export_needs_post_return(self.resolve, func) {
2354 uwriteln!(
2355 self.src.c_fns,
2356 "__attribute__((__weak__, __export_name__(\"cabi_post_{export_name}\")))"
2357 );
2358 uwrite!(self.src.c_fns, "void {import_name}_post_return(");
2359
2360 let mut params = Vec::new();
2361 let mut c_sig = CSig {
2362 name: String::from("INVALID"),
2363 sig: String::from("INVALID"),
2364 params: Vec::new(),
2365 ret: Return::default(),
2366 retptrs: Vec::new(),
2367 };
2368 for (i, result) in sig.results.iter().enumerate() {
2369 let name = format!("arg{i}");
2370 uwrite!(self.src.c_fns, "{} {name}", wasm_type(*result));
2371 c_sig.params.push((false, name.clone()));
2372 params.push(name);
2373 }
2374 self.src.c_fns.push_str(") {\n");
2375
2376 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
2377 f.params = params;
2378 abi::post_return(f.r#gen.resolve, func, &mut f);
2379 let FunctionBindgen { src, .. } = f;
2380 self.src.c_fns(&src);
2381 self.src.c_fns("}\n");
2382 }
2383
2384 self.generate_async_futures_and_streams("[export]", func, interface_name);
2385 }
2386
2387 fn print_sig(
2388 &mut self,
2389 interface_name: Option<&WorldKey>,
2390 func: &Function,
2391 sig: &WasmSignature,
2392 async_: bool,
2393 ) -> CSig {
2394 let name = self.c_func_name(interface_name, func);
2395 self.r#gen.names.insert(&name).expect("duplicate symbols");
2396
2397 let start = self.src.h_fns.len();
2398 let mut result_rets = false;
2399 let mut result_rets_has_ok_type = false;
2400
2401 let ret = if async_ && !self.in_import {
2402 Return {
2403 scalar: func.result.map(Scalar::Type),
2404 retptrs: Vec::new(),
2405 }
2406 } else {
2407 self.classify_ret(func)
2408 };
2409 if async_ {
2410 let snake = self.r#gen.world.to_snake_case();
2411 if self.in_import {
2412 uwrite!(self.src.h_fns, "{snake}_subtask_status_t");
2413 } else {
2414 uwrite!(self.src.h_fns, "{snake}_callback_code_t");
2415 }
2416 } else {
2417 match &ret.scalar {
2418 None | Some(Scalar::Void) => self.src.h_fns("void"),
2419 Some(Scalar::OptionBool(_id)) => self.src.h_fns("bool"),
2420 Some(Scalar::ResultBool(ok, _err)) => {
2421 result_rets = true;
2422 result_rets_has_ok_type = ok.is_some();
2423 self.src.h_fns("bool");
2424 }
2425 Some(Scalar::Type(ty)) => self.print_ty(SourceType::HFns, ty),
2426 }
2427 }
2428 self.src.h_fns(" ");
2429 self.src.h_fns(&name);
2430 self.src.h_fns("(");
2431 let params;
2432 let mut retptrs = Vec::new();
2433 if async_ && self.in_import {
2434 params = self.print_sig_async_import_params(&name, func, sig);
2435 } else if async_ && !self.in_import {
2436 params = self.print_sig_params(func);
2437 } else {
2438 params = self.print_sig_params(func);
2439 let single_ret = ret.retptrs.len() == 1;
2440 for (i, ty) in ret.retptrs.iter().enumerate() {
2441 if i > 0 || func.params.len() > 0 {
2442 self.src.h_fns(", ");
2443 }
2444 self.print_ty(SourceType::HFns, ty);
2445 self.src.h_fns(" *");
2446 let name: String = if result_rets {
2447 assert!(i <= 1);
2448 if i == 0 && result_rets_has_ok_type {
2449 "ret".into()
2450 } else {
2451 "err".into()
2452 }
2453 } else if single_ret {
2454 "ret".into()
2455 } else {
2456 format!("ret{i}")
2457 };
2458 self.src.h_fns(&name);
2459 retptrs.push(name);
2460 }
2461 if func.params.len() == 0 && ret.retptrs.len() == 0 {
2462 self.src.h_fns("void");
2463 }
2464 }
2465 self.src.h_fns(")");
2466
2467 let sig = self.src.h_fns[start..].to_string();
2468 self.src.h_fns(";\n");
2469
2470 CSig {
2471 sig,
2472 name,
2473 params,
2474 ret,
2475 retptrs,
2476 }
2477 }
2478
2479 fn print_sig_params(&mut self, func: &Function) -> Vec<(bool, String)> {
2480 let mut params = Vec::new();
2481 for (i, (name, ty)) in func.params.iter().enumerate() {
2482 if i > 0 {
2483 self.src.h_fns(", ");
2484 }
2485 let pointer = is_arg_by_pointer(self.resolve, ty);
2486 let optional_type = if let Type::Id(id) = ty {
2488 if let TypeDefKind::Option(option_ty) = &self.resolve.types[*id].kind {
2489 if !self.r#gen.opts.no_sig_flattening {
2490 Some(option_ty)
2491 } else {
2492 None
2493 }
2494 } else {
2495 None
2496 }
2497 } else {
2498 None
2499 };
2500 let (print_ty, print_name) = if !self.r#gen.opts.no_sig_flattening {
2501 if let Some(option_ty) = optional_type {
2502 (option_ty, format!("maybe_{}", to_c_ident(name)))
2503 } else {
2504 (ty, to_c_ident(name))
2505 }
2506 } else {
2507 (ty, to_c_ident(name))
2508 };
2509 self.print_ty(SourceType::HFns, print_ty);
2510 self.src.h_fns(" ");
2511 if pointer {
2512 self.src.h_fns("*");
2513 }
2514 self.src.h_fns(&print_name);
2515 params.push((optional_type.is_none() && pointer, to_c_ident(name)));
2516 }
2517 params
2518 }
2519
2520 fn print_sig_async_import_params(
2521 &mut self,
2522 c_func_name: &str,
2523 func: &Function,
2524 sig: &WasmSignature,
2525 ) -> Vec<(bool, String)> {
2526 let mut params = Vec::new();
2527 let mut printed = false;
2528 if sig.indirect_params {
2529 match &func.params[..] {
2530 [] => {}
2531 [(_name, ty)] => {
2532 printed = true;
2533 let name = "arg".to_string();
2534 self.print_ty(SourceType::HFns, ty);
2535 self.src.h_fns(" *");
2536 self.src.h_fns(&name);
2537 params.push((true, name));
2538 }
2539 multiple => {
2540 printed = true;
2541 let names = multiple
2542 .iter()
2543 .map(|(name, ty)| (to_c_ident(name), self.r#gen.type_name(ty)))
2544 .collect::<Vec<_>>();
2545 uwriteln!(self.src.h_defs, "typedef struct {c_func_name}_args {{");
2546 for (name, ty) in names {
2547 uwriteln!(self.src.h_defs, "{ty} {name};");
2548 }
2549 uwriteln!(self.src.h_defs, "}} {c_func_name}_args_t;");
2550 uwrite!(self.src.h_fns, "{c_func_name}_args_t *args");
2551 params.push((true, "args".to_string()));
2552 }
2553 }
2554 } else {
2555 for (name, ty) in func.params.iter() {
2556 let name = to_c_ident(name);
2557 if printed {
2558 self.src.h_fns(", ");
2559 } else {
2560 printed = true;
2561 }
2562 self.print_ty(SourceType::HFns, ty);
2563 self.src.h_fns(" ");
2564 self.src.h_fns(&name);
2565 params.push((false, name));
2566 }
2567 }
2568 if let Some(ty) = &func.result {
2569 if printed {
2570 self.src.h_fns(", ");
2571 } else {
2572 printed = true;
2573 }
2574 let name = "result".to_string();
2575 self.print_ty(SourceType::HFns, ty);
2576 self.src.h_fns(" *");
2577 self.src.h_fns(&name);
2578 params.push((true, name));
2579 }
2580 if !printed {
2581 self.src.h_fns("void");
2582 }
2583 params
2584 }
2585
2586 fn classify_ret(&mut self, func: &Function) -> Return {
2587 let mut ret = Return::default();
2588 match &func.result {
2589 None => ret.scalar = Some(Scalar::Void),
2590 Some(ty) => {
2591 ret.return_single(self.resolve, ty, ty, !self.r#gen.opts.no_sig_flattening);
2592 }
2593 }
2594 return ret;
2595 }
2596
2597 fn print_typedef_target(&mut self, id: TypeId) {
2598 let name = &self.r#gen.type_names[&id];
2599 self.src.h_defs(&name);
2600 self.src.h_defs(";\n");
2601 }
2602
2603 fn start_typedef_struct(&mut self, id: TypeId) {
2604 let name = &self.r#gen.type_names[&id];
2605 self.src.h_defs("typedef struct ");
2606 self.src.h_defs(&name);
2607 self.src.h_defs(" {\n");
2608 }
2609
2610 fn finish_typedef_struct(&mut self, id: TypeId) {
2611 self.src.h_defs("} ");
2612 self.print_typedef_target(id);
2613 }
2614
2615 fn owner_namespace(&self, id: TypeId) -> String {
2616 owner_namespace(
2617 self.interface,
2618 self.in_import,
2619 self.r#gen.world.clone(),
2620 self.resolve,
2621 id,
2622 &self.r#gen.renamed_interfaces,
2623 )
2624 }
2625
2626 fn print_ty(&mut self, stype: SourceType, ty: &Type) {
2627 self.r#gen
2628 .push_type_name(ty, self.src.src(stype).as_mut_string());
2629 }
2630
2631 fn docs(&mut self, docs: &Docs, stype: SourceType) {
2632 let docs = match &docs.contents {
2633 Some(docs) => docs,
2634 None => return,
2635 };
2636 let src = self.src.src(stype);
2637 for line in docs.trim().lines() {
2638 src.push_str("// ");
2639 src.push_str(line);
2640 src.push_str("\n");
2641 }
2642 }
2643
2644 fn autodrop_enabled(&self) -> bool {
2645 self.r#gen.opts.autodrop_borrows == Enabled::Yes
2646 }
2647
2648 fn contains_droppable_borrow(&self, ty: &Type) -> bool {
2649 if let Type::Id(id) = ty {
2650 match &self.resolve.types[*id].kind {
2651 TypeDefKind::Handle(h) => match h {
2652 Handle::Borrow(id) => {
2655 !self.in_import
2656 && matches!(
2657 self.r#gen.resources[&dealias(self.resolve, *id)].direction,
2658 Direction::Import
2659 )
2660 }
2661
2662 Handle::Own(_) => false,
2663 },
2664
2665 TypeDefKind::Resource | TypeDefKind::Flags(_) | TypeDefKind::Enum(_) => false,
2666
2667 TypeDefKind::Record(r) => r
2668 .fields
2669 .iter()
2670 .any(|f| self.contains_droppable_borrow(&f.ty)),
2671
2672 TypeDefKind::Tuple(t) => {
2673 t.types.iter().any(|ty| self.contains_droppable_borrow(ty))
2674 }
2675
2676 TypeDefKind::Variant(v) => v.cases.iter().any(|case| {
2677 case.ty
2678 .as_ref()
2679 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2680 }),
2681
2682 TypeDefKind::Option(ty) => self.contains_droppable_borrow(ty),
2683
2684 TypeDefKind::Result(r) => {
2685 r.ok.as_ref()
2686 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2687 || r.err
2688 .as_ref()
2689 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2690 }
2691
2692 TypeDefKind::List(ty) => self.contains_droppable_borrow(ty),
2693
2694 TypeDefKind::Future(_) | TypeDefKind::Stream(_) => false,
2695
2696 TypeDefKind::Type(ty) => self.contains_droppable_borrow(ty),
2697
2698 TypeDefKind::Unknown => false,
2699 TypeDefKind::FixedSizeList(..) => todo!(),
2700 TypeDefKind::Map(..) => todo!(),
2701 }
2702 } else {
2703 false
2704 }
2705 }
2706
2707 fn generate_async_futures_and_streams(
2708 &mut self,
2709 prefix: &str,
2710 func: &Function,
2711 interface: Option<&WorldKey>,
2712 ) {
2713 let module = format!(
2714 "{prefix}{}",
2715 interface
2716 .map(|name| self.resolve.name_world_key(name))
2717 .unwrap_or_else(|| "$root".into())
2718 );
2719 for (index, ty) in func
2720 .find_futures_and_streams(self.resolve)
2721 .into_iter()
2722 .enumerate()
2723 {
2724 let func_name = &func.name;
2725
2726 match &self.resolve.types[ty].kind {
2727 TypeDefKind::Future(payload_type) => {
2728 self.generate_async_future_or_stream(
2729 PayloadFor::Future,
2730 &module,
2731 index,
2732 func_name,
2733 ty,
2734 payload_type.as_ref(),
2735 );
2736 }
2737 TypeDefKind::Stream(payload_type) => {
2738 self.generate_async_future_or_stream(
2739 PayloadFor::Stream,
2740 &module,
2741 index,
2742 func_name,
2743 ty,
2744 payload_type.as_ref(),
2745 );
2746 }
2747 _ => unreachable!(),
2748 }
2749 }
2750 }
2751
2752 fn generate_async_future_or_stream(
2753 &mut self,
2754 payload_for: PayloadFor,
2755 module: &str,
2756 index: usize,
2757 func_name: &str,
2758 ty: TypeId,
2759 payload_type: Option<&Type>,
2760 ) {
2761 if !self.r#gen.futures.insert(ty) {
2762 return;
2763 }
2764 let ty = self.r#gen.type_name(&Type::Id(ty));
2765 let name = ty.strip_suffix("_t").unwrap();
2766 let snake = self.r#gen.world.to_snake_case();
2767 let kind = match payload_for {
2768 PayloadFor::Future => "future",
2769 PayloadFor::Stream => "stream",
2770 };
2771 let payload_len_arg = match payload_for {
2772 PayloadFor::Future => "",
2773 PayloadFor::Stream => ", size_t",
2774 };
2775 let (read_arg_ty, read_arg_expr, write_arg_ty, write_arg_expr) =
2776 match (payload_for, payload_type) {
2777 (PayloadFor::Future, None) => ("".to_string(), "NULL", "".to_string(), "NULL"),
2778 (PayloadFor::Future, Some(ty)) => {
2779 let ty = self.r#gen.type_name(ty);
2780 (
2781 format!(", {ty} *buf"),
2782 "(uint8_t*) buf",
2783 format!(", const {ty} *buf"),
2784 "(const uint8_t*) buf",
2785 )
2786 }
2787 (PayloadFor::Stream, None) => (
2788 ", size_t amt".to_string(),
2789 "NULL, amt",
2790 ", size_t amt".to_string(),
2791 "NULL, amt",
2792 ),
2793 (PayloadFor::Stream, Some(ty)) => {
2794 let ty = self.r#gen.type_name(ty);
2795 (
2796 format!(", {ty} *buf, size_t amt"),
2797 "(uint8_t*) buf, amt",
2798 format!(", const {ty} *buf, size_t amt"),
2799 "(const uint8_t*) buf, amt",
2800 )
2801 }
2802 };
2803
2804 let empty = "";
2807 uwriteln!(
2808 self.src.h_helpers,
2809 r#"
2810typedef uint32_t {name}_writer_t;
2811
2812{ty} {name}_new({name}_writer_t *writer);
2813{snake}_waitable_status_t {name}_read({ty} reader{read_arg_ty});
2814{snake}_waitable_status_t {name}_write({name}_writer_t writer{write_arg_ty});
2815{snake}_waitable_status_t {name}_cancel_read({ty} reader);
2816{snake}_waitable_status_t {name}_cancel_write({name}_writer_t writer);
2817void {name}_drop_readable({ty} reader);{empty}
2818void {name}_drop_writable({name}_writer_t writer);
2819 "#,
2820 );
2821 uwriteln!(
2822 self.src.c_helpers,
2823 r#"
2824__attribute__((__import_module__("{module}"), __import_name__("[{kind}-new-{index}]{func_name}")))
2825extern uint64_t {name}__new(void);
2826__attribute__((__import_module__("{module}"), __import_name__("[async-lower][{kind}-read-{index}]{func_name}")))
2827extern uint32_t {name}__read(uint32_t, uint8_t*{payload_len_arg});
2828__attribute__((__import_module__("{module}"), __import_name__("[async-lower][{kind}-write-{index}]{func_name}")))
2829extern uint32_t {name}__write(uint32_t, const uint8_t*{payload_len_arg});
2830__attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-read-{index}]{func_name}")))
2831extern uint32_t {name}__cancel_read(uint32_t);
2832__attribute__((__import_module__("{module}"), __import_name__("[{kind}-cancel-write-{index}]{func_name}")))
2833extern uint32_t {name}__cancel_write(uint32_t);
2834__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-readable-{index}]{func_name}")))
2835extern void {name}__drop_readable(uint32_t);
2836__attribute__((__import_module__("{module}"), __import_name__("[{kind}-drop-writable-{index}]{func_name}")))
2837extern void {name}__drop_writable(uint32_t);
2838
2839{ty} {name}_new({name}_writer_t *writer) {{
2840 uint64_t packed = {name}__new();
2841 *writer = (uint32_t) (packed >> 32);
2842 return (uint32_t) packed;
2843}}
2844
2845{snake}_waitable_status_t {name}_read({ty} reader{read_arg_ty}) {{
2846 return {name}__read(reader, {read_arg_expr});
2847}}
2848
2849{snake}_waitable_status_t {name}_write({name}_writer_t writer{write_arg_ty}) {{
2850 return {name}__write(writer, {write_arg_expr});
2851}}
2852
2853{snake}_waitable_status_t {name}_cancel_read({ty} reader){empty} {{
2854 return {name}__cancel_read(reader);
2855}}
2856
2857{snake}_waitable_status_t {name}_cancel_write({name}_writer_t writer) {{
2858 return {name}__cancel_write(writer);
2859}}
2860
2861void {name}_drop_readable({ty} reader){empty} {{
2862 {name}__drop_readable(reader);
2863}}
2864
2865void {name}_drop_writable({name}_writer_t writer) {{
2866 {name}__drop_writable(writer);
2867}}
2868 "#,
2869 );
2870 }
2871}
2872
2873enum PayloadFor {
2874 Future,
2875 Stream,
2876}
2877
2878struct DroppableBorrow {
2879 name: String,
2880 ty: TypeId,
2881}
2882
2883struct FunctionBindgen<'a, 'b> {
2884 r#gen: &'a mut InterfaceGenerator<'b>,
2885 locals: Ns,
2886 src: wit_bindgen_core::Source,
2887 sig: CSig,
2888 func_to_call: &'a str,
2889 block_storage: Vec<wit_bindgen_core::Source>,
2890 blocks: Vec<(String, Vec<String>)>,
2891 payloads: Vec<String>,
2892 params: Vec<String>,
2893 wasm_return: Option<String>,
2894 ret_store_cnt: usize,
2895 import_return_pointer_area_size: ArchitectureSize,
2896 import_return_pointer_area_align: Alignment,
2897
2898 deferred_task_return: DeferredTaskReturn,
2906
2907 borrows: Vec<DroppableBorrow>,
2910
2911 borrow_decls: wit_bindgen_core::Source,
2913}
2914
2915enum DeferredTaskReturn {
2918 None,
2922
2923 Generating {
2930 prev_src: wit_bindgen_core::Source,
2935 },
2936
2937 Emitted {
2945 name: String,
2948 params: Vec<(WasmType, String)>,
2954 body: wit_bindgen_core::Source,
2958 },
2959}
2960
2961impl<'a, 'b> FunctionBindgen<'a, 'b> {
2962 fn new(
2963 r#gen: &'a mut InterfaceGenerator<'b>,
2964 sig: CSig,
2965 func_to_call: &'a str,
2966 ) -> FunctionBindgen<'a, 'b> {
2967 let mut locals = Ns::default();
2968 for (_, name) in sig.params.iter() {
2969 locals.insert(name).unwrap();
2970 }
2971 FunctionBindgen {
2972 r#gen,
2973 sig,
2974 locals,
2975 src: Default::default(),
2976 func_to_call,
2977 block_storage: Vec::new(),
2978 blocks: Vec::new(),
2979 payloads: Vec::new(),
2980 params: Vec::new(),
2981 wasm_return: None,
2982 ret_store_cnt: 0,
2983 import_return_pointer_area_size: Default::default(),
2984 import_return_pointer_area_align: Default::default(),
2985 borrow_decls: Default::default(),
2986 borrows: Vec::new(),
2987 deferred_task_return: DeferredTaskReturn::None,
2988 }
2989 }
2990
2991 fn store_op(&mut self, op: &str, loc: &str) {
2992 self.src.push_str(loc);
2993 self.src.push_str(" = ");
2994 self.src.push_str(op);
2995 self.src.push_str(";\n");
2996 }
2997
2998 fn load(
2999 &mut self,
3000 ty: &str,
3001 offset: ArchitectureSize,
3002 operands: &[String],
3003 results: &mut Vec<String>,
3004 ) {
3005 results.push(format!(
3006 "*(({}*) ({} + {}))",
3007 ty,
3008 operands[0],
3009 offset.format(POINTER_SIZE_EXPRESSION)
3010 ));
3011 }
3012
3013 fn load_ext(
3014 &mut self,
3015 ty: &str,
3016 offset: ArchitectureSize,
3017 operands: &[String],
3018 results: &mut Vec<String>,
3019 ) {
3020 self.load(ty, offset, operands, results);
3021 let result = results.pop().unwrap();
3022 results.push(format!("(int32_t) {result}"));
3023 }
3024
3025 fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) {
3026 uwriteln!(
3027 self.src,
3028 "*(({}*)({} + {})) = {};",
3029 ty,
3030 operands[1],
3031 offset.format(POINTER_SIZE_EXPRESSION),
3032 operands[0]
3033 );
3034 }
3035
3036 fn store_in_retptr(&mut self, operand: &String) {
3037 self.store_op(
3038 operand,
3039 &format!("*{}", self.sig.retptrs[self.ret_store_cnt]),
3040 );
3041 self.ret_store_cnt = self.ret_store_cnt + 1;
3042 }
3043
3044 fn empty_return_value(&mut self) {
3045 self.ret_store_cnt = self.ret_store_cnt + 1;
3048 }
3049
3050 fn assert_no_droppable_borrows(&self, context: &str, ty: &Type) {
3051 if !self.r#gen.in_import
3052 && self.r#gen.autodrop_enabled()
3053 && self.r#gen.contains_droppable_borrow(ty)
3054 {
3055 panic!("Unable to autodrop borrows in `{context}` values, please disable autodrop")
3056 }
3057 }
3058}
3059
3060impl Bindgen for FunctionBindgen<'_, '_> {
3061 type Operand = String;
3062
3063 fn sizes(&self) -> &SizeAlign {
3064 &self.r#gen.r#gen.sizes
3065 }
3066
3067 fn push_block(&mut self) {
3068 let prev = mem::take(&mut self.src);
3069 self.block_storage.push(prev);
3070 }
3071
3072 fn finish_block(&mut self, operands: &mut Vec<String>) {
3073 let to_restore = self.block_storage.pop().unwrap();
3074 let src = mem::replace(&mut self.src, to_restore);
3075 self.blocks.push((src.into(), mem::take(operands)));
3076 }
3077
3078 fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
3079 let ptr = self.locals.tmp("ptr");
3080
3081 if self.r#gen.in_import {
3084 self.import_return_pointer_area_size = self.import_return_pointer_area_size.max(size);
3085 self.import_return_pointer_area_align =
3086 self.import_return_pointer_area_align.max(align);
3087 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &ret_area;", ptr);
3088 } else {
3089 self.r#gen.r#gen.return_pointer_area_size =
3090 self.r#gen.r#gen.return_pointer_area_size.max(size);
3091 self.r#gen.r#gen.return_pointer_area_align =
3092 self.r#gen.r#gen.return_pointer_area_align.max(align);
3093 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &RET_AREA;", ptr);
3095 }
3096
3097 ptr
3098 }
3099
3100 fn is_list_canonical(&self, resolve: &Resolve, ty: &Type) -> bool {
3101 resolve.all_bits_valid(ty)
3102 }
3103
3104 fn emit(
3105 &mut self,
3106 resolve: &Resolve,
3107 inst: &Instruction<'_>,
3108 operands: &mut Vec<String>,
3109 results: &mut Vec<String>,
3110 ) {
3111 match inst {
3112 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
3113 Instruction::I32Const { val } => results.push(val.to_string()),
3114 Instruction::ConstZero { tys } => {
3115 for _ in tys.iter() {
3116 results.push("0".to_string());
3117 }
3118 }
3119
3120 Instruction::U8FromI32 => results.push(format!("(uint8_t) ({})", operands[0])),
3122 Instruction::S8FromI32 => results.push(format!("(int8_t) ({})", operands[0])),
3123 Instruction::U16FromI32 => results.push(format!("(uint16_t) ({})", operands[0])),
3124 Instruction::S16FromI32 => results.push(format!("(int16_t) ({})", operands[0])),
3125 Instruction::U32FromI32 => results.push(format!("(uint32_t) ({})", operands[0])),
3126 Instruction::S32FromI32 | Instruction::S64FromI64 => results.push(operands[0].clone()),
3127 Instruction::U64FromI64 => results.push(format!("(uint64_t) ({})", operands[0])),
3128
3129 Instruction::I32FromU8
3130 | Instruction::I32FromS8
3131 | Instruction::I32FromU16
3132 | Instruction::I32FromS16
3133 | Instruction::I32FromU32 => {
3134 results.push(format!("(int32_t) ({})", operands[0]));
3135 }
3136 Instruction::I32FromS32 | Instruction::I64FromS64 => results.push(operands[0].clone()),
3137 Instruction::I64FromU64 => {
3138 results.push(format!("(int64_t) ({})", operands[0]));
3139 }
3140
3141 Instruction::CoreF32FromF32
3144 | Instruction::CoreF64FromF64
3145 | Instruction::F32FromCoreF32
3146 | Instruction::F64FromCoreF64 => {
3147 results.push(operands[0].clone());
3148 }
3149
3150 Instruction::CharFromI32 => {
3152 results.push(format!("(uint32_t) ({})", operands[0]));
3153 }
3154 Instruction::I32FromChar => {
3155 results.push(format!("(int32_t) ({})", operands[0]));
3156 }
3157
3158 Instruction::Bitcasts { casts } => {
3159 for (cast, op) in casts.iter().zip(operands) {
3160 let op = self.r#gen.r#gen.perform_cast(op, cast);
3161 results.push(op);
3162 }
3163 }
3164
3165 Instruction::BoolFromI32 | Instruction::I32FromBool => {
3166 results.push(operands[0].clone());
3167 }
3168
3169 Instruction::RecordLower { record, .. } => {
3170 let op = &operands[0];
3171 for f in record.fields.iter() {
3172 results.push(format!("({}).{}", op, to_c_ident(&f.name)));
3173 }
3174 }
3175 Instruction::RecordLift { ty, record, .. } => {
3176 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3177 let mut result = format!("({name}) {{\n");
3178 for (field, op) in record.fields.iter().zip(operands.iter()) {
3179 let field_ty = self.r#gen.r#gen.type_name(&field.ty);
3180 uwriteln!(result, "({}) {},", field_ty, op);
3181 }
3182 result.push_str("}");
3183 results.push(result);
3184 }
3185
3186 Instruction::TupleLower { tuple, .. } => {
3187 let op = &operands[0];
3188 for i in 0..tuple.types.len() {
3189 results.push(format!("({op}).f{i}"));
3190 }
3191 }
3192 Instruction::TupleLift { ty, tuple, .. } => {
3193 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3194 let mut result = format!("({name}) {{\n");
3195 for (ty, op) in tuple.types.iter().zip(operands.iter()) {
3196 let ty = self.r#gen.r#gen.type_name(&ty);
3197 uwriteln!(result, "({}) {},", ty, op);
3198 }
3199 result.push_str("}");
3200 results.push(result);
3201 }
3202
3203 Instruction::HandleLower { .. } => {
3204 let op = &operands[0];
3205 results.push(format!("({op}).__handle"))
3206 }
3207
3208 Instruction::HandleLift { handle, ty, .. } => match handle {
3209 Handle::Borrow(resource)
3210 if matches!(
3211 self.r#gen.r#gen.resources[&dealias(resolve, *resource)].direction,
3212 Direction::Export
3213 ) =>
3214 {
3215 let op = &operands[0];
3218 let name = self
3219 .r#gen
3220 .r#gen
3221 .type_name(&Type::Id(dealias(resolve, *resource)));
3222 results.push(format!("(({name}*) {op})"))
3223 }
3224 _ => {
3225 let op = &operands[0];
3226 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3227 results.push(format!("({name}) {{ {op} }}"));
3228
3229 if let Handle::Borrow(id) = handle {
3230 if !self.r#gen.in_import && self.r#gen.autodrop_enabled() {
3231 let ty = dealias(self.r#gen.resolve, *id);
3234
3235 let name = self.locals.tmp("borrow");
3236 uwriteln!(self.borrow_decls, "int32_t {name} = 0;");
3237 uwriteln!(self.src, "{name} = {op};");
3238
3239 self.borrows.push(DroppableBorrow { name, ty });
3240 }
3241 }
3242 }
3243 },
3244
3245 Instruction::FlagsLower { flags, ty, .. } => match flags_repr(flags) {
3247 Int::U8 | Int::U16 | Int::U32 => {
3248 results.push(operands.pop().unwrap());
3249 }
3250 Int::U64 => {
3251 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3252 let tmp = self.locals.tmp("flags");
3253 uwriteln!(self.src, "{name} {tmp} = {};", operands[0]);
3254 results.push(format!("{tmp} & 0xffffffff"));
3255 results.push(format!("({tmp} >> 32) & 0xffffffff"));
3256 }
3257 },
3258
3259 Instruction::FlagsLift { flags, ty, .. } => match flags_repr(flags) {
3260 Int::U8 | Int::U16 | Int::U32 => {
3261 results.push(operands.pop().unwrap());
3262 }
3263 Int::U64 => {
3264 let name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3265 let op0 = &operands[0];
3266 let op1 = &operands[1];
3267 results.push(format!("(({name}) ({op0})) | ((({name}) ({op1})) << 32)"));
3268 }
3269 },
3270
3271 Instruction::VariantPayloadName => {
3272 let name = self.locals.tmp("payload");
3273 results.push(format!("*{name}"));
3274 self.payloads.push(name);
3275 }
3276
3277 Instruction::VariantLower {
3278 variant,
3279 results: result_types,
3280 ..
3281 } => {
3282 let blocks = self
3283 .blocks
3284 .drain(self.blocks.len() - variant.cases.len()..)
3285 .collect::<Vec<_>>();
3286 let payloads = self
3287 .payloads
3288 .drain(self.payloads.len() - variant.cases.len()..)
3289 .collect::<Vec<_>>();
3290
3291 let mut variant_results = Vec::with_capacity(result_types.len());
3292 for ty in result_types.iter() {
3293 let name = self.locals.tmp("variant");
3294 results.push(name.clone());
3295 self.src.push_str(wasm_type(*ty));
3296 self.src.push_str(" ");
3297 self.src.push_str(&name);
3298 self.src.push_str(";\n");
3299 variant_results.push(name);
3300 }
3301
3302 let expr_to_match = format!("({}).tag", operands[0]);
3303
3304 uwriteln!(self.src, "switch ((int32_t) {}) {{", expr_to_match);
3305 for (i, ((case, (block, block_results)), payload)) in
3306 variant.cases.iter().zip(blocks).zip(payloads).enumerate()
3307 {
3308 uwriteln!(self.src, "case {}: {{", i);
3309 if let Some(ty) = case.ty.as_ref() {
3310 let ty = self.r#gen.r#gen.type_name(ty);
3311 uwrite!(
3312 self.src,
3313 "const {} *{} = &({}).val",
3314 ty,
3315 payload,
3316 operands[0],
3317 );
3318 self.src.push_str(".");
3319 self.src.push_str(&to_c_ident(&case.name));
3320 self.src.push_str(";\n");
3321 }
3322 self.src.push_str(&block);
3323
3324 for (name, result) in variant_results.iter().zip(&block_results) {
3325 uwriteln!(self.src, "{} = {};", name, result);
3326 }
3327 self.src.push_str("break;\n}\n");
3328 }
3329 self.src.push_str("}\n");
3330 }
3331
3332 Instruction::VariantLift { variant, ty, .. } => {
3333 let blocks = self
3334 .blocks
3335 .drain(self.blocks.len() - variant.cases.len()..)
3336 .collect::<Vec<_>>();
3337
3338 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3339 let result = self.locals.tmp("variant");
3340 uwriteln!(self.src, "{} {};", ty, result);
3341 uwriteln!(self.src, "{}.tag = {};", result, operands[0]);
3342 uwriteln!(self.src, "switch ((int32_t) {}.tag) {{", result);
3343 for (i, (case, (block, block_results))) in
3344 variant.cases.iter().zip(blocks).enumerate()
3345 {
3346 uwriteln!(self.src, "case {}: {{", i);
3347 self.src.push_str(&block);
3348 assert!(block_results.len() == (case.ty.is_some() as usize));
3349
3350 if let Some(_) = case.ty.as_ref() {
3351 let mut dst = format!("{result}.val");
3352 dst.push_str(".");
3353 dst.push_str(&to_c_ident(&case.name));
3354 self.store_op(&block_results[0], &dst);
3355 }
3356 self.src.push_str("break;\n}\n");
3357 }
3358 self.src.push_str("}\n");
3359 results.push(result);
3360 }
3361
3362 Instruction::OptionLower {
3363 results: result_types,
3364 payload,
3365 ..
3366 } => {
3367 let (mut some, some_results) = self.blocks.pop().unwrap();
3368 let (mut none, none_results) = self.blocks.pop().unwrap();
3369 let some_payload = self.payloads.pop().unwrap();
3370 let _none_payload = self.payloads.pop().unwrap();
3371
3372 for (i, ty) in result_types.iter().enumerate() {
3373 let name = self.locals.tmp("option");
3374 results.push(name.clone());
3375 self.src.push_str(wasm_type(*ty));
3376 self.src.push_str(" ");
3377 self.src.push_str(&name);
3378 self.src.push_str(";\n");
3379 let some_result = &some_results[i];
3380 uwriteln!(some, "{name} = {some_result};");
3381 let none_result = &none_results[i];
3382 uwriteln!(none, "{name} = {none_result};");
3383 }
3384
3385 let op0 = &operands[0];
3386 let ty = self.r#gen.r#gen.type_name(payload);
3387 let bind_some = format!("const {ty} *{some_payload} = &({op0}).val;");
3388
3389 uwrite!(
3390 self.src,
3391 "\
3392 if (({op0}).is_some) {{
3393 {bind_some}
3394 {some}}} else {{
3395 {none}}}
3396 "
3397 );
3398 }
3399
3400 Instruction::OptionLift { ty, .. } => {
3401 let (mut some, some_results) = self.blocks.pop().unwrap();
3402 let (mut none, none_results) = self.blocks.pop().unwrap();
3403 assert!(none_results.len() == 0);
3404 assert!(some_results.len() == 1);
3405 let some_result = &some_results[0];
3406
3407 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3408 let result = self.locals.tmp("option");
3409 uwriteln!(self.src, "{ty} {result};");
3410 let op0 = &operands[0];
3411 let set_some = format!("{result}.val = {some_result};\n");
3412 if none.len() > 0 {
3413 none.push('\n');
3414 }
3415 if some.len() > 0 {
3416 some.push('\n');
3417 }
3418 uwrite!(
3419 self.src,
3420 "switch ({op0}) {{
3421 case 0: {{
3422 {result}.is_some = false;
3423 {none}\
3424 break;
3425 }}
3426 case 1: {{
3427 {result}.is_some = true;
3428 {some}\
3429 {set_some}\
3430 break;
3431 }}
3432 }}\n"
3433 );
3434 results.push(result);
3435 }
3436
3437 Instruction::ResultLower {
3438 results: result_types,
3439 result,
3440 ..
3441 } => {
3442 let (mut err, err_results) = self.blocks.pop().unwrap();
3443 let (mut ok, ok_results) = self.blocks.pop().unwrap();
3444 let err_payload = self.payloads.pop().unwrap();
3445 let ok_payload = self.payloads.pop().unwrap();
3446
3447 for (i, ty) in result_types.iter().enumerate() {
3448 let name = self.locals.tmp("result");
3449 results.push(name.clone());
3450 self.src.push_str(wasm_type(*ty));
3451 self.src.push_str(" ");
3452 self.src.push_str(&name);
3453 self.src.push_str(";\n");
3454 let ok_result = &ok_results[i];
3455 uwriteln!(ok, "{name} = {ok_result};");
3456 let err_result = &err_results[i];
3457 uwriteln!(err, "{name} = {err_result};");
3458 }
3459
3460 let op0 = &operands[0];
3461 let bind_ok = if let Some(ok) = result.ok.as_ref() {
3462 let ok_ty = self.r#gen.r#gen.type_name(ok);
3463 format!("const {ok_ty} *{ok_payload} = &({op0}).val.ok;")
3464 } else {
3465 String::new()
3466 };
3467 let bind_err = if let Some(err) = result.err.as_ref() {
3468 let err_ty = self.r#gen.r#gen.type_name(err);
3469 format!("const {err_ty} *{err_payload} = &({op0}).val.err;")
3470 } else {
3471 String::new()
3472 };
3473 uwrite!(
3474 self.src,
3475 "\
3476 if (({op0}).is_err) {{
3477 {bind_err}\
3478 {err}\
3479 }} else {{
3480 {bind_ok}\
3481 {ok}\
3482 }}
3483 "
3484 );
3485 }
3486
3487 Instruction::ResultLift { result, ty, .. } => {
3488 let (mut err, err_results) = self.blocks.pop().unwrap();
3489 assert!(err_results.len() == (result.err.is_some() as usize));
3490 let (mut ok, ok_results) = self.blocks.pop().unwrap();
3491 assert!(ok_results.len() == (result.ok.is_some() as usize));
3492
3493 if err.len() > 0 {
3494 err.push_str("\n");
3495 }
3496 if ok.len() > 0 {
3497 ok.push_str("\n");
3498 }
3499
3500 let result_tmp = self.locals.tmp("result");
3501 let set_ok = if let Some(_) = result.ok.as_ref() {
3502 let ok_result = &ok_results[0];
3503 format!("{result_tmp}.val.ok = {ok_result};\n")
3504 } else {
3505 String::new()
3506 };
3507 let set_err = if let Some(_) = result.err.as_ref() {
3508 let err_result = &err_results[0];
3509 format!("{result_tmp}.val.err = {err_result};\n")
3510 } else {
3511 String::new()
3512 };
3513
3514 let ty = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3515 uwriteln!(self.src, "{ty} {result_tmp};");
3516 let op0 = &operands[0];
3517 uwriteln!(
3518 self.src,
3519 "switch ({op0}) {{
3520 case 0: {{
3521 {result_tmp}.is_err = false;
3522 {ok}\
3523 {set_ok}\
3524 break;
3525 }}
3526 case 1: {{
3527 {result_tmp}.is_err = true;
3528 {err}\
3529 {set_err}\
3530 break;
3531 }}
3532 }}"
3533 );
3534 results.push(result_tmp);
3535 }
3536
3537 Instruction::EnumLower { .. } => results.push(format!("(int32_t) {}", operands[0])),
3538 Instruction::EnumLift { .. } => results.push(operands.pop().unwrap()),
3539
3540 Instruction::ListCanonLower { .. } | Instruction::StringLower { .. } => {
3541 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
3542 results.push(format!("({}).len", operands[0]));
3543 }
3544 Instruction::ListCanonLift { element, ty, .. } => {
3545 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
3546
3547 let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3548 let elem_name = self.r#gen.r#gen.type_name(element);
3549 results.push(format!(
3550 "({}) {{ ({}*)({}), ({}) }}",
3551 list_name, elem_name, operands[0], operands[1]
3552 ));
3553 }
3554 Instruction::StringLift { .. } => {
3555 let list_name = self.r#gen.r#gen.type_name(&Type::String);
3556 results.push(format!(
3557 "({}) {{ ({}*)({}), ({}) }}",
3558 list_name,
3559 self.r#gen.r#gen.char_type(),
3560 operands[0],
3561 operands[1]
3562 ));
3563 }
3564
3565 Instruction::ListLower { .. } => {
3566 let _body = self.blocks.pop().unwrap();
3567 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
3568 results.push(format!("({}).len", operands[0]));
3569 }
3570
3571 Instruction::ListLift { element, ty, .. } => {
3572 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
3573
3574 let _body = self.blocks.pop().unwrap();
3575 let list_name = self.r#gen.r#gen.type_name(&Type::Id(*ty));
3576 let elem_name = self.r#gen.r#gen.type_name(element);
3577 results.push(format!(
3578 "({}) {{ ({}*)({}), ({}) }}",
3579 list_name, elem_name, operands[0], operands[1]
3580 ));
3581 }
3582 Instruction::IterElem { .. } => results.push("e".to_string()),
3583 Instruction::IterBasePointer => results.push("base".to_string()),
3584
3585 Instruction::CallWasm { sig, .. } => {
3586 match sig.results.len() {
3587 0 => {}
3588 1 => {
3589 self.src.push_str(wasm_type(sig.results[0]));
3590 let ret = self.locals.tmp("ret");
3591 self.wasm_return = Some(ret.clone());
3592 uwrite!(self.src, " {} = ", ret);
3593 results.push(ret);
3594 }
3595 _ => unimplemented!(),
3596 }
3597 self.src.push_str(self.func_to_call);
3598 self.src.push_str("(");
3599 for (i, op) in operands.iter().enumerate() {
3600 if i > 0 {
3601 self.src.push_str(", ");
3602 }
3603 self.src.push_str(op);
3604 }
3605 self.src.push_str(");\n");
3606 }
3607
3608 Instruction::CallInterface { func, async_ } => {
3609 let mut args = String::new();
3610 for (i, (op, (byref, _))) in operands.iter().zip(&self.sig.params).enumerate() {
3611 if i > 0 {
3612 args.push_str(", ");
3613 }
3614 let ty = &func.params[i].1;
3615 if *byref {
3616 let name = self.locals.tmp("arg");
3617 let ty = self.r#gen.r#gen.type_name(ty);
3618 uwriteln!(self.src, "{} {} = {};", ty, name, op);
3619 args.push_str("&");
3620 args.push_str(&name);
3621 } else {
3622 if !self.r#gen.in_import {
3623 if let Type::Id(id) = ty {
3624 if let TypeDefKind::Option(_) = &self.r#gen.resolve.types[*id].kind
3625 {
3626 uwrite!(args, "{op}.is_some ? &({op}.val) : NULL");
3627 continue;
3628 }
3629 }
3630 }
3631 args.push_str(op);
3632 }
3633 }
3634 if *async_ {
3635 let ret = self.locals.tmp("ret");
3636 let snake = self.r#gen.r#gen.world.to_snake_case();
3637 uwriteln!(
3638 self.src,
3639 "{snake}_callback_code_t {ret} = {}({args});",
3640 self.sig.name,
3641 );
3642 uwriteln!(self.src, "return {ret};");
3643 if func.result.is_some() {
3644 results.push("ret".to_string());
3645 }
3646 assert!(matches!(
3647 self.deferred_task_return,
3648 DeferredTaskReturn::None
3649 ));
3650 self.deferred_task_return = DeferredTaskReturn::Generating {
3651 prev_src: mem::take(&mut self.src),
3652 };
3653 return;
3654 }
3655 match &self.sig.ret.scalar {
3656 None => {
3657 let mut retptrs = Vec::new();
3658 for ty in self.sig.ret.retptrs.iter() {
3659 let name = self.locals.tmp("ret");
3660 let ty = self.r#gen.r#gen.type_name(ty);
3661 uwriteln!(self.src, "{} {};", ty, name);
3662 if args.len() > 0 {
3663 args.push_str(", ");
3664 }
3665 args.push_str("&");
3666 args.push_str(&name);
3667 retptrs.push(name);
3668 }
3669 uwriteln!(self.src, "{}({});", self.sig.name, args);
3670 results.extend(retptrs);
3671 }
3672 Some(Scalar::Void) => {
3673 uwriteln!(self.src, "{}({});", self.sig.name, args);
3674 }
3675 Some(Scalar::Type(_)) => {
3676 let ret = self.locals.tmp("ret");
3677 let ty = func.result.unwrap();
3678 let ty = self.r#gen.r#gen.type_name(&ty);
3679 uwriteln!(self.src, "{} {} = {}({});", ty, ret, self.sig.name, args);
3680 results.push(ret);
3681 }
3682 Some(Scalar::OptionBool(ty)) => {
3683 let ret = self.locals.tmp("ret");
3684 let val = self.locals.tmp("val");
3685 if args.len() > 0 {
3686 args.push_str(", ");
3687 }
3688 args.push_str("&");
3689 args.push_str(&val);
3690 let payload_ty = self.r#gen.r#gen.type_name(ty);
3691 uwriteln!(self.src, "{} {};", payload_ty, val);
3692 uwriteln!(self.src, "bool {} = {}({});", ret, self.sig.name, args);
3693 let ty = func.result.unwrap();
3694 let option_ty = self.r#gen.r#gen.type_name(&ty);
3695 let option_ret = self.locals.tmp("ret");
3696 uwrite!(
3697 self.src,
3698 "
3699 {option_ty} {option_ret};
3700 {option_ret}.is_some = {ret};
3701 {option_ret}.val = {val};
3702 ",
3703 );
3704 results.push(option_ret);
3705 }
3706 Some(Scalar::ResultBool(ok, err)) => {
3707 let ty = &func.result.unwrap();
3708 let result_ty = self.r#gen.r#gen.type_name(ty);
3709 let ret = self.locals.tmp("ret");
3710 let mut ret_iter = self.sig.ret.retptrs.iter();
3711 uwriteln!(self.src, "{result_ty} {ret};");
3712 let ok_name = if ok.is_some() {
3713 if let Some(ty) = ret_iter.next() {
3714 let val = self.locals.tmp("ok");
3715 if args.len() > 0 {
3716 uwrite!(args, ", ");
3717 }
3718 uwrite!(args, "&{val}");
3719 let ty = self.r#gen.r#gen.type_name(ty);
3720 uwriteln!(self.src, "{} {};", ty, val);
3721 Some(val)
3722 } else {
3723 None
3724 }
3725 } else {
3726 None
3727 };
3728 let err_name = if let Some(ty) = ret_iter.next() {
3729 let val = self.locals.tmp("err");
3730 if args.len() > 0 {
3731 uwrite!(args, ", ")
3732 }
3733 uwrite!(args, "&{val}");
3734 let ty = self.r#gen.r#gen.type_name(ty);
3735 uwriteln!(self.src, "{} {};", ty, val);
3736 Some(val)
3737 } else {
3738 None
3739 };
3740 assert!(ret_iter.next().is_none());
3741 uwrite!(self.src, "");
3742 uwriteln!(self.src, "{ret}.is_err = !{}({args});", self.sig.name);
3743 if err.is_some() {
3744 if let Some(err_name) = err_name {
3745 uwriteln!(
3746 self.src,
3747 "if ({ret}.is_err) {{
3748 {ret}.val.err = {err_name};
3749 }}",
3750 );
3751 }
3752 }
3753 if ok.is_some() {
3754 if let Some(ok_name) = ok_name {
3755 uwriteln!(
3756 self.src,
3757 "if (!{ret}.is_err) {{
3758 {ret}.val.ok = {ok_name};
3759 }}"
3760 );
3761 } else {
3762 uwrite!(self.src, "\n");
3763 }
3764 }
3765 results.push(ret);
3766 }
3767 }
3768 }
3769 Instruction::Return { .. } if self.r#gen.in_import => match self.sig.ret.scalar {
3770 None => {
3771 for op in operands.iter() {
3772 self.store_in_retptr(op);
3773 }
3774 }
3775 Some(Scalar::Void) => {
3776 assert!(operands.is_empty());
3777 }
3778 Some(Scalar::Type(_)) => {
3779 assert_eq!(operands.len(), 1);
3780 self.src.push_str("return ");
3781 self.src.push_str(&operands[0]);
3782 self.src.push_str(";\n");
3783 }
3784 Some(Scalar::OptionBool(_)) => {
3785 assert_eq!(operands.len(), 1);
3786 let variant = &operands[0];
3787 self.store_in_retptr(&format!("{variant}.val"));
3788 self.src.push_str("return ");
3789 self.src.push_str(&variant);
3790 self.src.push_str(".is_some;\n");
3791 }
3792 Some(Scalar::ResultBool(ok, err)) => {
3793 assert_eq!(operands.len(), 1);
3794 let variant = &operands[0];
3795 assert!(self.sig.retptrs.len() <= 2);
3796 uwriteln!(self.src, "if (!{}.is_err) {{", variant);
3797 if ok.is_some() {
3798 if ok.is_some() {
3799 self.store_in_retptr(&format!("{variant}.val.ok"));
3800 } else {
3801 self.empty_return_value();
3802 }
3803 }
3804 uwriteln!(
3805 self.src,
3806 " return 1;
3807 }} else {{"
3808 );
3809 if err.is_some() {
3810 if err.is_some() {
3811 self.store_in_retptr(&format!("{variant}.val.err"));
3812 } else {
3813 self.empty_return_value();
3814 }
3815 }
3816 uwriteln!(
3817 self.src,
3818 " return 0;
3819 }}"
3820 );
3821 assert_eq!(self.ret_store_cnt, self.sig.retptrs.len());
3822 }
3823 },
3824 Instruction::Return { amt, .. } => {
3825 let src = std::mem::replace(&mut self.src, std::mem::take(&mut self.borrow_decls));
3827 self.src.append_src(&src);
3828
3829 for DroppableBorrow { name, ty } in self.borrows.iter() {
3830 let drop_fn = self.r#gen.r#gen.resources[ty].drop_fn.as_str();
3831 uwriteln!(self.src, "if ({name} != 0) {{");
3832 uwriteln!(self.src, " {drop_fn}({name});");
3833 uwriteln!(self.src, "}}");
3834 }
3835
3836 assert!(*amt <= 1);
3837 if *amt == 1 {
3838 uwriteln!(self.src, "return {};", operands[0]);
3839 }
3840 }
3841
3842 Instruction::I32Load { offset } => self.load("int32_t", *offset, operands, results),
3843 Instruction::I64Load { offset } => self.load("int64_t", *offset, operands, results),
3844 Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
3845 Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
3846 Instruction::PointerLoad { offset } => {
3847 self.load("uint8_t *", *offset, operands, results)
3848 }
3849 Instruction::LengthLoad { offset } => self.load("size_t", *offset, operands, results),
3850 Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
3851 Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
3852 Instruction::F32Store { offset } => self.store("float", *offset, operands),
3853 Instruction::F64Store { offset } => self.store("double", *offset, operands),
3854 Instruction::I32Store8 { offset } => self.store("int8_t", *offset, operands),
3855 Instruction::I32Store16 { offset } => self.store("int16_t", *offset, operands),
3856 Instruction::PointerStore { offset } => self.store("uint8_t *", *offset, operands),
3857 Instruction::LengthStore { offset } => self.store("size_t", *offset, operands),
3858
3859 Instruction::I32Load8U { offset } => {
3860 self.load_ext("uint8_t", *offset, operands, results)
3861 }
3862 Instruction::I32Load8S { offset } => {
3863 self.load_ext("int8_t", *offset, operands, results)
3864 }
3865 Instruction::I32Load16U { offset } => {
3866 self.load_ext("uint16_t", *offset, operands, results)
3867 }
3868 Instruction::I32Load16S { offset } => {
3869 self.load_ext("int16_t", *offset, operands, results)
3870 }
3871
3872 Instruction::GuestDeallocate { .. } => {
3873 uwriteln!(self.src, "free({});", operands[0]);
3874 }
3875 Instruction::GuestDeallocateString => {
3876 uwriteln!(self.src, "if (({}) > 0) {{", operands[1]);
3877 uwriteln!(self.src, "free({});", operands[0]);
3878 uwriteln!(self.src, "}}");
3879 }
3880 Instruction::GuestDeallocateVariant { blocks } => {
3881 let blocks = self
3882 .blocks
3883 .drain(self.blocks.len() - blocks..)
3884 .collect::<Vec<_>>();
3885
3886 uwriteln!(self.src, "switch ((int32_t) {}) {{", operands[0]);
3887 for (i, (block, results)) in blocks.into_iter().enumerate() {
3888 assert!(results.is_empty());
3889 uwriteln!(self.src, "case {}: {{", i);
3890 self.src.push_str(&block);
3891 self.src.push_str("break;\n}\n");
3892 }
3893 self.src.push_str("}\n");
3894 }
3895 Instruction::GuestDeallocateList { element } => {
3896 let (body, results) = self.blocks.pop().unwrap();
3897 assert!(results.is_empty());
3898 let len = self.locals.tmp("len");
3899 uwriteln!(self.src, "size_t {len} = {};", operands[1]);
3900 uwriteln!(self.src, "if ({len} > 0) {{");
3901 let ptr = self.locals.tmp("ptr");
3902 uwriteln!(self.src, "uint8_t *{ptr} = {};", operands[0]);
3903 let i = self.locals.tmp("i");
3904 uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{");
3905 let size = self.r#gen.r#gen.sizes.size(element);
3906 uwriteln!(
3907 self.src,
3908 "uint8_t *base = {ptr} + {i} * {};",
3909 size.format(POINTER_SIZE_EXPRESSION)
3910 );
3911 uwriteln!(self.src, "(void) base;");
3912 uwrite!(self.src, "{body}");
3913 uwriteln!(self.src, "}}");
3914 uwriteln!(self.src, "free({ptr});");
3915 uwriteln!(self.src, "}}");
3916 }
3917
3918 Instruction::Flush { amt } => {
3919 results.extend(operands.iter().take(*amt).cloned());
3920 }
3921
3922 Instruction::AsyncTaskReturn { name, params } => {
3923 let body = match &mut self.deferred_task_return {
3924 DeferredTaskReturn::Generating { prev_src } => {
3925 mem::swap(&mut self.src, prev_src);
3926 mem::take(prev_src)
3927 }
3928 _ => unreachable!(),
3929 };
3930 assert_eq!(params.len(), operands.len());
3931 self.deferred_task_return = DeferredTaskReturn::Emitted {
3932 name: name.to_string(),
3933 body,
3934 params: params
3935 .iter()
3936 .zip(operands)
3937 .map(|(a, b)| (*a, b.clone()))
3938 .collect(),
3939 };
3940 }
3941
3942 Instruction::FutureLift { .. } => {
3943 results.push(format!("((uint32_t) {})", operands[0]));
3944 }
3945 Instruction::FutureLower { .. } => {
3946 results.push(format!("((int32_t) {})", operands[0]));
3947 }
3948 Instruction::StreamLift { .. } => {
3949 results.push(format!("((uint32_t) {})", operands[0]));
3950 }
3951 Instruction::StreamLower { .. } => {
3952 results.push(format!("((int32_t) {})", operands[0]));
3953 }
3954
3955 i => unimplemented!("{:?}", i),
3956 }
3957 }
3958}
3959
3960#[derive(Default, Clone, Copy)]
3961enum SourceType {
3962 #[default]
3963 HDefs,
3964 HFns,
3965 }
3971
3972#[derive(Default)]
3973struct Source {
3974 h_defs: wit_bindgen_core::Source,
3975 h_fns: wit_bindgen_core::Source,
3976 h_helpers: wit_bindgen_core::Source,
3977 h_async: wit_bindgen_core::Source,
3978 c_defs: wit_bindgen_core::Source,
3979 c_fns: wit_bindgen_core::Source,
3980 c_helpers: wit_bindgen_core::Source,
3981 c_adapters: wit_bindgen_core::Source,
3982 c_async: wit_bindgen_core::Source,
3983}
3984
3985impl Source {
3986 fn src(&mut self, stype: SourceType) -> &mut wit_bindgen_core::Source {
3987 match stype {
3988 SourceType::HDefs => &mut self.h_defs,
3989 SourceType::HFns => &mut self.h_fns,
3990 }
3991 }
3992 fn append(&mut self, append_src: &Source) {
3993 self.h_defs.push_str(&append_src.h_defs);
3994 self.h_fns.push_str(&append_src.h_fns);
3995 self.h_helpers.push_str(&append_src.h_helpers);
3996 self.h_async.push_str(&append_src.h_async);
3997 self.c_defs.push_str(&append_src.c_defs);
3998 self.c_fns.push_str(&append_src.c_fns);
3999 self.c_helpers.push_str(&append_src.c_helpers);
4000 self.c_adapters.push_str(&append_src.c_adapters);
4001 self.c_async.push_str(&append_src.c_async);
4002 }
4003 fn h_defs(&mut self, s: &str) {
4004 self.h_defs.push_str(s);
4005 }
4006 fn h_fns(&mut self, s: &str) {
4007 self.h_fns.push_str(s);
4008 }
4009 fn h_helpers(&mut self, s: &str) {
4010 self.h_helpers.push_str(s);
4011 }
4012 fn c_fns(&mut self, s: &str) {
4013 self.c_fns.push_str(s);
4014 }
4015 fn c_helpers(&mut self, s: &str) {
4016 self.c_helpers.push_str(s);
4017 }
4018 fn c_adapters(&mut self, s: &str) {
4019 self.c_adapters.push_str(s);
4020 }
4021}
4022
4023pub fn wasm_type(ty: WasmType) -> &'static str {
4024 match ty {
4025 WasmType::I32 => "int32_t",
4026 WasmType::I64 => "int64_t",
4027 WasmType::F32 => "float",
4028 WasmType::F64 => "double",
4029 WasmType::Pointer => "uint8_t *",
4030 WasmType::PointerOrI64 => "int64_t",
4031 WasmType::Length => "size_t",
4032 }
4033}
4034
4035pub fn int_repr(ty: Int) -> &'static str {
4036 match ty {
4037 Int::U8 => "uint8_t",
4038 Int::U16 => "uint16_t",
4039 Int::U32 => "uint32_t",
4040 Int::U64 => "uint64_t",
4041 }
4042}
4043
4044pub fn flags_repr(f: &Flags) -> Int {
4045 match f.repr() {
4046 FlagsRepr::U8 => Int::U8,
4047 FlagsRepr::U16 => Int::U16,
4048 FlagsRepr::U32(1) => Int::U32,
4049 FlagsRepr::U32(2) => Int::U64,
4050 repr => panic!("unimplemented flags {repr:?}"),
4051 }
4052}
4053
4054pub fn is_arg_by_pointer(resolve: &Resolve, ty: &Type) -> bool {
4055 match ty {
4056 Type::Id(id) => match resolve.types[*id].kind {
4057 TypeDefKind::Type(t) => is_arg_by_pointer(resolve, &t),
4058 TypeDefKind::Variant(_) => true,
4059 TypeDefKind::Option(_) => true,
4060 TypeDefKind::Result(_) => true,
4061 TypeDefKind::Enum(_) => false,
4062 TypeDefKind::Flags(_) => false,
4063 TypeDefKind::Handle(_) => false,
4064 TypeDefKind::Tuple(_) | TypeDefKind::Record(_) | TypeDefKind::List(_) => true,
4065 TypeDefKind::Future(_) => false,
4066 TypeDefKind::Stream(_) => false,
4067 TypeDefKind::Resource => todo!("is_arg_by_pointer for resource"),
4068 TypeDefKind::Unknown => unreachable!(),
4069 TypeDefKind::FixedSizeList(..) => todo!(),
4070 TypeDefKind::Map(..) => todo!(),
4071 },
4072 Type::String => true,
4073 _ => false,
4074 }
4075}
4076
4077pub fn to_c_ident(name: &str) -> String {
4078 match name {
4079 "alignas" => "alignas_".into(),
4082 "alignof" => "alignof_".into(),
4083 "and" => "and_".into(),
4084 "and_eq" => "and_eq_".into(),
4085 "asm" => "asm_".into(),
4086 "atomic_cancel" => "atomic_cancel_".into(),
4087 "atomic_commit" => "atomic_commit_".into(),
4088 "atomic_noexcept" => "atomic_noexcept_".into(),
4089 "auto" => "auto_".into(),
4090 "bitand" => "bitand_".into(),
4091 "bitor" => "bitor_".into(),
4092 "bool" => "bool_".into(),
4093 "break" => "break_".into(),
4094 "case" => "case_".into(),
4095 "catch" => "catch_".into(),
4096 "char" => "char_".into(),
4097 "char8_t" => "char8_t_".into(),
4098 "char16_t" => "char16_t_".into(),
4099 "char32_t" => "char32_t_".into(),
4100 "class" => "class_".into(),
4101 "compl" => "compl_".into(),
4102 "concept" => "concept_".into(),
4103 "const" => "const_".into(),
4104 "consteval" => "consteval_".into(),
4105 "constexpr" => "constexpr_".into(),
4106 "constinit" => "constinit_".into(),
4107 "const_cast" => "const_cast_".into(),
4108 "continue" => "continue_".into(),
4109 "co_await" => "co_await_".into(),
4110 "co_return" => "co_return_".into(),
4111 "co_yield" => "co_yield_".into(),
4112 "decltype" => "decltype_".into(),
4113 "default" => "default_".into(),
4114 "delete" => "delete_".into(),
4115 "do" => "do_".into(),
4116 "double" => "double_".into(),
4117 "dynamic_cast" => "dynamic_cast_".into(),
4118 "else" => "else_".into(),
4119 "enum" => "enum_".into(),
4120 "explicit" => "explicit_".into(),
4121 "export" => "export_".into(),
4122 "extern" => "extern_".into(),
4123 "false" => "false_".into(),
4124 "float" => "float_".into(),
4125 "for" => "for_".into(),
4126 "friend" => "friend_".into(),
4127 "goto" => "goto_".into(),
4128 "if" => "if_".into(),
4129 "inline" => "inline_".into(),
4130 "int" => "int_".into(),
4131 "long" => "long_".into(),
4132 "mutable" => "mutable_".into(),
4133 "namespace" => "namespace_".into(),
4134 "new" => "new_".into(),
4135 "noexcept" => "noexcept_".into(),
4136 "not" => "not_".into(),
4137 "not_eq" => "not_eq_".into(),
4138 "nullptr" => "nullptr_".into(),
4139 "operator" => "operator_".into(),
4140 "or" => "or_".into(),
4141 "or_eq" => "or_eq_".into(),
4142 "private" => "private_".into(),
4143 "protected" => "protected_".into(),
4144 "public" => "public_".into(),
4145 "reflexpr" => "reflexpr_".into(),
4146 "register" => "register_".into(),
4147 "reinterpret_cast" => "reinterpret_cast_".into(),
4148 "requires" => "requires_".into(),
4149 "return" => "return_".into(),
4150 "short" => "short_".into(),
4151 "signed" => "signed_".into(),
4152 "sizeof" => "sizeof_".into(),
4153 "static" => "static_".into(),
4154 "static_assert" => "static_assert_".into(),
4155 "static_cast" => "static_cast_".into(),
4156 "struct" => "struct_".into(),
4157 "switch" => "switch_".into(),
4158 "synchronized" => "synchronized_".into(),
4159 "template" => "template_".into(),
4160 "this" => "this_".into(),
4161 "thread_local" => "thread_local_".into(),
4162 "throw" => "throw_".into(),
4163 "true" => "true_".into(),
4164 "try" => "try_".into(),
4165 "typedef" => "typedef_".into(),
4166 "typeid" => "typeid_".into(),
4167 "typename" => "typename_".into(),
4168 "union" => "union_".into(),
4169 "unsigned" => "unsigned_".into(),
4170 "using" => "using_".into(),
4171 "virtual" => "virtual_".into(),
4172 "void" => "void_".into(),
4173 "volatile" => "volatile_".into(),
4174 "wchar_t" => "wchar_t_".into(),
4175 "while" => "while_".into(),
4176 "xor" => "xor_".into(),
4177 "xor_eq" => "xor_eq_".into(),
4178 "_Packed" => "_Packed_".into(),
4179 "ret" => "ret_".into(),
4182 "err" => "err_".into(),
4183 "stdin" => "stdin_".into(),
4185 "stdout" => "stdout_".into(),
4186 "stderr" => "stderr_".into(),
4187 s => s.to_snake_case(),
4188 }
4189}
4190
4191const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)";