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