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