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