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