1mod component_type_object;
2
3use anyhow::Result;
4use heck::*;
5use std::collections::{HashMap, HashSet};
6use std::fmt::Write;
7use std::mem;
8use wit_bindgen_core::abi::{self, AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType};
9use wit_bindgen_core::{
10 dealias, uwrite, uwriteln, wit_parser::*, AnonymousTypeGenerator, Direction, Files,
11 InterfaceGenerator as _, Ns, WorldGenerator,
12};
13use wit_component::StringEncoding;
14
15#[derive(Default)]
16struct C {
17 src: Source,
18 opts: Opts,
19 h_includes: Vec<String>,
20 c_includes: Vec<String>,
21 return_pointer_area_size: ArchitectureSize,
22 return_pointer_area_align: Alignment,
23 names: Ns,
24 needs_string: bool,
25 needs_union_int32_float: bool,
26 needs_union_float_int32: bool,
27 needs_union_int64_double: bool,
28 needs_union_double_int64: bool,
29 prim_names: HashSet<String>,
30 world: String,
31 sizes: SizeAlign,
32 renamed_interfaces: HashMap<WorldKey, String>,
33
34 world_id: Option<WorldId>,
35 dtor_funcs: HashMap<TypeId, String>,
36 type_names: HashMap<TypeId, String>,
37 resources: HashMap<TypeId, ResourceInfo>,
38}
39
40#[derive(Default)]
41pub struct ResourceInfo {
42 pub direction: Direction,
43 own: String,
44 borrow: String,
45 drop_fn: String,
46}
47
48#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
49#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
50pub enum Enabled {
51 #[default]
52 No,
53 Yes,
54}
55
56impl std::fmt::Display for Enabled {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 match self {
59 Self::Yes => write!(f, "yes"),
60 Self::No => write!(f, "no"),
61 }
62 }
63}
64
65#[derive(Default, Debug, Clone)]
66#[cfg_attr(feature = "clap", derive(clap::Parser))]
67pub struct Opts {
68 #[cfg_attr(feature = "clap", arg(long))]
70 pub no_helpers: bool,
71
72 #[cfg_attr(feature = "clap", arg(long, default_value_t = StringEncoding::default()))]
74 pub string_encoding: StringEncoding,
75
76 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
79 pub no_sig_flattening: bool,
80
81 #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
84 pub no_object_file: bool,
85
86 #[cfg_attr(feature = "clap", arg(long, name = "K=V", value_parser = parse_rename))]
88 pub rename: Vec<(String, String)>,
89
90 #[cfg_attr(feature = "clap", arg(long))]
92 pub rename_world: Option<String>,
93
94 #[cfg_attr(feature = "clap", arg(long))]
97 pub type_section_suffix: Option<String>,
98
99 #[cfg_attr(feature = "clap", arg(long, default_value_t = Enabled::default()))]
101 pub autodrop_borrows: Enabled,
102}
103
104#[cfg(feature = "clap")]
105fn parse_rename(name: &str) -> Result<(String, String)> {
106 let mut parts = name.splitn(2, '=');
107 let to_rename = parts.next().unwrap();
108 match parts.next() {
109 Some(part) => Ok((to_rename.to_string(), part.to_string())),
110 None => anyhow::bail!("`--rename` option must have an `=` in it (e.g. `--rename a=b`)"),
111 }
112}
113
114impl Opts {
115 pub fn build(&self) -> Box<dyn WorldGenerator> {
116 let mut r = C::default();
117 r.opts = self.clone();
118 Box::new(r)
119 }
120}
121
122#[derive(Debug, Default)]
123struct Return {
124 scalar: Option<Scalar>,
125 retptrs: Vec<Type>,
126}
127
128struct CSig {
129 name: String,
130 sig: String,
131 params: Vec<(bool, String)>,
132 ret: Return,
133 retptrs: Vec<String>,
134}
135
136#[derive(Debug)]
137enum Scalar {
138 Void,
139 OptionBool(Type),
140 ResultBool(Option<Type>, Option<Type>),
141 Type(Type),
142}
143
144impl WorldGenerator for C {
145 fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
146 self.world = self
147 .opts
148 .rename_world
149 .clone()
150 .unwrap_or_else(|| resolve.worlds[world].name.clone());
151 self.sizes.fill(resolve);
152 self.world_id = Some(world);
153
154 let mut interfaces = HashMap::new();
155 let world = &resolve.worlds[world];
156 for (key, _item) in world.imports.iter().chain(world.exports.iter()) {
157 let name = resolve.name_world_key(key);
158 interfaces.insert(name, key.clone());
159 }
160
161 for (from, to) in self.opts.rename.iter() {
162 match interfaces.get(from) {
163 Some(key) => {
164 self.renamed_interfaces.insert(key.clone(), to.clone());
165 }
166 None => {
167 eprintln!("warning: rename of `{from}` did not match any interfaces");
168 }
169 }
170 }
171 }
172
173 fn import_interface(
174 &mut self,
175 resolve: &Resolve,
176 name: &WorldKey,
177 id: InterfaceId,
178 _files: &mut Files,
179 ) -> Result<()> {
180 let wasm_import_module = resolve.name_world_key(name);
181 let mut gen = self.interface(resolve, true, Some(&wasm_import_module));
182 gen.interface = Some((id, name));
183 gen.define_interface_types(id);
184
185 for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() {
186 if i == 0 {
187 let name = resolve.name_world_key(name);
188 uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`");
189 uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`");
190 }
191 gen.import(Some(name), func);
192 }
193
194 gen.gen.src.append(&gen.src);
195
196 Ok(())
197 }
198
199 fn import_funcs(
200 &mut self,
201 resolve: &Resolve,
202 world: WorldId,
203 funcs: &[(&str, &Function)],
204 _files: &mut Files,
205 ) {
206 let name = &resolve.worlds[world].name;
207 let mut gen = self.interface(resolve, true, Some("$root"));
208 gen.define_function_types(funcs);
209
210 for (i, (_name, func)) in funcs.iter().enumerate() {
211 if i == 0 {
212 uwriteln!(gen.src.h_fns, "\n// Imported Functions from `{name}`");
213 uwriteln!(gen.src.c_fns, "\n// Imported Functions from `{name}`");
214 }
215 gen.import(None, func);
216 }
217
218 gen.gen.src.append(&gen.src);
219 }
220
221 fn export_interface(
222 &mut self,
223 resolve: &Resolve,
224 name: &WorldKey,
225 id: InterfaceId,
226 _files: &mut Files,
227 ) -> Result<()> {
228 let mut gen = self.interface(resolve, false, None);
229 gen.interface = Some((id, name));
230 gen.define_interface_types(id);
231
232 for (i, (_name, func)) in resolve.interfaces[id].functions.iter().enumerate() {
233 if i == 0 {
234 let name = resolve.name_world_key(name);
235 uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`");
236 uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`");
237 }
238 gen.export(func, Some(name));
239 }
240
241 gen.gen.src.append(&gen.src);
242 Ok(())
243 }
244
245 fn export_funcs(
246 &mut self,
247 resolve: &Resolve,
248 world: WorldId,
249 funcs: &[(&str, &Function)],
250 _files: &mut Files,
251 ) -> Result<()> {
252 let name = &resolve.worlds[world].name;
253 let mut gen = self.interface(resolve, false, None);
254 gen.define_function_types(funcs);
255
256 for (i, (_name, func)) in funcs.iter().enumerate() {
257 if i == 0 {
258 uwriteln!(gen.src.h_fns, "\n// Exported Functions from `{name}`");
259 uwriteln!(gen.src.c_fns, "\n// Exported Functions from `{name}`");
260 }
261 gen.export(func, None);
262 }
263
264 gen.gen.src.append(&gen.src);
265 Ok(())
266 }
267
268 fn import_types(
269 &mut self,
270 resolve: &Resolve,
271 _world: WorldId,
272 types: &[(&str, TypeId)],
273 _files: &mut Files,
274 ) {
275 let mut gen = self.interface(resolve, true, Some("$root"));
276 let mut live = LiveTypes::default();
277 for (_, id) in types {
278 live.add_type_id(resolve, *id);
279 }
280 gen.define_live_types(live);
281 gen.gen.src.append(&gen.src);
282 }
283
284 fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
285 let linking_symbol = component_type_object::linking_symbol(&self.world);
286 self.c_include("<stdlib.h>");
287 let snake = self.world.to_snake_case();
288 uwriteln!(
289 self.src.c_adapters,
290 "\n// Ensure that the *_component_type.o object is linked in"
291 );
292 uwrite!(
293 self.src.c_adapters,
294 "
295 extern void {linking_symbol}(void);
296 void {linking_symbol}_public_use_in_this_compilation_unit(void) {{
297 {linking_symbol}();
298 }}
299 ",
300 );
301
302 self.print_intrinsics();
303
304 if self.needs_string {
305 self.c_include("<string.h>");
306 let (strlen, size) = match self.opts.string_encoding {
307 StringEncoding::UTF8 => (format!("strlen(s)"), 1),
308 StringEncoding::UTF16 => {
309 self.h_include("<uchar.h>");
310 uwrite!(
311 self.src.h_helpers,
312 "
313 size_t {snake}_string_len(const char16_t* s);
314 ",
315 );
316 uwrite!(
317 self.src.c_helpers,
318 "
319 size_t {snake}_string_len(const char16_t* s) {{
320 char16_t* c = (char16_t*)s;
321 for (; *c; ++c);
322 return c-s;
323 }}
324 ",
325 );
326 (format!("{snake}_string_len(s)"), 2)
327 }
328 StringEncoding::CompactUTF16 => unimplemented!(),
329 };
330 let ty = self.char_type();
331 let c_string_ty = match self.opts.string_encoding {
332 StringEncoding::UTF8 => "char",
333 StringEncoding::UTF16 => "char16_t",
334 StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"),
335 };
336 uwrite!(
337 self.src.h_helpers,
338 "
339 // Transfers ownership of `s` into the string `ret`
340 void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s);
341
342 // Creates a copy of the input nul-terminate string `s` and
343 // stores it into the component model string `ret`.
344 void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s);
345
346 // Deallocates the string pointed to by `ret`, deallocating
347 // the memory behind the string.
348 void {snake}_string_free({snake}_string_t *ret);\
349 ",
350 );
351 uwrite!(
352 self.src.c_helpers,
353 "
354 void {snake}_string_set({snake}_string_t *ret, const {c_string_ty} *s) {{
355 ret->ptr = ({ty}*) s;
356 ret->len = {strlen};
357 }}
358
359 void {snake}_string_dup({snake}_string_t *ret, const {c_string_ty} *s) {{
360 ret->len = {strlen};
361 ret->ptr = ({ty}*) cabi_realloc(NULL, 0, {size}, ret->len * {size});
362 memcpy(ret->ptr, s, ret->len * {size});
363 }}
364
365 void {snake}_string_free({snake}_string_t *ret) {{
366 if (ret->len > 0) {{
367 free(ret->ptr);
368 }}
369 ret->ptr = NULL;
370 ret->len = 0;
371 }}
372 ",
373 );
374 }
375 if self.needs_union_int32_float {
376 uwriteln!(
377 self.src.c_helpers,
378 "\nunion int32_float {{ int32_t a; float b; }};"
379 );
380 }
381 if self.needs_union_float_int32 {
382 uwriteln!(
383 self.src.c_helpers,
384 "\nunion float_int32 {{ float a; int32_t b; }};"
385 );
386 }
387 if self.needs_union_int64_double {
388 uwriteln!(
389 self.src.c_helpers,
390 "\nunion int64_double {{ int64_t a; double b; }};"
391 );
392 }
393 if self.needs_union_double_int64 {
394 uwriteln!(
395 self.src.c_helpers,
396 "\nunion double_int64 {{ double a; int64_t b; }};"
397 );
398 }
399 let version = env!("CARGO_PKG_VERSION");
400 let mut h_str = wit_bindgen_core::Source::default();
401
402 wit_bindgen_core::generated_preamble(&mut h_str, version);
403
404 uwrite!(
405 h_str,
406 "#ifndef __BINDINGS_{0}_H
407 #define __BINDINGS_{0}_H
408 #ifdef __cplusplus
409 extern \"C\" {{",
410 self.world.to_shouty_snake_case(),
411 );
412
413 h_str.deindent(1);
415 uwriteln!(h_str, "\n#endif\n");
416
417 uwriteln!(h_str, "#include <stdint.h>");
418 uwriteln!(h_str, "#include <stdbool.h>");
419 uwriteln!(h_str, "#include <stddef.h>");
420 for include in self.h_includes.iter() {
421 uwriteln!(h_str, "#include {include}");
422 }
423
424 let mut c_str = wit_bindgen_core::Source::default();
425 wit_bindgen_core::generated_preamble(&mut c_str, version);
426 uwriteln!(c_str, "#include \"{snake}.h\"");
427 for include in self.c_includes.iter() {
428 uwriteln!(c_str, "#include {include}");
429 }
430 c_str.push_str(&self.src.c_defs);
431 c_str.push_str(&self.src.c_fns);
432
433 if self.needs_string {
434 uwriteln!(
435 h_str,
436 "
437 typedef struct {snake}_string_t {{\n\
438 {ty} *ptr;\n\
439 size_t len;\n\
440 }} {snake}_string_t;",
441 ty = self.char_type(),
442 );
443 }
444 if self.src.h_defs.len() > 0 {
445 h_str.push_str(&self.src.h_defs);
446 }
447
448 h_str.push_str(&self.src.h_fns);
449
450 if !self.opts.no_helpers && self.src.h_helpers.len() > 0 {
451 uwriteln!(h_str, "\n// Helper Functions");
452 h_str.push_str(&self.src.h_helpers);
453 h_str.push_str("\n");
454 }
455
456 if !self.opts.no_helpers && self.src.c_helpers.len() > 0 {
457 uwriteln!(c_str, "\n// Helper Functions");
458 c_str.push_str(self.src.c_helpers.as_mut_string());
459 }
460
461 uwriteln!(c_str, "\n// Component Adapters");
462
463 if !self.return_pointer_area_size.is_empty() {
467 uwrite!(
469 c_str,
470 "
471 __attribute__((__aligned__({})))
472 static uint8_t RET_AREA[{}];
473 ",
474 self.return_pointer_area_align
475 .format(POINTER_SIZE_EXPRESSION),
476 self.return_pointer_area_size
477 .format(POINTER_SIZE_EXPRESSION),
478 );
479 }
480 c_str.push_str(&self.src.c_adapters);
481
482 uwriteln!(
483 h_str,
484 "
485 #ifdef __cplusplus
486 }}
487 #endif
488 #endif"
489 );
490
491 files.push(&format!("{snake}.h"), h_str.as_bytes());
492 files.push(&format!("{snake}.c"), c_str.as_bytes());
493 if !self.opts.no_object_file {
494 files.push(
495 &format!("{snake}_component_type.o",),
496 component_type_object::object(
497 resolve,
498 id,
499 &self.world,
500 self.opts.string_encoding,
501 self.opts.type_section_suffix.as_deref(),
502 )
503 .unwrap()
504 .as_slice(),
505 );
506 }
507
508 Ok(())
509 }
510
511 fn pre_export_interface(&mut self, resolve: &Resolve, _files: &mut Files) -> Result<()> {
512 self.remove_types_redefined_by_exports(resolve, self.world_id.unwrap());
513 Ok(())
514 }
515}
516
517impl C {
518 fn interface<'a>(
519 &'a mut self,
520 resolve: &'a Resolve,
521 in_import: bool,
522 wasm_import_module: Option<&'a str>,
523 ) -> InterfaceGenerator<'a> {
524 InterfaceGenerator {
525 src: Source::default(),
526 gen: self,
527 resolve,
528 interface: None,
529 in_import,
530 wasm_import_module,
531 }
532 }
533
534 fn h_include(&mut self, s: &str) {
535 self.h_includes.push(s.to_string());
536 }
537
538 fn c_include(&mut self, s: &str) {
539 self.c_includes.push(s.to_string());
540 }
541
542 fn char_type(&self) -> &'static str {
543 match self.opts.string_encoding {
544 StringEncoding::UTF8 => "uint8_t",
545 StringEncoding::UTF16 => "uint16_t",
546 StringEncoding::CompactUTF16 => panic!("Compact UTF16 unsupported"),
547 }
548 }
549
550 fn type_name(&mut self, ty: &Type) -> String {
551 let mut name = String::new();
552 self.push_type_name(ty, &mut name);
553 name
554 }
555
556 fn push_type_name(&mut self, ty: &Type, dst: &mut String) {
557 match ty {
558 Type::Bool => dst.push_str("bool"),
559 Type::Char => dst.push_str("uint32_t"), Type::U8 => dst.push_str("uint8_t"),
561 Type::S8 => dst.push_str("int8_t"),
562 Type::U16 => dst.push_str("uint16_t"),
563 Type::S16 => dst.push_str("int16_t"),
564 Type::U32 => dst.push_str("uint32_t"),
565 Type::S32 => dst.push_str("int32_t"),
566 Type::U64 => dst.push_str("uint64_t"),
567 Type::S64 => dst.push_str("int64_t"),
568 Type::F32 => dst.push_str("float"),
569 Type::F64 => dst.push_str("double"),
570 Type::String => {
571 dst.push_str(&self.world.to_snake_case());
572 dst.push_str("_");
573 dst.push_str("string_t");
574 self.needs_string = true;
575 }
576 Type::ErrorContext => todo!("C error context type name"),
577 Type::Id(id) => {
578 if let Some(name) = self.type_names.get(id) {
579 dst.push_str(name);
580 return;
581 }
582
583 panic!("failed to find type name for {id:?}");
584 }
585 }
586 }
587
588 fn remove_types_redefined_by_exports(&mut self, resolve: &Resolve, world: WorldId) {
602 let live_import_types = imported_types_used_by_exported_interfaces(resolve, world);
603 self.dtor_funcs.retain(|k, _| live_import_types.contains(k));
604 self.type_names.retain(|k, _| live_import_types.contains(k));
605 self.resources.retain(|k, _| live_import_types.contains(k));
606 }
607
608 fn perform_cast(&mut self, op: &str, cast: &Bitcast) -> String {
609 match cast {
610 Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
611 self.needs_union_int32_float = true;
612 format!("((union int32_float){{ (int32_t) {} }}).b", op)
613 }
614 Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
615 self.needs_union_float_int32 = true;
616 format!("((union float_int32){{ {} }}).b", op)
617 }
618 Bitcast::I64ToF64 => {
619 self.needs_union_int64_double = true;
620 format!("((union int64_double){{ (int64_t) {} }}).b", op)
621 }
622 Bitcast::F64ToI64 => {
623 self.needs_union_double_int64 = true;
624 format!("((union double_int64){{ {} }}).b", op)
625 }
626 Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
627 format!("(int64_t) {}", op)
628 }
629 Bitcast::I64ToI32 | Bitcast::I64ToL => {
630 format!("(int32_t) {}", op)
631 }
632 Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
634 format!("{}", op)
635 }
636 Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
637 format!("(uint8_t *) {}", op)
638 }
639
640 Bitcast::PToI32 | Bitcast::PToL => format!("(uintptr_t) {}", op),
642
643 Bitcast::I32ToL | Bitcast::LToI32 | Bitcast::None => op.to_string(),
644
645 Bitcast::Sequence(sequence) => {
646 let [first, second] = &**sequence;
647 let inner = self.perform_cast(op, first);
648 self.perform_cast(&inner, second)
649 }
650 }
651 }
652}
653
654pub fn imported_types_used_by_exported_interfaces(
655 resolve: &Resolve,
656 world: WorldId,
657) -> HashSet<TypeId> {
658 let mut live_export_types = LiveTypes::default();
661 let mut exported_interfaces = HashSet::new();
662 for (_, export) in resolve.worlds[world].exports.iter() {
663 match export {
664 WorldItem::Function(_) => {}
665 WorldItem::Interface { id, .. } => {
666 exported_interfaces.insert(*id);
667 live_export_types.add_interface(resolve, *id)
668 }
669 WorldItem::Type(_) => unreachable!(),
670 }
671 }
672
673 let mut imports_used = HashSet::new();
678 for ty in live_export_types.iter() {
679 if let TypeOwner::Interface(id) = resolve.types[ty].owner {
680 if !exported_interfaces.contains(&id) {
681 imports_used.insert(id);
682 }
683 }
684 }
685
686 let mut live_import_types = LiveTypes::default();
690 for import in imports_used {
691 live_import_types.add_interface(resolve, import);
692 }
693 let live_import_types = live_import_types.iter().collect::<HashSet<_>>();
694 live_import_types
695}
696
697fn is_prim_type(resolve: &Resolve, ty: &Type) -> bool {
698 if let Type::Id(id) = ty {
699 is_prim_type_id(resolve, *id)
700 } else {
701 true
702 }
703}
704
705fn is_prim_type_id(resolve: &Resolve, id: TypeId) -> bool {
706 match &resolve.types[id].kind {
707 TypeDefKind::List(elem) => is_prim_type(resolve, elem),
708
709 TypeDefKind::Option(ty) => is_prim_type(resolve, ty),
710
711 TypeDefKind::Tuple(tuple) => tuple.types.iter().all(|ty| is_prim_type(resolve, ty)),
712
713 TypeDefKind::Type(ty) => is_prim_type(resolve, ty),
714
715 TypeDefKind::Record(_)
716 | TypeDefKind::Resource
717 | TypeDefKind::Handle(_)
718 | TypeDefKind::Flags(_)
719 | TypeDefKind::Variant(_)
720 | TypeDefKind::Enum(_)
721 | TypeDefKind::Result(_)
722 | TypeDefKind::Future(_)
723 | TypeDefKind::Stream(_)
724 | TypeDefKind::Unknown => false,
725 }
726}
727
728pub fn push_ty_name(resolve: &Resolve, ty: &Type, src: &mut String) {
729 match ty {
730 Type::Bool => src.push_str("bool"),
731 Type::Char => src.push_str("char32"),
732 Type::U8 => src.push_str("u8"),
733 Type::S8 => src.push_str("s8"),
734 Type::U16 => src.push_str("u16"),
735 Type::S16 => src.push_str("s16"),
736 Type::U32 => src.push_str("u32"),
737 Type::S32 => src.push_str("s32"),
738 Type::U64 => src.push_str("u64"),
739 Type::S64 => src.push_str("s64"),
740 Type::F32 => src.push_str("f32"),
741 Type::F64 => src.push_str("f64"),
742 Type::String => src.push_str("string"),
743 Type::ErrorContext => todo!(),
744 Type::Id(id) => {
745 let ty = &resolve.types[*id];
746 if let Some(name) = &ty.name {
747 return src.push_str(&name.to_snake_case());
748 }
749 match &ty.kind {
750 TypeDefKind::Type(t) => push_ty_name(resolve, t, src),
751 TypeDefKind::Record(_)
752 | TypeDefKind::Resource
753 | TypeDefKind::Flags(_)
754 | TypeDefKind::Enum(_)
755 | TypeDefKind::Variant(_) => {
756 unimplemented!()
757 }
758 TypeDefKind::Tuple(t) => {
759 src.push_str("tuple");
760 src.push_str(&t.types.len().to_string());
761 for ty in t.types.iter() {
762 src.push_str("_");
763 push_ty_name(resolve, ty, src);
764 }
765 }
766 TypeDefKind::Option(ty) => {
767 src.push_str("option_");
768 push_ty_name(resolve, ty, src);
769 }
770 TypeDefKind::Result(r) => {
771 src.push_str("result_");
772 match &r.ok {
773 Some(ty) => push_ty_name(resolve, ty, src),
774 None => src.push_str("void"),
775 }
776 src.push_str("_");
777 match &r.err {
778 Some(ty) => push_ty_name(resolve, ty, src),
779 None => src.push_str("void"),
780 }
781 }
782 TypeDefKind::List(ty) => {
783 src.push_str("list_");
784 push_ty_name(resolve, ty, src);
785 }
786 TypeDefKind::Future(_) => todo!(),
787 TypeDefKind::Stream(_) => todo!(),
788 TypeDefKind::Handle(Handle::Own(resource)) => {
789 src.push_str("own_");
790 push_ty_name(resolve, &Type::Id(*resource), src);
791 }
792 TypeDefKind::Handle(Handle::Borrow(resource)) => {
793 src.push_str("borrow_");
794 push_ty_name(resolve, &Type::Id(*resource), src);
795 }
796 TypeDefKind::Unknown => unreachable!(),
797 }
798 }
799 }
800}
801
802pub fn owner_namespace<'a>(
803 interface: Option<(InterfaceId, &'a WorldKey)>,
804 in_import: bool,
805 world: String,
806 resolve: &Resolve,
807 id: TypeId,
808 renamed_interfaces: &HashMap<WorldKey, String>,
809) -> String {
810 let ty = &resolve.types[id];
811 match (ty.owner, interface) {
812 (TypeOwner::Interface(a), Some((b, key))) if a == b => {
815 interface_identifier(key, resolve, !in_import, renamed_interfaces)
816 }
817 (TypeOwner::Interface(_), None) => unreachable!(),
818 (TypeOwner::Interface(_), Some(_)) => unreachable!(),
819
820 (TypeOwner::World(_), None) => world.to_snake_case(),
823 (TypeOwner::World(_), Some(_)) => unreachable!(),
824
825 (TypeOwner::None, Some((_, key))) => {
828 interface_identifier(key, resolve, !in_import, renamed_interfaces)
829 }
830 (TypeOwner::None, None) => world.to_snake_case(),
831 }
832}
833
834fn interface_identifier(
835 interface_id: &WorldKey,
836 resolve: &Resolve,
837 in_export: bool,
838 renamed_interfaces: &HashMap<WorldKey, String>,
839) -> String {
840 if let Some(rename) = renamed_interfaces.get(interface_id) {
841 let mut ns = String::new();
842 if in_export && matches!(interface_id, WorldKey::Interface(_)) {
843 ns.push_str("exports_");
844 }
845 ns.push_str(rename);
846 return ns;
847 }
848
849 match interface_id {
850 WorldKey::Name(name) => name.to_snake_case(),
851 WorldKey::Interface(id) => {
852 let mut ns = String::new();
853 if in_export {
854 ns.push_str("exports_");
855 }
856 let iface = &resolve.interfaces[*id];
857 let pkg = &resolve.packages[iface.package.unwrap()];
858 ns.push_str(&pkg.name.namespace.to_snake_case());
859 ns.push_str("_");
860 ns.push_str(&pkg.name.name.to_snake_case());
861 ns.push_str("_");
862 let pkg_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
863 p.name.namespace == pkg.name.namespace
864 && p.name.name == pkg.name.name
865 && p.name.version != pkg.name.version
866 });
867 if pkg_has_multiple_versions {
868 if let Some(version) = &pkg.name.version {
869 let version = version
870 .to_string()
871 .replace('.', "_")
872 .replace('-', "_")
873 .replace('+', "_");
874 ns.push_str(&version);
875 ns.push_str("_");
876 }
877 }
878 ns.push_str(&iface.name.as_ref().unwrap().to_snake_case());
879 ns
880 }
881 }
882}
883
884pub fn c_func_name(
885 in_import: bool,
886 resolve: &Resolve,
887 world: &str,
888 interface_id: Option<&WorldKey>,
889 func: &Function,
890 renamed_interfaces: &HashMap<WorldKey, String>,
891) -> String {
892 let mut name = String::new();
893 match interface_id {
894 Some(id) => name.push_str(&interface_identifier(
895 id,
896 resolve,
897 !in_import,
898 renamed_interfaces,
899 )),
900 None => {
901 if !in_import {
902 name.push_str("exports_");
903 }
904 name.push_str(&world.to_snake_case());
905 }
906 }
907 name.push_str("_");
908 name.push_str(&func.name.to_snake_case().replace('.', "_"));
909 name
910}
911
912struct InterfaceGenerator<'a> {
913 src: Source,
914 in_import: bool,
915 gen: &'a mut C,
916 resolve: &'a Resolve,
917 interface: Option<(InterfaceId, &'a WorldKey)>,
918 wasm_import_module: Option<&'a str>,
919}
920
921impl C {
922 fn print_intrinsics(&mut self) {
923 self.src.c_fns("\n// Canonical ABI intrinsics");
926 self.src.c_fns("\n");
927 self.src.c_fns(
928 r#"
929 __attribute__((__weak__, __export_name__("cabi_realloc")))
930 void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {
931 (void) old_size;
932 if (new_size == 0) return (void*) align;
933 void *ret = realloc(ptr, new_size);
934 if (!ret) abort();
935 return ret;
936 }
937 "#,
938 );
939 }
940}
941
942impl Return {
943 fn return_single(
944 &mut self,
945 resolve: &Resolve,
946 ty: &Type,
947 orig_ty: &Type,
948 sig_flattening: bool,
949 ) {
950 let id = match ty {
951 Type::Id(id) => *id,
952 Type::String => {
953 self.retptrs.push(*orig_ty);
954 return;
955 }
956 Type::ErrorContext => todo!("return_single for error-context"),
957 _ => {
958 self.scalar = Some(Scalar::Type(*orig_ty));
959 return;
960 }
961 };
962 match &resolve.types[id].kind {
963 TypeDefKind::Type(t) => return self.return_single(resolve, t, orig_ty, sig_flattening),
964
965 TypeDefKind::Flags(_) | TypeDefKind::Enum(_) | TypeDefKind::Handle(_) => {
967 self.scalar = Some(Scalar::Type(*orig_ty));
968 return;
969 }
970
971 TypeDefKind::Option(ty) => {
975 if sig_flattening {
976 self.scalar = Some(Scalar::OptionBool(*ty));
977 self.retptrs.push(*ty);
978 return;
979 }
980 }
981
982 TypeDefKind::Result(r) => {
985 if sig_flattening {
986 if let Some(ok) = r.ok {
987 self.retptrs.push(ok);
988 }
989 if let Some(err) = r.err {
990 self.retptrs.push(err);
991 }
992 self.scalar = Some(Scalar::ResultBool(r.ok, r.err));
993 return;
994 }
995 }
996
997 TypeDefKind::Tuple(_)
999 | TypeDefKind::Record(_)
1000 | TypeDefKind::List(_)
1001 | TypeDefKind::Variant(_) => {}
1002
1003 TypeDefKind::Future(_) => todo!("return_single for future"),
1004 TypeDefKind::Stream(_) => todo!("return_single for stream"),
1005 TypeDefKind::Resource => todo!("return_single for resource"),
1006 TypeDefKind::Unknown => unreachable!(),
1007 }
1008
1009 self.retptrs.push(*orig_ty);
1010 }
1011}
1012
1013impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
1014 fn resolve(&self) -> &'a Resolve {
1015 self.resolve
1016 }
1017
1018 fn type_record(&mut self, id: TypeId, _name: &str, record: &Record, docs: &Docs) {
1019 self.src.h_defs("\n");
1020 self.docs(docs, SourceType::HDefs);
1021 self.start_typedef_struct(id);
1022 for field in record.fields.iter() {
1023 self.docs(&field.docs, SourceType::HDefs);
1024 self.print_ty(SourceType::HDefs, &field.ty);
1025 self.src.h_defs(" ");
1026 self.src.h_defs(&to_c_ident(&field.name));
1027 self.src.h_defs(";\n");
1028 }
1029 self.finish_typedef_struct(id);
1030 }
1031
1032 fn type_resource(&mut self, id: TypeId, name: &str, _docs: &Docs) {
1033 let ns = self.owner_namespace(id);
1034 let snake = name.to_snake_case();
1035 let mut own = ns.clone();
1036 let mut borrow = own.clone();
1037 own.push_str("_own");
1038 borrow.push_str("_borrow");
1039 own.push_str("_");
1040 borrow.push_str("_");
1041 own.push_str(&snake);
1042 borrow.push_str(&snake);
1043 own.push_str("_t");
1044 borrow.push_str("_t");
1045
1046 self.src.h_helpers(&format!(
1049 "
1050extern void {ns}_{snake}_drop_own({own} handle);
1051 "
1052 ));
1053 let import_module = if self.in_import {
1054 self.wasm_import_module.unwrap().to_string()
1055 } else {
1056 let module = match self.interface {
1057 Some((_, key)) => self.resolve.name_world_key(key),
1058 None => unimplemented!("resource exports from worlds"),
1059 };
1060 format!("[export]{module}")
1061 };
1062
1063 let drop_fn = format!("__wasm_import_{ns}_{snake}_drop");
1064
1065 self.src.c_helpers(&format!(
1066 r#"
1067__attribute__((__import_module__("{import_module}"), __import_name__("[resource-drop]{name}")))
1068extern void {drop_fn}(int32_t handle);
1069
1070void {ns}_{snake}_drop_own({own} handle) {{
1071 {drop_fn}(handle.__handle);
1072}}
1073 "#
1074 ));
1075
1076 self.src.h_defs(&format!(
1079 "\ntypedef struct {own} {{\nint32_t __handle;\n}} {own};\n"
1080 ));
1081
1082 if self.in_import {
1083 self.src.h_defs(&format!(
1087 "\ntypedef struct {borrow} {{\nint32_t __handle;\n}} {borrow};\n"
1088 ));
1089
1090 if self.autodrop_enabled() {
1091 self.src.h_helpers(&format!(
1096 "\nextern void {ns}_{snake}_drop_borrow({borrow} handle);\n"
1097 ));
1098
1099 self.src.c_helpers(&format!(
1100 "
1101void {ns}_{snake}_drop_borrow({borrow} handle) {{
1102 __wasm_import_{ns}_{snake}_drop(handle.__handle);
1103}}
1104 "
1105 ));
1106 }
1107
1108 self.src.h_helpers(&format!(
1112 "
1113extern {borrow} {ns}_borrow_{snake}({own} handle);
1114 "
1115 ));
1116
1117 self.src.c_helpers(&format!(
1118 r#"
1119{borrow} {ns}_borrow_{snake}({own} arg) {{
1120 return ({borrow}) {{ arg.__handle }};
1121}}
1122 "#
1123 ));
1124 } else {
1125 self.src.h_defs("\n");
1128 self.src.h_defs("typedef struct ");
1129 let ty_name = self.gen.type_names[&id].clone();
1130 self.src.h_defs(&ty_name);
1131 self.src.h_defs(" ");
1132 self.print_typedef_target(id);
1133 let (_, key) = self.interface.unwrap();
1134 let module = self.resolve.name_world_key(key);
1135
1136 self.src
1140 .h_defs(&format!("\ntypedef {ty_name}* {borrow};\n"));
1141
1142 self.src.h_helpers(&format!(
1151 "
1152extern {own} {ns}_{snake}_new({ty_name} *rep);
1153extern {ty_name}* {ns}_{snake}_rep({own} handle);
1154void {ns}_{snake}_destructor({ty_name} *rep);
1155 "
1156 ));
1157
1158 self.src.c_helpers(&format!(
1159 r#"
1160__attribute__(( __import_module__("[export]{module}"), __import_name__("[resource-new]{name}")))
1161extern int32_t __wasm_import_{ns}_{snake}_new(int32_t);
1162
1163__attribute__((__import_module__("[export]{module}"), __import_name__("[resource-rep]{name}")))
1164extern int32_t __wasm_import_{ns}_{snake}_rep(int32_t);
1165
1166{own} {ns}_{snake}_new({ty_name} *rep) {{
1167 return ({own}) {{ __wasm_import_{ns}_{snake}_new((int32_t) rep) }};
1168}}
1169
1170{ty_name}* {ns}_{snake}_rep({own} handle) {{
1171 return ({ns}_{snake}_t*) __wasm_import_{ns}_{snake}_rep(handle.__handle);
1172}}
1173
1174__attribute__((__export_name__("{module}#[dtor]{snake}")))
1175void __wasm_export_{ns}_{snake}_dtor({ns}_{snake}_t* arg) {{
1176 {ns}_{snake}_destructor(arg);
1177}}
1178 "#
1179 ));
1180 }
1181
1182 self.gen.resources.insert(
1183 id,
1184 ResourceInfo {
1185 own,
1186 borrow,
1187 direction: if self.in_import {
1188 Direction::Import
1189 } else {
1190 Direction::Export
1191 },
1192 drop_fn,
1193 },
1194 );
1195 }
1196
1197 fn type_tuple(&mut self, id: TypeId, _name: &str, tuple: &Tuple, docs: &Docs) {
1198 self.src.h_defs("\n");
1199 self.docs(docs, SourceType::HDefs);
1200 self.start_typedef_struct(id);
1201 for (i, ty) in tuple.types.iter().enumerate() {
1202 self.print_ty(SourceType::HDefs, ty);
1203 uwriteln!(self.src.h_defs, " f{i};");
1204 }
1205 self.finish_typedef_struct(id);
1206 }
1207
1208 fn type_flags(&mut self, id: TypeId, name: &str, flags: &Flags, docs: &Docs) {
1209 self.src.h_defs("\n");
1210 self.docs(docs, SourceType::HDefs);
1211 self.src.h_defs("typedef ");
1212 let repr = flags_repr(flags);
1213 self.src.h_defs(int_repr(repr));
1214 self.src.h_defs(" ");
1215 self.print_typedef_target(id);
1216
1217 if flags.flags.len() > 0 {
1218 self.src.h_defs("\n");
1219 }
1220 let ns = self.owner_namespace(id).to_shouty_snake_case();
1221 for (i, flag) in flags.flags.iter().enumerate() {
1222 self.docs(&flag.docs, SourceType::HDefs);
1223 uwriteln!(
1224 self.src.h_defs,
1225 "#define {ns}_{}_{} (1 << {i})",
1226 name.to_shouty_snake_case(),
1227 flag.name.to_shouty_snake_case(),
1228 );
1229 }
1230 }
1231
1232 fn type_variant(&mut self, id: TypeId, name: &str, variant: &Variant, docs: &Docs) {
1233 self.src.h_defs("\n");
1234 self.docs(docs, SourceType::HDefs);
1235 self.start_typedef_struct(id);
1236 self.src.h_defs(int_repr(variant.tag()));
1237 self.src.h_defs(" tag;\n");
1238
1239 let cases_with_data = Vec::from_iter(
1240 variant
1241 .cases
1242 .iter()
1243 .filter_map(|case| case.ty.as_ref().map(|ty| (&case.name, ty))),
1244 );
1245
1246 if !cases_with_data.is_empty() {
1247 self.src.h_defs("union {\n");
1248 for (name, ty) in cases_with_data {
1249 self.print_ty(SourceType::HDefs, ty);
1250 self.src.h_defs(" ");
1251 self.src.h_defs(&to_c_ident(name));
1252 self.src.h_defs(";\n");
1253 }
1254 self.src.h_defs("} val;\n");
1255 }
1256 self.finish_typedef_struct(id);
1257
1258 if variant.cases.len() > 0 {
1259 self.src.h_defs("\n");
1260 }
1261 let ns = self.owner_namespace(id).to_shouty_snake_case();
1262 for (i, case) in variant.cases.iter().enumerate() {
1263 self.docs(&case.docs, SourceType::HDefs);
1264 uwriteln!(
1265 self.src.h_defs,
1266 "#define {ns}_{}_{} {i}",
1267 name.to_shouty_snake_case(),
1268 case.name.to_shouty_snake_case(),
1269 );
1270 }
1271 }
1272
1273 fn type_option(&mut self, id: TypeId, _name: &str, payload: &Type, docs: &Docs) {
1274 self.src.h_defs("\n");
1275 self.docs(docs, SourceType::HDefs);
1276 self.start_typedef_struct(id);
1277 self.src.h_defs("bool is_some;\n");
1278 self.print_ty(SourceType::HDefs, payload);
1279 self.src.h_defs(" val;\n");
1280 self.finish_typedef_struct(id);
1281 }
1282
1283 fn type_result(&mut self, id: TypeId, _name: &str, result: &Result_, docs: &Docs) {
1284 self.src.h_defs("\n");
1285 self.docs(docs, SourceType::HDefs);
1286 self.start_typedef_struct(id);
1287 self.src.h_defs("bool is_err;\n");
1288 if result.ok.is_some() || result.err.is_some() {
1289 self.src.h_defs("union {\n");
1290 if let Some(ok) = result.ok.as_ref() {
1291 self.print_ty(SourceType::HDefs, ok);
1292 self.src.h_defs(" ok;\n");
1293 }
1294 if let Some(err) = result.err.as_ref() {
1295 self.print_ty(SourceType::HDefs, err);
1296 self.src.h_defs(" err;\n");
1297 }
1298 self.src.h_defs("} val;\n");
1299 }
1300 self.finish_typedef_struct(id);
1301 }
1302
1303 fn type_enum(&mut self, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
1304 uwrite!(self.src.h_defs, "\n");
1305 self.docs(docs, SourceType::HDefs);
1306 let int_t = int_repr(enum_.tag());
1307 uwrite!(self.src.h_defs, "typedef {int_t} ");
1308 self.print_typedef_target(id);
1309
1310 if enum_.cases.len() > 0 {
1311 self.src.h_defs("\n");
1312 }
1313 let ns = self.owner_namespace(id).to_shouty_snake_case();
1314 for (i, case) in enum_.cases.iter().enumerate() {
1315 self.docs(&case.docs, SourceType::HDefs);
1316 uwriteln!(
1317 self.src.h_defs,
1318 "#define {ns}_{}_{} {i}",
1319 name.to_shouty_snake_case(),
1320 case.name.to_shouty_snake_case(),
1321 );
1322 }
1323 }
1324
1325 fn type_alias(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
1326 let target = dealias(self.resolve, id);
1330 if matches!(&self.resolve.types[target].kind, TypeDefKind::Resource) {
1331 return;
1332 }
1333
1334 self.src.h_defs("\n");
1335 self.docs(docs, SourceType::HDefs);
1336 self.src.h_defs("typedef ");
1337 self.print_ty(SourceType::HDefs, ty);
1338 self.src.h_defs(" ");
1339 self.print_typedef_target(id);
1340 }
1341
1342 fn type_list(&mut self, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
1343 self.src.h_defs("\n");
1344 self.docs(docs, SourceType::HDefs);
1345 self.start_typedef_struct(id);
1346 self.print_ty(SourceType::HDefs, ty);
1347 self.src.h_defs(" *ptr;\n");
1348 self.src.h_defs("size_t len;\n");
1349 self.finish_typedef_struct(id);
1350 }
1351
1352 fn type_future(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1353 _ = (id, name, ty, docs);
1354 todo!()
1355 }
1356
1357 fn type_stream(&mut self, id: TypeId, name: &str, ty: &Option<Type>, docs: &Docs) {
1358 _ = (id, name, ty, docs);
1359 todo!()
1360 }
1361
1362 fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
1363 let _ = (id, name, ty, docs);
1364 }
1365}
1366
1367impl<'a> wit_bindgen_core::AnonymousTypeGenerator<'a> for InterfaceGenerator<'a> {
1368 fn resolve(&self) -> &'a Resolve {
1369 self.resolve
1370 }
1371
1372 fn anonymous_type_handle(&mut self, id: TypeId, handle: &Handle, _docs: &Docs) {
1373 self.src.h_defs("\ntypedef ");
1374 let resource = match handle {
1375 Handle::Borrow(id) | Handle::Own(id) => id,
1376 };
1377 let info = &self.gen.resources[&dealias(self.resolve, *resource)];
1378 match handle {
1379 Handle::Borrow(_) => self.src.h_defs(&info.borrow),
1380 Handle::Own(_) => self.src.h_defs(&info.own),
1381 }
1382 self.src.h_defs(" ");
1383 self.print_typedef_target(id);
1384 }
1385
1386 fn anonymous_type_tuple(&mut self, id: TypeId, ty: &Tuple, _docs: &Docs) {
1387 self.src.h_defs("\ntypedef ");
1388 self.src.h_defs("struct {\n");
1389 for (i, t) in ty.types.iter().enumerate() {
1390 let ty = self.gen.type_name(t);
1391 uwriteln!(self.src.h_defs, "{ty} f{i};");
1392 }
1393 self.src.h_defs("}");
1394 self.src.h_defs(" ");
1395 self.print_typedef_target(id);
1396 }
1397
1398 fn anonymous_type_option(&mut self, id: TypeId, ty: &Type, _docs: &Docs) {
1399 self.src.h_defs("\ntypedef ");
1400 self.src.h_defs("struct {\n");
1401 self.src.h_defs("bool is_some;\n");
1402 let ty = self.gen.type_name(ty);
1403 uwriteln!(self.src.h_defs, "{ty} val;");
1404 self.src.h_defs("}");
1405 self.src.h_defs(" ");
1406 self.print_typedef_target(id);
1407 }
1408
1409 fn anonymous_type_result(&mut self, id: TypeId, ty: &Result_, _docs: &Docs) {
1410 self.src.h_defs("\ntypedef ");
1411 self.src.h_defs(
1412 "struct {
1413 bool is_err;
1414 ",
1415 );
1416 let ok_ty = ty.ok.as_ref();
1417 let err_ty = ty.err.as_ref();
1418 if ok_ty.is_some() || err_ty.is_some() {
1419 self.src.h_defs("union {\n");
1420 if let Some(ok) = ok_ty {
1421 let ty = self.gen.type_name(ok);
1422 uwriteln!(self.src.h_defs, "{ty} ok;");
1423 }
1424 if let Some(err) = err_ty {
1425 let ty = self.gen.type_name(err);
1426 uwriteln!(self.src.h_defs, "{ty} err;");
1427 }
1428 self.src.h_defs("} val;\n");
1429 }
1430 self.src.h_defs("}");
1431 self.src.h_defs(" ");
1432 self.print_typedef_target(id);
1433 }
1434
1435 fn anonymous_type_list(&mut self, id: TypeId, ty: &Type, _docs: &Docs) {
1436 self.src.h_defs("\ntypedef ");
1437 self.src.h_defs("struct {\n");
1438 let ty = self.gen.type_name(ty);
1439 uwriteln!(self.src.h_defs, "{ty} *ptr;");
1440 self.src.h_defs("size_t len;\n");
1441 self.src.h_defs("}");
1442 self.src.h_defs(" ");
1443 self.print_typedef_target(id);
1444 }
1445
1446 fn anonymous_type_future(&mut self, _id: TypeId, _ty: &Option<Type>, _docs: &Docs) {
1447 todo!("print_anonymous_type for future");
1448 }
1449
1450 fn anonymous_type_stream(&mut self, _id: TypeId, _ty: &Option<Type>, _docs: &Docs) {
1451 todo!("print_anonymous_type for stream");
1452 }
1453
1454 fn anonymous_type_type(&mut self, _id: TypeId, _ty: &Type, _docs: &Docs) {
1455 todo!("print_anonymous_type for type");
1456 }
1457}
1458
1459pub enum CTypeNameInfo<'a> {
1460 Named { name: &'a str },
1461 Anonymous { is_prim: bool },
1462}
1463
1464pub fn gen_type_name(resolve: &Resolve, ty: TypeId) -> (CTypeNameInfo<'_>, String) {
1467 let mut encoded = String::new();
1468 push_ty_name(resolve, &Type::Id(ty), &mut encoded);
1469 let info = if let Some(name) = &resolve.types[ty].name {
1470 CTypeNameInfo::Named {
1471 name: name.as_ref(),
1472 }
1473 } else {
1474 CTypeNameInfo::Anonymous {
1475 is_prim: is_prim_type_id(resolve, ty),
1476 }
1477 };
1478
1479 (info, encoded)
1480}
1481
1482impl InterfaceGenerator<'_> {
1483 fn define_interface_types(&mut self, id: InterfaceId) {
1484 let mut live = LiveTypes::default();
1485 live.add_interface(self.resolve, id);
1486 self.define_live_types(live);
1487 }
1488
1489 fn define_function_types(&mut self, funcs: &[(&str, &Function)]) {
1490 let mut live = LiveTypes::default();
1491 for (_, func) in funcs {
1492 live.add_func(self.resolve, func);
1493 }
1494 self.define_live_types(live);
1495 }
1496
1497 fn define_live_types(&mut self, live: LiveTypes) {
1498 for ty in live.iter() {
1499 if self.gen.type_names.contains_key(&ty) {
1500 continue;
1501 }
1502
1503 let (info, encoded) = gen_type_name(&self.resolve, ty);
1504 match info {
1505 CTypeNameInfo::Named { name } => {
1506 let typedef_name = format!("{}_{encoded}_t", self.owner_namespace(ty));
1507 let prev = self.gen.type_names.insert(ty, typedef_name.clone());
1508 assert!(prev.is_none());
1509
1510 self.define_type(name, ty)
1511 }
1512
1513 CTypeNameInfo::Anonymous { is_prim } => {
1514 let (defined, name) = if is_prim {
1515 let namespace = self.gen.world.to_snake_case();
1516 let name = format!("{namespace}_{encoded}_t");
1517 let new_prim = self.gen.prim_names.insert(name.clone());
1518 (!new_prim, name)
1519 } else {
1520 let namespace = self.owner_namespace(ty);
1521 (false, format!("{namespace}_{encoded}_t"))
1522 };
1523
1524 let prev = self.gen.type_names.insert(ty, name);
1525 assert!(prev.is_none());
1526
1527 if defined {
1528 continue;
1529 }
1530
1531 let kind = &self.resolve.types[ty].kind;
1532 if let TypeDefKind::Handle(handle) = kind {
1533 let resource = match handle {
1534 Handle::Borrow(id) | Handle::Own(id) => id,
1535 };
1536 let origin = dealias(self.resolve, *resource);
1537 if origin == *resource {
1538 continue;
1539 }
1540 }
1541
1542 self.define_anonymous_type(ty)
1543 }
1544 }
1545
1546 self.define_dtor(ty);
1547 }
1548 }
1549
1550 fn define_dtor(&mut self, id: TypeId) {
1551 let h_helpers_start = self.src.h_helpers.len();
1552 let c_helpers_start = self.src.c_helpers.len();
1553
1554 let name = self.gen.type_names[&id].clone();
1555 let prefix = name.strip_suffix("_t").unwrap();
1556
1557 self.src
1558 .h_helpers(&format!("\nvoid {prefix}_free({name} *ptr);\n"));
1559 self.src
1560 .c_helpers(&format!("\nvoid {prefix}_free({name} *ptr) {{\n"));
1561 let c_helpers_body_start = self.src.c_helpers.len();
1562 match &self.resolve.types[id].kind {
1563 TypeDefKind::Type(t) => self.free(t, "ptr"),
1564
1565 TypeDefKind::Flags(_) => {}
1566 TypeDefKind::Enum(_) => {}
1567
1568 TypeDefKind::Record(r) => {
1569 for field in r.fields.iter() {
1570 self.free(&field.ty, &format!("&ptr->{}", to_c_ident(&field.name)));
1571 }
1572 }
1573
1574 TypeDefKind::Tuple(t) => {
1575 for (i, ty) in t.types.iter().enumerate() {
1576 self.free(ty, &format!("&ptr->f{i}"));
1577 }
1578 }
1579
1580 TypeDefKind::List(t) => {
1581 self.src.c_helpers("size_t list_len = ptr->len;\n");
1582 uwriteln!(self.src.c_helpers, "if (list_len > 0) {{");
1583 let mut t_name = String::new();
1584 self.gen.push_type_name(t, &mut t_name);
1585 self.src
1586 .c_helpers(&format!("{t_name} *list_ptr = ptr->ptr;\n"));
1587 self.src
1588 .c_helpers("for (size_t i = 0; i < list_len; i++) {\n");
1589 self.free(t, "&list_ptr[i]");
1590 self.src.c_helpers("}\n");
1591 uwriteln!(self.src.c_helpers, "free(list_ptr);");
1592 uwriteln!(self.src.c_helpers, "}}");
1593 }
1594
1595 TypeDefKind::Variant(v) => {
1596 self.src.c_helpers("switch ((int32_t) ptr->tag) {\n");
1597 for (i, case) in v.cases.iter().enumerate() {
1598 if let Some(ty) = &case.ty {
1599 uwriteln!(self.src.c_helpers, "case {}: {{", i);
1600 let expr = format!("&ptr->val.{}", to_c_ident(&case.name));
1601 self.free(ty, &expr);
1602 self.src.c_helpers("break;\n");
1603 self.src.c_helpers("}\n");
1604 }
1605 }
1606 self.src.c_helpers("}\n");
1607 }
1608
1609 TypeDefKind::Option(t) => {
1610 self.src.c_helpers("if (ptr->is_some) {\n");
1611 self.free(t, "&ptr->val");
1612 self.src.c_helpers("}\n");
1613 }
1614
1615 TypeDefKind::Result(r) => {
1616 self.src.c_helpers("if (!ptr->is_err) {\n");
1617 if let Some(ok) = &r.ok {
1618 self.free(ok, "&ptr->val.ok");
1619 }
1620 if let Some(err) = &r.err {
1621 self.src.c_helpers("} else {\n");
1622 self.free(err, "&ptr->val.err");
1623 }
1624 self.src.c_helpers("}\n");
1625 }
1626 TypeDefKind::Future(_) => todo!("print_dtor for future"),
1627 TypeDefKind::Stream(_) => todo!("print_dtor for stream"),
1628 TypeDefKind::Resource => {}
1629 TypeDefKind::Handle(Handle::Borrow(id) | Handle::Own(id)) => {
1630 self.free(&Type::Id(*id), "*ptr");
1631 }
1632 TypeDefKind::Unknown => unreachable!(),
1633 }
1634 if c_helpers_body_start == self.src.c_helpers.len() {
1635 self.src.c_helpers.as_mut_string().truncate(c_helpers_start);
1636 self.src.h_helpers.as_mut_string().truncate(h_helpers_start);
1637 return;
1638 }
1639 self.src.c_helpers("}\n");
1640 self.gen.dtor_funcs.insert(id, format!("{prefix}_free"));
1641 }
1642
1643 fn free(&mut self, ty: &Type, expr: &str) {
1644 match ty {
1645 Type::Id(id) => {
1646 if let Some(dtor) = self.gen.dtor_funcs.get(&id) {
1647 self.src.c_helpers(&format!("{dtor}({expr});\n"));
1648 }
1649 }
1650 Type::String => {
1651 let snake = self.gen.world.to_snake_case();
1652 self.src
1653 .c_helpers(&format!("{snake}_string_free({expr});\n"));
1654 }
1655 Type::Bool
1656 | Type::U8
1657 | Type::S8
1658 | Type::U16
1659 | Type::S16
1660 | Type::U32
1661 | Type::S32
1662 | Type::U64
1663 | Type::S64
1664 | Type::F32
1665 | Type::F64
1666 | Type::Char => {}
1667 Type::ErrorContext => todo!("error context free"),
1668 }
1669 }
1670
1671 fn c_func_name(&self, interface_id: Option<&WorldKey>, func: &Function) -> String {
1672 c_func_name(
1673 self.in_import,
1674 self.resolve,
1675 &self.gen.world,
1676 interface_id,
1677 func,
1678 &self.gen.renamed_interfaces,
1679 )
1680 }
1681
1682 fn import(&mut self, interface_name: Option<&WorldKey>, func: &Function) {
1683 self.docs(&func.docs, SourceType::HFns);
1684 let sig = self.resolve.wasm_signature(AbiVariant::GuestImport, func);
1685
1686 self.src.c_fns("\n");
1687
1688 uwriteln!(
1692 self.src.c_fns,
1693 "__attribute__((__import_module__(\"{}\"), __import_name__(\"{}\")))",
1694 match interface_name {
1695 Some(name) => self.resolve.name_world_key(name),
1696 None => "$root".to_string(),
1697 },
1698 func.name
1699 );
1700 let name = self.c_func_name(interface_name, func);
1701 let import_name = self.gen.names.tmp(&format!("__wasm_import_{name}",));
1702 self.src.c_fns("extern ");
1703 match sig.results.len() {
1704 0 => self.src.c_fns("void"),
1705 1 => self.src.c_fns(wasm_type(sig.results[0])),
1706 _ => unimplemented!("multi-value return not supported"),
1707 }
1708 self.src.c_fns(" ");
1709 self.src.c_fns(&import_name);
1710 self.src.c_fns("(");
1711 for (i, param) in sig.params.iter().enumerate() {
1712 if i > 0 {
1713 self.src.c_fns(", ");
1714 }
1715 self.src.c_fns(wasm_type(*param));
1716 }
1717 if sig.params.len() == 0 {
1718 self.src.c_fns("void");
1719 }
1720 self.src.c_fns(");\n");
1721
1722 self.src.h_fns("extern ");
1725 let c_sig = self.print_sig(interface_name, func, !self.gen.opts.no_sig_flattening);
1726 self.src.c_adapters("\n");
1727 self.src.c_adapters(&c_sig.sig);
1728 self.src.c_adapters(" {\n");
1729
1730 let mut optional_adapters = String::from("");
1733 if !self.gen.opts.no_sig_flattening {
1734 for (i, (_, param)) in c_sig.params.iter().enumerate() {
1735 let ty = &func.params[i].1;
1736 if let Type::Id(id) = ty {
1737 if let TypeDefKind::Option(_) = &self.resolve.types[*id].kind {
1738 let ty = self.gen.type_name(ty);
1739 uwrite!(
1740 optional_adapters,
1741 "{ty} {param};
1742 {param}.is_some = maybe_{param} != NULL;"
1743 );
1744 uwriteln!(
1745 optional_adapters,
1746 "if (maybe_{param}) {{
1747 {param}.val = *maybe_{param};
1748 }}",
1749 );
1750 }
1751 }
1752 }
1753 }
1754
1755 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
1756 for (pointer, param) in f.sig.params.iter() {
1757 f.locals.insert(¶m).unwrap();
1758 if *pointer {
1759 f.params.push(format!("*{}", param));
1760 } else {
1761 f.params.push(param.clone());
1762 }
1763 }
1764 for ptr in f.sig.retptrs.iter() {
1765 f.locals.insert(ptr).unwrap();
1766 }
1767 f.src.push_str(&optional_adapters);
1768 abi::call(
1769 f.gen.resolve,
1770 AbiVariant::GuestImport,
1771 LiftLower::LowerArgsLiftResults,
1772 func,
1773 &mut f,
1774 false,
1775 );
1776
1777 let FunctionBindgen {
1778 src,
1779 import_return_pointer_area_size,
1780 import_return_pointer_area_align,
1781 ..
1782 } = f;
1783
1784 if !import_return_pointer_area_size.is_empty() {
1785 self.src.c_adapters(&format!(
1786 "\
1787 __attribute__((__aligned__({})))
1788 uint8_t ret_area[{}];
1789 ",
1790 import_return_pointer_area_align.format(POINTER_SIZE_EXPRESSION),
1791 import_return_pointer_area_size.format(POINTER_SIZE_EXPRESSION),
1792 ));
1793 }
1794
1795 self.src.c_adapters(&String::from(src));
1796 self.src.c_adapters("}\n");
1797 }
1798
1799 fn export(&mut self, func: &Function, interface_name: Option<&WorldKey>) {
1800 let sig = self.resolve.wasm_signature(AbiVariant::GuestExport, func);
1801
1802 self.src.c_fns("\n");
1803
1804 let core_module_name = interface_name.map(|s| self.resolve.name_world_key(s));
1805 let export_name = func.legacy_core_export_name(core_module_name.as_deref());
1806
1807 let h_sig = self.print_sig(interface_name, func, !self.gen.opts.no_sig_flattening);
1810
1811 uwriteln!(
1814 self.src.c_adapters,
1815 "\n__attribute__((__export_name__(\"{export_name}\")))"
1816 );
1817 let name = self.c_func_name(interface_name, func);
1818 let import_name = self.gen.names.tmp(&format!("__wasm_export_{name}"));
1819
1820 let mut f = FunctionBindgen::new(self, h_sig, &import_name);
1821 match sig.results.len() {
1822 0 => f.gen.src.c_adapters("void"),
1823 1 => f.gen.src.c_adapters(wasm_type(sig.results[0])),
1824 _ => unimplemented!("multi-value return not supported"),
1825 }
1826 f.gen.src.c_adapters(" ");
1827 f.gen.src.c_adapters(&import_name);
1828 f.gen.src.c_adapters("(");
1829 for (i, param) in sig.params.iter().enumerate() {
1830 if i > 0 {
1831 f.gen.src.c_adapters(", ");
1832 }
1833 let name = f.locals.tmp("arg");
1834 uwrite!(f.gen.src.c_adapters, "{} {}", wasm_type(*param), name);
1835 f.params.push(name);
1836 }
1837 if sig.params.len() == 0 {
1838 f.gen.src.c_adapters("void");
1839 }
1840 f.gen.src.c_adapters(") {\n");
1841
1842 abi::call(
1844 f.gen.resolve,
1845 AbiVariant::GuestExport,
1846 LiftLower::LiftArgsLowerResults,
1847 func,
1848 &mut f,
1849 false,
1850 );
1851 let FunctionBindgen { src, .. } = f;
1852 self.src.c_adapters(&src);
1853 self.src.c_adapters("}\n");
1854
1855 if abi::guest_export_needs_post_return(self.resolve, func) {
1856 uwriteln!(
1857 self.src.c_fns,
1858 "__attribute__((__weak__, __export_name__(\"cabi_post_{export_name}\")))"
1859 );
1860 uwrite!(self.src.c_fns, "void {import_name}_post_return(");
1861
1862 let mut params = Vec::new();
1863 let mut c_sig = CSig {
1864 name: String::from("INVALID"),
1865 sig: String::from("INVALID"),
1866 params: Vec::new(),
1867 ret: Return::default(),
1868 retptrs: Vec::new(),
1869 };
1870 for (i, result) in sig.results.iter().enumerate() {
1871 let name = format!("arg{i}");
1872 uwrite!(self.src.c_fns, "{} {name}", wasm_type(*result));
1873 c_sig.params.push((false, name.clone()));
1874 params.push(name);
1875 }
1876 self.src.c_fns.push_str(") {\n");
1877
1878 let mut f = FunctionBindgen::new(self, c_sig, &import_name);
1879 f.params = params;
1880 abi::post_return(f.gen.resolve, func, &mut f, false);
1881 let FunctionBindgen { src, .. } = f;
1882 self.src.c_fns(&src);
1883 self.src.c_fns("}\n");
1884 }
1885 }
1886
1887 fn print_sig(
1888 &mut self,
1889 interface_name: Option<&WorldKey>,
1890 func: &Function,
1891 sig_flattening: bool,
1892 ) -> CSig {
1893 let name = self.c_func_name(interface_name, func);
1894 self.gen.names.insert(&name).expect("duplicate symbols");
1895
1896 let start = self.src.h_fns.len();
1897 let mut result_rets = false;
1898 let mut result_rets_has_ok_type = false;
1899
1900 let ret = self.classify_ret(func, sig_flattening);
1901 match &ret.scalar {
1902 None | Some(Scalar::Void) => self.src.h_fns("void"),
1903 Some(Scalar::OptionBool(_id)) => self.src.h_fns("bool"),
1904 Some(Scalar::ResultBool(ok, _err)) => {
1905 result_rets = true;
1906 result_rets_has_ok_type = ok.is_some();
1907 self.src.h_fns("bool");
1908 }
1909 Some(Scalar::Type(ty)) => self.print_ty(SourceType::HFns, ty),
1910 }
1911 self.src.h_fns(" ");
1912 self.src.h_fns(&name);
1913 self.src.h_fns("(");
1914 let mut params = Vec::new();
1915 for (i, (name, ty)) in func.params.iter().enumerate() {
1916 if i > 0 {
1917 self.src.h_fns(", ");
1918 }
1919 let pointer = is_arg_by_pointer(self.resolve, ty);
1920 let optional_type = if let Type::Id(id) = ty {
1922 if let TypeDefKind::Option(option_ty) = &self.resolve.types[*id].kind {
1923 if sig_flattening {
1924 Some(option_ty)
1925 } else {
1926 None
1927 }
1928 } else {
1929 None
1930 }
1931 } else {
1932 None
1933 };
1934 let (print_ty, print_name) = if sig_flattening {
1935 if let Some(option_ty) = optional_type {
1936 (option_ty, format!("maybe_{}", to_c_ident(name)))
1937 } else {
1938 (ty, to_c_ident(name))
1939 }
1940 } else {
1941 (ty, to_c_ident(name))
1942 };
1943 self.print_ty(SourceType::HFns, print_ty);
1944 self.src.h_fns(" ");
1945 if pointer {
1946 self.src.h_fns("*");
1947 }
1948 self.src.h_fns(&print_name);
1949 params.push((optional_type.is_none() && pointer, to_c_ident(name)));
1950 }
1951 let mut retptrs = Vec::new();
1952 let single_ret = ret.retptrs.len() == 1;
1953 for (i, ty) in ret.retptrs.iter().enumerate() {
1954 if i > 0 || func.params.len() > 0 {
1955 self.src.h_fns(", ");
1956 }
1957 self.print_ty(SourceType::HFns, ty);
1958 self.src.h_fns(" *");
1959 let name: String = if result_rets {
1960 assert!(i <= 1);
1961 if i == 0 && result_rets_has_ok_type {
1962 "ret".into()
1963 } else {
1964 "err".into()
1965 }
1966 } else if single_ret {
1967 "ret".into()
1968 } else {
1969 format!("ret{}", i)
1970 };
1971 self.src.h_fns(&name);
1972 retptrs.push(name);
1973 }
1974 if func.params.len() == 0 && ret.retptrs.len() == 0 {
1975 self.src.h_fns("void");
1976 }
1977 self.src.h_fns(")");
1978
1979 let sig = self.src.h_fns[start..].to_string();
1980 self.src.h_fns(";\n");
1981
1982 CSig {
1983 sig,
1984 name,
1985 params,
1986 ret,
1987 retptrs,
1988 }
1989 }
1990
1991 fn classify_ret(&mut self, func: &Function, sig_flattening: bool) -> Return {
1992 let mut ret = Return::default();
1993 match &func.result {
1994 None => ret.scalar = Some(Scalar::Void),
1995 Some(ty) => {
1996 ret.return_single(self.resolve, ty, ty, sig_flattening);
1997 }
1998 }
1999 return ret;
2000 }
2001
2002 fn print_typedef_target(&mut self, id: TypeId) {
2003 let name = &self.gen.type_names[&id];
2004 self.src.h_defs(&name);
2005 self.src.h_defs(";\n");
2006 }
2007
2008 fn start_typedef_struct(&mut self, id: TypeId) {
2009 let name = &self.gen.type_names[&id];
2010 self.src.h_defs("typedef struct ");
2011 self.src.h_defs(&name);
2012 self.src.h_defs(" {\n");
2013 }
2014
2015 fn finish_typedef_struct(&mut self, id: TypeId) {
2016 self.src.h_defs("} ");
2017 self.print_typedef_target(id);
2018 }
2019
2020 fn owner_namespace(&self, id: TypeId) -> String {
2021 owner_namespace(
2022 self.interface,
2023 self.in_import,
2024 self.gen.world.clone(),
2025 self.resolve,
2026 id,
2027 &self.gen.renamed_interfaces,
2028 )
2029 }
2030
2031 fn print_ty(&mut self, stype: SourceType, ty: &Type) {
2032 self.gen
2033 .push_type_name(ty, self.src.src(stype).as_mut_string());
2034 }
2035
2036 fn docs(&mut self, docs: &Docs, stype: SourceType) {
2037 let docs = match &docs.contents {
2038 Some(docs) => docs,
2039 None => return,
2040 };
2041 let src = self.src.src(stype);
2042 for line in docs.trim().lines() {
2043 src.push_str("// ");
2044 src.push_str(line);
2045 src.push_str("\n");
2046 }
2047 }
2048
2049 fn autodrop_enabled(&self) -> bool {
2050 self.gen.opts.autodrop_borrows == Enabled::Yes
2051 }
2052
2053 fn contains_droppable_borrow(&self, ty: &Type) -> bool {
2054 if let Type::Id(id) = ty {
2055 match &self.resolve.types[*id].kind {
2056 TypeDefKind::Handle(h) => match h {
2057 Handle::Borrow(id) => {
2060 !self.in_import
2061 && matches!(
2062 self.gen.resources[&dealias(self.resolve, *id)].direction,
2063 Direction::Import
2064 )
2065 }
2066
2067 Handle::Own(_) => false,
2068 },
2069
2070 TypeDefKind::Resource | TypeDefKind::Flags(_) | TypeDefKind::Enum(_) => false,
2071
2072 TypeDefKind::Record(r) => r
2073 .fields
2074 .iter()
2075 .any(|f| self.contains_droppable_borrow(&f.ty)),
2076
2077 TypeDefKind::Tuple(t) => {
2078 t.types.iter().any(|ty| self.contains_droppable_borrow(ty))
2079 }
2080
2081 TypeDefKind::Variant(v) => v.cases.iter().any(|case| {
2082 case.ty
2083 .as_ref()
2084 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2085 }),
2086
2087 TypeDefKind::Option(ty) => self.contains_droppable_borrow(ty),
2088
2089 TypeDefKind::Result(r) => {
2090 r.ok.as_ref()
2091 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2092 || r.err
2093 .as_ref()
2094 .map_or(false, |ty| self.contains_droppable_borrow(ty))
2095 }
2096
2097 TypeDefKind::List(ty) => self.contains_droppable_borrow(ty),
2098
2099 TypeDefKind::Future(_) | TypeDefKind::Stream(_) => false,
2100
2101 TypeDefKind::Type(ty) => self.contains_droppable_borrow(ty),
2102
2103 TypeDefKind::Unknown => false,
2104 }
2105 } else {
2106 false
2107 }
2108 }
2109}
2110
2111struct DroppableBorrow {
2112 name: String,
2113 ty: TypeId,
2114}
2115
2116struct FunctionBindgen<'a, 'b> {
2117 gen: &'a mut InterfaceGenerator<'b>,
2118 locals: Ns,
2119 src: wit_bindgen_core::Source,
2120 sig: CSig,
2121 func_to_call: &'a str,
2122 block_storage: Vec<wit_bindgen_core::Source>,
2123 blocks: Vec<(String, Vec<String>)>,
2124 payloads: Vec<String>,
2125 params: Vec<String>,
2126 wasm_return: Option<String>,
2127 ret_store_cnt: usize,
2128 import_return_pointer_area_size: ArchitectureSize,
2129 import_return_pointer_area_align: Alignment,
2130
2131 borrows: Vec<DroppableBorrow>,
2134
2135 borrow_decls: wit_bindgen_core::Source,
2137}
2138
2139impl<'a, 'b> FunctionBindgen<'a, 'b> {
2140 fn new(
2141 gen: &'a mut InterfaceGenerator<'b>,
2142 sig: CSig,
2143 func_to_call: &'a str,
2144 ) -> FunctionBindgen<'a, 'b> {
2145 FunctionBindgen {
2146 gen,
2147 sig,
2148 locals: Default::default(),
2149 src: Default::default(),
2150 func_to_call,
2151 block_storage: Vec::new(),
2152 blocks: Vec::new(),
2153 payloads: Vec::new(),
2154 params: Vec::new(),
2155 wasm_return: None,
2156 ret_store_cnt: 0,
2157 import_return_pointer_area_size: Default::default(),
2158 import_return_pointer_area_align: Default::default(),
2159 borrow_decls: Default::default(),
2160 borrows: Vec::new(),
2161 }
2162 }
2163
2164 fn store_op(&mut self, op: &str, loc: &str) {
2165 self.src.push_str(loc);
2166 self.src.push_str(" = ");
2167 self.src.push_str(op);
2168 self.src.push_str(";\n");
2169 }
2170
2171 fn load(
2172 &mut self,
2173 ty: &str,
2174 offset: ArchitectureSize,
2175 operands: &[String],
2176 results: &mut Vec<String>,
2177 ) {
2178 results.push(format!(
2179 "*(({}*) ({} + {}))",
2180 ty,
2181 operands[0],
2182 offset.format(POINTER_SIZE_EXPRESSION)
2183 ));
2184 }
2185
2186 fn load_ext(
2187 &mut self,
2188 ty: &str,
2189 offset: ArchitectureSize,
2190 operands: &[String],
2191 results: &mut Vec<String>,
2192 ) {
2193 self.load(ty, offset, operands, results);
2194 let result = results.pop().unwrap();
2195 results.push(format!("(int32_t) {}", result));
2196 }
2197
2198 fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) {
2199 uwriteln!(
2200 self.src,
2201 "*(({}*)({} + {})) = {};",
2202 ty,
2203 operands[1],
2204 offset.format(POINTER_SIZE_EXPRESSION),
2205 operands[0]
2206 );
2207 }
2208
2209 fn store_in_retptr(&mut self, operand: &String) {
2210 self.store_op(
2211 operand,
2212 &format!("*{}", self.sig.retptrs[self.ret_store_cnt]),
2213 );
2214 self.ret_store_cnt = self.ret_store_cnt + 1;
2215 }
2216
2217 fn empty_return_value(&mut self) {
2218 self.ret_store_cnt = self.ret_store_cnt + 1;
2221 }
2222
2223 fn assert_no_droppable_borrows(&self, context: &str, ty: &Type) {
2224 if !self.gen.in_import
2225 && self.gen.autodrop_enabled()
2226 && self.gen.contains_droppable_borrow(ty)
2227 {
2228 panic!(
2229 "Unable to autodrop borrows in `{}` values, please disable autodrop",
2230 context
2231 )
2232 }
2233 }
2234}
2235
2236impl Bindgen for FunctionBindgen<'_, '_> {
2237 type Operand = String;
2238
2239 fn sizes(&self) -> &SizeAlign {
2240 &self.gen.gen.sizes
2241 }
2242
2243 fn push_block(&mut self) {
2244 let prev = mem::take(&mut self.src);
2245 self.block_storage.push(prev);
2246 }
2247
2248 fn finish_block(&mut self, operands: &mut Vec<String>) {
2249 let to_restore = self.block_storage.pop().unwrap();
2250 let src = mem::replace(&mut self.src, to_restore);
2251 self.blocks.push((src.into(), mem::take(operands)));
2252 }
2253
2254 fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
2255 let ptr = self.locals.tmp("ptr");
2256
2257 if self.gen.in_import {
2260 self.import_return_pointer_area_size = self.import_return_pointer_area_size.max(size);
2261 self.import_return_pointer_area_align =
2262 self.import_return_pointer_area_align.max(align);
2263 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &ret_area;", ptr);
2264 } else {
2265 self.gen.gen.return_pointer_area_size = self.gen.gen.return_pointer_area_size.max(size);
2266 self.gen.gen.return_pointer_area_align =
2267 self.gen.gen.return_pointer_area_align.max(align);
2268 uwriteln!(self.src, "uint8_t *{} = (uint8_t *) &RET_AREA;", ptr);
2270 }
2271
2272 ptr
2273 }
2274
2275 fn is_list_canonical(&self, resolve: &Resolve, ty: &Type) -> bool {
2276 resolve.all_bits_valid(ty)
2277 }
2278
2279 fn emit(
2280 &mut self,
2281 resolve: &Resolve,
2282 inst: &Instruction<'_>,
2283 operands: &mut Vec<String>,
2284 results: &mut Vec<String>,
2285 ) {
2286 match inst {
2287 Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
2288 Instruction::I32Const { val } => results.push(val.to_string()),
2289 Instruction::ConstZero { tys } => {
2290 for _ in tys.iter() {
2291 results.push("0".to_string());
2292 }
2293 }
2294
2295 Instruction::U8FromI32 => results.push(format!("(uint8_t) ({})", operands[0])),
2297 Instruction::S8FromI32 => results.push(format!("(int8_t) ({})", operands[0])),
2298 Instruction::U16FromI32 => results.push(format!("(uint16_t) ({})", operands[0])),
2299 Instruction::S16FromI32 => results.push(format!("(int16_t) ({})", operands[0])),
2300 Instruction::U32FromI32 => results.push(format!("(uint32_t) ({})", operands[0])),
2301 Instruction::S32FromI32 | Instruction::S64FromI64 => results.push(operands[0].clone()),
2302 Instruction::U64FromI64 => results.push(format!("(uint64_t) ({})", operands[0])),
2303
2304 Instruction::I32FromU8
2305 | Instruction::I32FromS8
2306 | Instruction::I32FromU16
2307 | Instruction::I32FromS16
2308 | Instruction::I32FromU32 => {
2309 results.push(format!("(int32_t) ({})", operands[0]));
2310 }
2311 Instruction::I32FromS32 | Instruction::I64FromS64 => results.push(operands[0].clone()),
2312 Instruction::I64FromU64 => {
2313 results.push(format!("(int64_t) ({})", operands[0]));
2314 }
2315
2316 Instruction::CoreF32FromF32
2319 | Instruction::CoreF64FromF64
2320 | Instruction::F32FromCoreF32
2321 | Instruction::F64FromCoreF64 => {
2322 results.push(operands[0].clone());
2323 }
2324
2325 Instruction::CharFromI32 => {
2327 results.push(format!("(uint32_t) ({})", operands[0]));
2328 }
2329 Instruction::I32FromChar => {
2330 results.push(format!("(int32_t) ({})", operands[0]));
2331 }
2332
2333 Instruction::Bitcasts { casts } => {
2334 for (cast, op) in casts.iter().zip(operands) {
2335 let op = self.gen.gen.perform_cast(op, cast);
2336 results.push(op);
2337 }
2338 }
2339
2340 Instruction::BoolFromI32 | Instruction::I32FromBool => {
2341 results.push(operands[0].clone());
2342 }
2343
2344 Instruction::RecordLower { record, .. } => {
2345 let op = &operands[0];
2346 for f in record.fields.iter() {
2347 results.push(format!("({}).{}", op, to_c_ident(&f.name)));
2348 }
2349 }
2350 Instruction::RecordLift { ty, record, .. } => {
2351 let name = self.gen.gen.type_name(&Type::Id(*ty));
2352 let mut result = format!("({}) {{\n", name);
2353 for (field, op) in record.fields.iter().zip(operands.iter()) {
2354 let field_ty = self.gen.gen.type_name(&field.ty);
2355 uwriteln!(result, "({}) {},", field_ty, op);
2356 }
2357 result.push_str("}");
2358 results.push(result);
2359 }
2360
2361 Instruction::TupleLower { tuple, .. } => {
2362 let op = &operands[0];
2363 for i in 0..tuple.types.len() {
2364 results.push(format!("({}).f{}", op, i));
2365 }
2366 }
2367 Instruction::TupleLift { ty, tuple, .. } => {
2368 let name = self.gen.gen.type_name(&Type::Id(*ty));
2369 let mut result = format!("({}) {{\n", name);
2370 for (ty, op) in tuple.types.iter().zip(operands.iter()) {
2371 let ty = self.gen.gen.type_name(&ty);
2372 uwriteln!(result, "({}) {},", ty, op);
2373 }
2374 result.push_str("}");
2375 results.push(result);
2376 }
2377
2378 Instruction::HandleLower { .. } => {
2379 let op = &operands[0];
2380 results.push(format!("({op}).__handle"))
2381 }
2382
2383 Instruction::HandleLift { handle, ty, .. } => match handle {
2384 Handle::Borrow(resource)
2385 if matches!(
2386 self.gen.gen.resources[&dealias(resolve, *resource)].direction,
2387 Direction::Export
2388 ) =>
2389 {
2390 let op = &operands[0];
2393 let name = self
2394 .gen
2395 .gen
2396 .type_name(&Type::Id(dealias(resolve, *resource)));
2397 results.push(format!("(({name}*) {op})"))
2398 }
2399 _ => {
2400 let op = &operands[0];
2401 let name = self.gen.gen.type_name(&Type::Id(*ty));
2402 results.push(format!("({name}) {{ {op} }}"));
2403
2404 if let Handle::Borrow(id) = handle {
2405 if !self.gen.in_import && self.gen.autodrop_enabled() {
2406 let ty = dealias(self.gen.resolve, *id);
2409
2410 let name = self.locals.tmp("borrow");
2411 uwriteln!(self.borrow_decls, "int32_t {name} = 0;");
2412 uwriteln!(self.src, "{name} = {op};");
2413
2414 self.borrows.push(DroppableBorrow { name, ty });
2415 }
2416 }
2417 }
2418 },
2419
2420 Instruction::FlagsLower { flags, ty, .. } => match flags_repr(flags) {
2422 Int::U8 | Int::U16 | Int::U32 => {
2423 results.push(operands.pop().unwrap());
2424 }
2425 Int::U64 => {
2426 let name = self.gen.gen.type_name(&Type::Id(*ty));
2427 let tmp = self.locals.tmp("flags");
2428 uwriteln!(self.src, "{name} {tmp} = {};", operands[0]);
2429 results.push(format!("{tmp} & 0xffffffff"));
2430 results.push(format!("({tmp} >> 32) & 0xffffffff"));
2431 }
2432 },
2433
2434 Instruction::FlagsLift { flags, ty, .. } => match flags_repr(flags) {
2435 Int::U8 | Int::U16 | Int::U32 => {
2436 results.push(operands.pop().unwrap());
2437 }
2438 Int::U64 => {
2439 let name = self.gen.gen.type_name(&Type::Id(*ty));
2440 let op0 = &operands[0];
2441 let op1 = &operands[1];
2442 results.push(format!("(({name}) ({op0})) | ((({name}) ({op1})) << 32)"));
2443 }
2444 },
2445
2446 Instruction::VariantPayloadName => {
2447 let name = self.locals.tmp("payload");
2448 results.push(format!("*{}", name));
2449 self.payloads.push(name);
2450 }
2451
2452 Instruction::VariantLower {
2453 variant,
2454 results: result_types,
2455 ..
2456 } => {
2457 let blocks = self
2458 .blocks
2459 .drain(self.blocks.len() - variant.cases.len()..)
2460 .collect::<Vec<_>>();
2461 let payloads = self
2462 .payloads
2463 .drain(self.payloads.len() - variant.cases.len()..)
2464 .collect::<Vec<_>>();
2465
2466 let mut variant_results = Vec::with_capacity(result_types.len());
2467 for ty in result_types.iter() {
2468 let name = self.locals.tmp("variant");
2469 results.push(name.clone());
2470 self.src.push_str(wasm_type(*ty));
2471 self.src.push_str(" ");
2472 self.src.push_str(&name);
2473 self.src.push_str(";\n");
2474 variant_results.push(name);
2475 }
2476
2477 let expr_to_match = format!("({}).tag", operands[0]);
2478
2479 uwriteln!(self.src, "switch ((int32_t) {}) {{", expr_to_match);
2480 for (i, ((case, (block, block_results)), payload)) in
2481 variant.cases.iter().zip(blocks).zip(payloads).enumerate()
2482 {
2483 uwriteln!(self.src, "case {}: {{", i);
2484 if let Some(ty) = case.ty.as_ref() {
2485 let ty = self.gen.gen.type_name(ty);
2486 uwrite!(
2487 self.src,
2488 "const {} *{} = &({}).val",
2489 ty,
2490 payload,
2491 operands[0],
2492 );
2493 self.src.push_str(".");
2494 self.src.push_str(&to_c_ident(&case.name));
2495 self.src.push_str(";\n");
2496 }
2497 self.src.push_str(&block);
2498
2499 for (name, result) in variant_results.iter().zip(&block_results) {
2500 uwriteln!(self.src, "{} = {};", name, result);
2501 }
2502 self.src.push_str("break;\n}\n");
2503 }
2504 self.src.push_str("}\n");
2505 }
2506
2507 Instruction::VariantLift { variant, ty, .. } => {
2508 let blocks = self
2509 .blocks
2510 .drain(self.blocks.len() - variant.cases.len()..)
2511 .collect::<Vec<_>>();
2512
2513 let ty = self.gen.gen.type_name(&Type::Id(*ty));
2514 let result = self.locals.tmp("variant");
2515 uwriteln!(self.src, "{} {};", ty, result);
2516 uwriteln!(self.src, "{}.tag = {};", result, operands[0]);
2517 uwriteln!(self.src, "switch ((int32_t) {}.tag) {{", result);
2518 for (i, (case, (block, block_results))) in
2519 variant.cases.iter().zip(blocks).enumerate()
2520 {
2521 uwriteln!(self.src, "case {}: {{", i);
2522 self.src.push_str(&block);
2523 assert!(block_results.len() == (case.ty.is_some() as usize));
2524
2525 if let Some(_) = case.ty.as_ref() {
2526 let mut dst = format!("{}.val", result);
2527 dst.push_str(".");
2528 dst.push_str(&to_c_ident(&case.name));
2529 self.store_op(&block_results[0], &dst);
2530 }
2531 self.src.push_str("break;\n}\n");
2532 }
2533 self.src.push_str("}\n");
2534 results.push(result);
2535 }
2536
2537 Instruction::OptionLower {
2538 results: result_types,
2539 payload,
2540 ..
2541 } => {
2542 let (mut some, some_results) = self.blocks.pop().unwrap();
2543 let (mut none, none_results) = self.blocks.pop().unwrap();
2544 let some_payload = self.payloads.pop().unwrap();
2545 let _none_payload = self.payloads.pop().unwrap();
2546
2547 for (i, ty) in result_types.iter().enumerate() {
2548 let name = self.locals.tmp("option");
2549 results.push(name.clone());
2550 self.src.push_str(wasm_type(*ty));
2551 self.src.push_str(" ");
2552 self.src.push_str(&name);
2553 self.src.push_str(";\n");
2554 let some_result = &some_results[i];
2555 uwriteln!(some, "{name} = {some_result};");
2556 let none_result = &none_results[i];
2557 uwriteln!(none, "{name} = {none_result};");
2558 }
2559
2560 let op0 = &operands[0];
2561 let ty = self.gen.gen.type_name(payload);
2562 let bind_some = format!("const {ty} *{some_payload} = &({op0}).val;");
2563
2564 uwrite!(
2565 self.src,
2566 "\
2567 if (({op0}).is_some) {{
2568 {bind_some}
2569 {some}}} else {{
2570 {none}}}
2571 "
2572 );
2573 }
2574
2575 Instruction::OptionLift { ty, .. } => {
2576 let (mut some, some_results) = self.blocks.pop().unwrap();
2577 let (mut none, none_results) = self.blocks.pop().unwrap();
2578 assert!(none_results.len() == 0);
2579 assert!(some_results.len() == 1);
2580 let some_result = &some_results[0];
2581
2582 let ty = self.gen.gen.type_name(&Type::Id(*ty));
2583 let result = self.locals.tmp("option");
2584 uwriteln!(self.src, "{ty} {result};");
2585 let op0 = &operands[0];
2586 let set_some = format!("{result}.val = {some_result};\n");
2587 if none.len() > 0 {
2588 none.push('\n');
2589 }
2590 if some.len() > 0 {
2591 some.push('\n');
2592 }
2593 uwrite!(
2594 self.src,
2595 "switch ({op0}) {{
2596 case 0: {{
2597 {result}.is_some = false;
2598 {none}\
2599 break;
2600 }}
2601 case 1: {{
2602 {result}.is_some = true;
2603 {some}\
2604 {set_some}\
2605 break;
2606 }}
2607 }}\n"
2608 );
2609 results.push(result);
2610 }
2611
2612 Instruction::ResultLower {
2613 results: result_types,
2614 result,
2615 ..
2616 } => {
2617 let (mut err, err_results) = self.blocks.pop().unwrap();
2618 let (mut ok, ok_results) = self.blocks.pop().unwrap();
2619 let err_payload = self.payloads.pop().unwrap();
2620 let ok_payload = self.payloads.pop().unwrap();
2621
2622 for (i, ty) in result_types.iter().enumerate() {
2623 let name = self.locals.tmp("result");
2624 results.push(name.clone());
2625 self.src.push_str(wasm_type(*ty));
2626 self.src.push_str(" ");
2627 self.src.push_str(&name);
2628 self.src.push_str(";\n");
2629 let ok_result = &ok_results[i];
2630 uwriteln!(ok, "{name} = {ok_result};");
2631 let err_result = &err_results[i];
2632 uwriteln!(err, "{name} = {err_result};");
2633 }
2634
2635 let op0 = &operands[0];
2636 let bind_ok = if let Some(ok) = result.ok.as_ref() {
2637 let ok_ty = self.gen.gen.type_name(ok);
2638 format!("const {ok_ty} *{ok_payload} = &({op0}).val.ok;")
2639 } else {
2640 String::new()
2641 };
2642 let bind_err = if let Some(err) = result.err.as_ref() {
2643 let err_ty = self.gen.gen.type_name(err);
2644 format!("const {err_ty} *{err_payload} = &({op0}).val.err;")
2645 } else {
2646 String::new()
2647 };
2648 uwrite!(
2649 self.src,
2650 "\
2651 if (({op0}).is_err) {{
2652 {bind_err}\
2653 {err}\
2654 }} else {{
2655 {bind_ok}\
2656 {ok}\
2657 }}
2658 "
2659 );
2660 }
2661
2662 Instruction::ResultLift { result, ty, .. } => {
2663 let (mut err, err_results) = self.blocks.pop().unwrap();
2664 assert!(err_results.len() == (result.err.is_some() as usize));
2665 let (mut ok, ok_results) = self.blocks.pop().unwrap();
2666 assert!(ok_results.len() == (result.ok.is_some() as usize));
2667
2668 if err.len() > 0 {
2669 err.push_str("\n");
2670 }
2671 if ok.len() > 0 {
2672 ok.push_str("\n");
2673 }
2674
2675 let result_tmp = self.locals.tmp("result");
2676 let set_ok = if let Some(_) = result.ok.as_ref() {
2677 let ok_result = &ok_results[0];
2678 format!("{result_tmp}.val.ok = {ok_result};\n")
2679 } else {
2680 String::new()
2681 };
2682 let set_err = if let Some(_) = result.err.as_ref() {
2683 let err_result = &err_results[0];
2684 format!("{result_tmp}.val.err = {err_result};\n")
2685 } else {
2686 String::new()
2687 };
2688
2689 let ty = self.gen.gen.type_name(&Type::Id(*ty));
2690 uwriteln!(self.src, "{ty} {result_tmp};");
2691 let op0 = &operands[0];
2692 uwriteln!(
2693 self.src,
2694 "switch ({op0}) {{
2695 case 0: {{
2696 {result_tmp}.is_err = false;
2697 {ok}\
2698 {set_ok}\
2699 break;
2700 }}
2701 case 1: {{
2702 {result_tmp}.is_err = true;
2703 {err}\
2704 {set_err}\
2705 break;
2706 }}
2707 }}"
2708 );
2709 results.push(result_tmp);
2710 }
2711
2712 Instruction::EnumLower { .. } => results.push(format!("(int32_t) {}", operands[0])),
2713 Instruction::EnumLift { .. } => results.push(operands.pop().unwrap()),
2714
2715 Instruction::ListCanonLower { .. } | Instruction::StringLower { .. } => {
2716 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
2717 results.push(format!("({}).len", operands[0]));
2718 }
2719 Instruction::ListCanonLift { element, ty, .. } => {
2720 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
2721
2722 let list_name = self.gen.gen.type_name(&Type::Id(*ty));
2723 let elem_name = self.gen.gen.type_name(element);
2724 results.push(format!(
2725 "({}) {{ ({}*)({}), ({}) }}",
2726 list_name, elem_name, operands[0], operands[1]
2727 ));
2728 }
2729 Instruction::StringLift { .. } => {
2730 let list_name = self.gen.gen.type_name(&Type::String);
2731 results.push(format!(
2732 "({}) {{ ({}*)({}), ({}) }}",
2733 list_name,
2734 self.gen.gen.char_type(),
2735 operands[0],
2736 operands[1]
2737 ));
2738 }
2739
2740 Instruction::ListLower { .. } => {
2741 let _body = self.blocks.pop().unwrap();
2742 results.push(format!("(uint8_t *) ({}).ptr", operands[0]));
2743 results.push(format!("({}).len", operands[0]));
2744 }
2745
2746 Instruction::ListLift { element, ty, .. } => {
2747 self.assert_no_droppable_borrows("list", &Type::Id(*ty));
2748
2749 let _body = self.blocks.pop().unwrap();
2750 let list_name = self.gen.gen.type_name(&Type::Id(*ty));
2751 let elem_name = self.gen.gen.type_name(element);
2752 results.push(format!(
2753 "({}) {{ ({}*)({}), ({}) }}",
2754 list_name, elem_name, operands[0], operands[1]
2755 ));
2756 }
2757 Instruction::IterElem { .. } => results.push("e".to_string()),
2758 Instruction::IterBasePointer => results.push("base".to_string()),
2759
2760 Instruction::CallWasm { sig, .. } => {
2761 match sig.results.len() {
2762 0 => {}
2763 1 => {
2764 self.src.push_str(wasm_type(sig.results[0]));
2765 let ret = self.locals.tmp("ret");
2766 self.wasm_return = Some(ret.clone());
2767 uwrite!(self.src, " {} = ", ret);
2768 results.push(ret);
2769 }
2770 _ => unimplemented!(),
2771 }
2772 self.src.push_str(self.func_to_call);
2773 self.src.push_str("(");
2774 for (i, op) in operands.iter().enumerate() {
2775 if i > 0 {
2776 self.src.push_str(", ");
2777 }
2778 self.src.push_str(op);
2779 }
2780 self.src.push_str(");\n");
2781 }
2782
2783 Instruction::CallInterface { func, .. } => {
2784 let mut args = String::new();
2785 for (i, (op, (byref, _))) in operands.iter().zip(&self.sig.params).enumerate() {
2786 if i > 0 {
2787 args.push_str(", ");
2788 }
2789 let ty = &func.params[i].1;
2790 if *byref {
2791 let name = self.locals.tmp("arg");
2792 let ty = self.gen.gen.type_name(ty);
2793 uwriteln!(self.src, "{} {} = {};", ty, name, op);
2794 args.push_str("&");
2795 args.push_str(&name);
2796 } else {
2797 if !self.gen.in_import {
2798 if let Type::Id(id) = ty {
2799 if let TypeDefKind::Option(_) = &self.gen.resolve.types[*id].kind {
2800 uwrite!(args, "{op}.is_some ? &({op}.val) : NULL");
2801 continue;
2802 }
2803 }
2804 }
2805 args.push_str(op);
2806 }
2807 }
2808 match &self.sig.ret.scalar {
2809 None => {
2810 let mut retptrs = Vec::new();
2811 for ty in self.sig.ret.retptrs.iter() {
2812 let name = self.locals.tmp("ret");
2813 let ty = self.gen.gen.type_name(ty);
2814 uwriteln!(self.src, "{} {};", ty, name);
2815 if args.len() > 0 {
2816 args.push_str(", ");
2817 }
2818 args.push_str("&");
2819 args.push_str(&name);
2820 retptrs.push(name);
2821 }
2822 uwriteln!(self.src, "{}({});", self.sig.name, args);
2823 results.extend(retptrs);
2824 }
2825 Some(Scalar::Void) => {
2826 uwriteln!(self.src, "{}({});", self.sig.name, args);
2827 }
2828 Some(Scalar::Type(_)) => {
2829 let ret = self.locals.tmp("ret");
2830 let ty = func.result.unwrap();
2831 let ty = self.gen.gen.type_name(&ty);
2832 uwriteln!(self.src, "{} {} = {}({});", ty, ret, self.sig.name, args);
2833 results.push(ret);
2834 }
2835 Some(Scalar::OptionBool(ty)) => {
2836 let ret = self.locals.tmp("ret");
2837 let val = self.locals.tmp("val");
2838 if args.len() > 0 {
2839 args.push_str(", ");
2840 }
2841 args.push_str("&");
2842 args.push_str(&val);
2843 let payload_ty = self.gen.gen.type_name(ty);
2844 uwriteln!(self.src, "{} {};", payload_ty, val);
2845 uwriteln!(self.src, "bool {} = {}({});", ret, self.sig.name, args);
2846 let ty = func.result.unwrap();
2847 let option_ty = self.gen.gen.type_name(&ty);
2848 let option_ret = self.locals.tmp("ret");
2849 uwrite!(
2850 self.src,
2851 "
2852 {option_ty} {option_ret};
2853 {option_ret}.is_some = {ret};
2854 {option_ret}.val = {val};
2855 ",
2856 );
2857 results.push(option_ret);
2858 }
2859 Some(Scalar::ResultBool(ok, err)) => {
2860 let ty = &func.result.unwrap();
2861 let result_ty = self.gen.gen.type_name(ty);
2862 let ret = self.locals.tmp("ret");
2863 let mut ret_iter = self.sig.ret.retptrs.iter();
2864 uwriteln!(self.src, "{result_ty} {ret};");
2865 let ok_name = if ok.is_some() {
2866 if let Some(ty) = ret_iter.next() {
2867 let val = self.locals.tmp("ok");
2868 if args.len() > 0 {
2869 uwrite!(args, ", ");
2870 }
2871 uwrite!(args, "&{val}");
2872 let ty = self.gen.gen.type_name(ty);
2873 uwriteln!(self.src, "{} {};", ty, val);
2874 Some(val)
2875 } else {
2876 None
2877 }
2878 } else {
2879 None
2880 };
2881 let err_name = if let Some(ty) = ret_iter.next() {
2882 let val = self.locals.tmp("err");
2883 if args.len() > 0 {
2884 uwrite!(args, ", ")
2885 }
2886 uwrite!(args, "&{val}");
2887 let ty = self.gen.gen.type_name(ty);
2888 uwriteln!(self.src, "{} {};", ty, val);
2889 Some(val)
2890 } else {
2891 None
2892 };
2893 assert!(ret_iter.next().is_none());
2894 uwrite!(self.src, "");
2895 uwriteln!(self.src, "{ret}.is_err = !{}({args});", self.sig.name);
2896 if err.is_some() {
2897 if let Some(err_name) = err_name {
2898 uwriteln!(
2899 self.src,
2900 "if ({ret}.is_err) {{
2901 {ret}.val.err = {err_name};
2902 }}",
2903 );
2904 }
2905 }
2906 if ok.is_some() {
2907 if let Some(ok_name) = ok_name {
2908 uwriteln!(
2909 self.src,
2910 "if (!{ret}.is_err) {{
2911 {ret}.val.ok = {ok_name};
2912 }}"
2913 );
2914 } else {
2915 uwrite!(self.src, "\n");
2916 }
2917 }
2918 results.push(ret);
2919 }
2920 }
2921 }
2922 Instruction::Return { .. } if self.gen.in_import => match self.sig.ret.scalar {
2923 None => {
2924 for op in operands.iter() {
2925 self.store_in_retptr(op);
2926 }
2927 }
2928 Some(Scalar::Void) => {
2929 assert!(operands.is_empty());
2930 }
2931 Some(Scalar::Type(_)) => {
2932 assert_eq!(operands.len(), 1);
2933 self.src.push_str("return ");
2934 self.src.push_str(&operands[0]);
2935 self.src.push_str(";\n");
2936 }
2937 Some(Scalar::OptionBool(_)) => {
2938 assert_eq!(operands.len(), 1);
2939 let variant = &operands[0];
2940 self.store_in_retptr(&format!("{}.val", variant));
2941 self.src.push_str("return ");
2942 self.src.push_str(&variant);
2943 self.src.push_str(".is_some;\n");
2944 }
2945 Some(Scalar::ResultBool(ok, err)) => {
2946 assert_eq!(operands.len(), 1);
2947 let variant = &operands[0];
2948 assert!(self.sig.retptrs.len() <= 2);
2949 uwriteln!(self.src, "if (!{}.is_err) {{", variant);
2950 if ok.is_some() {
2951 if ok.is_some() {
2952 self.store_in_retptr(&format!("{}.val.ok", variant));
2953 } else {
2954 self.empty_return_value();
2955 }
2956 }
2957 uwriteln!(
2958 self.src,
2959 " return 1;
2960 }} else {{"
2961 );
2962 if err.is_some() {
2963 if err.is_some() {
2964 self.store_in_retptr(&format!("{}.val.err", variant));
2965 } else {
2966 self.empty_return_value();
2967 }
2968 }
2969 uwriteln!(
2970 self.src,
2971 " return 0;
2972 }}"
2973 );
2974 assert_eq!(self.ret_store_cnt, self.sig.retptrs.len());
2975 }
2976 },
2977 Instruction::Return { amt, .. } => {
2978 let src = std::mem::replace(&mut self.src, std::mem::take(&mut self.borrow_decls));
2980 self.src.append_src(&src);
2981
2982 for DroppableBorrow { name, ty } in self.borrows.iter() {
2983 let drop_fn = self.gen.gen.resources[ty].drop_fn.as_str();
2984 uwriteln!(self.src, "if ({name} != 0) {{");
2985 uwriteln!(self.src, " {drop_fn}({name});");
2986 uwriteln!(self.src, "}}");
2987 }
2988
2989 assert!(*amt <= 1);
2990 if *amt == 1 {
2991 uwriteln!(self.src, "return {};", operands[0]);
2992 }
2993 }
2994
2995 Instruction::I32Load { offset } => self.load("int32_t", *offset, operands, results),
2996 Instruction::I64Load { offset } => self.load("int64_t", *offset, operands, results),
2997 Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
2998 Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
2999 Instruction::PointerLoad { offset } => {
3000 self.load("uint8_t *", *offset, operands, results)
3001 }
3002 Instruction::LengthLoad { offset } => self.load("size_t", *offset, operands, results),
3003 Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
3004 Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
3005 Instruction::F32Store { offset } => self.store("float", *offset, operands),
3006 Instruction::F64Store { offset } => self.store("double", *offset, operands),
3007 Instruction::I32Store8 { offset } => self.store("int8_t", *offset, operands),
3008 Instruction::I32Store16 { offset } => self.store("int16_t", *offset, operands),
3009 Instruction::PointerStore { offset } => self.store("uint8_t *", *offset, operands),
3010 Instruction::LengthStore { offset } => self.store("size_t", *offset, operands),
3011
3012 Instruction::I32Load8U { offset } => {
3013 self.load_ext("uint8_t", *offset, operands, results)
3014 }
3015 Instruction::I32Load8S { offset } => {
3016 self.load_ext("int8_t", *offset, operands, results)
3017 }
3018 Instruction::I32Load16U { offset } => {
3019 self.load_ext("uint16_t", *offset, operands, results)
3020 }
3021 Instruction::I32Load16S { offset } => {
3022 self.load_ext("int16_t", *offset, operands, results)
3023 }
3024
3025 Instruction::GuestDeallocate { .. } => {
3026 uwriteln!(self.src, "free({});", operands[0]);
3027 }
3028 Instruction::GuestDeallocateString => {
3029 uwriteln!(self.src, "if (({}) > 0) {{", operands[1]);
3030 uwriteln!(self.src, "free({});", operands[0]);
3031 uwriteln!(self.src, "}}");
3032 }
3033 Instruction::GuestDeallocateVariant { blocks } => {
3034 let blocks = self
3035 .blocks
3036 .drain(self.blocks.len() - blocks..)
3037 .collect::<Vec<_>>();
3038
3039 uwriteln!(self.src, "switch ((int32_t) {}) {{", operands[0]);
3040 for (i, (block, results)) in blocks.into_iter().enumerate() {
3041 assert!(results.is_empty());
3042 uwriteln!(self.src, "case {}: {{", i);
3043 self.src.push_str(&block);
3044 self.src.push_str("break;\n}\n");
3045 }
3046 self.src.push_str("}\n");
3047 }
3048 Instruction::GuestDeallocateList { element } => {
3049 let (body, results) = self.blocks.pop().unwrap();
3050 assert!(results.is_empty());
3051 let len = self.locals.tmp("len");
3052 uwriteln!(self.src, "size_t {len} = {};", operands[1]);
3053 uwriteln!(self.src, "if ({len} > 0) {{");
3054 let ptr = self.locals.tmp("ptr");
3055 uwriteln!(self.src, "uint8_t *{ptr} = {};", operands[0]);
3056 let i = self.locals.tmp("i");
3057 uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{");
3058 let size = self.gen.gen.sizes.size(element);
3059 uwriteln!(
3060 self.src,
3061 "uint8_t *base = {ptr} + {i} * {};",
3062 size.format(POINTER_SIZE_EXPRESSION)
3063 );
3064 uwriteln!(self.src, "(void) base;");
3065 uwrite!(self.src, "{body}");
3066 uwriteln!(self.src, "}}");
3067 uwriteln!(self.src, "free({ptr});");
3068 uwriteln!(self.src, "}}");
3069 }
3070
3071 Instruction::Flush { amt } => {
3072 results.extend(operands.iter().take(*amt).map(|v| v.clone()));
3073 }
3074
3075 i => unimplemented!("{:?}", i),
3076 }
3077 }
3078}
3079
3080#[derive(Default, Clone, Copy)]
3081enum SourceType {
3082 #[default]
3083 HDefs,
3084 HFns,
3085 }
3091
3092#[derive(Default)]
3093struct Source {
3094 h_defs: wit_bindgen_core::Source,
3095 h_fns: wit_bindgen_core::Source,
3096 h_helpers: wit_bindgen_core::Source,
3097 c_defs: wit_bindgen_core::Source,
3098 c_fns: wit_bindgen_core::Source,
3099 c_helpers: wit_bindgen_core::Source,
3100 c_adapters: wit_bindgen_core::Source,
3101}
3102
3103impl Source {
3104 fn src(&mut self, stype: SourceType) -> &mut wit_bindgen_core::Source {
3105 match stype {
3106 SourceType::HDefs => &mut self.h_defs,
3107 SourceType::HFns => &mut self.h_fns,
3108 }
3109 }
3110 fn append(&mut self, append_src: &Source) {
3111 self.h_defs.push_str(&append_src.h_defs);
3112 self.h_fns.push_str(&append_src.h_fns);
3113 self.h_helpers.push_str(&append_src.h_helpers);
3114 self.c_defs.push_str(&append_src.c_defs);
3115 self.c_fns.push_str(&append_src.c_fns);
3116 self.c_helpers.push_str(&append_src.c_helpers);
3117 self.c_adapters.push_str(&append_src.c_adapters);
3118 }
3119 fn h_defs(&mut self, s: &str) {
3120 self.h_defs.push_str(s);
3121 }
3122 fn h_fns(&mut self, s: &str) {
3123 self.h_fns.push_str(s);
3124 }
3125 fn h_helpers(&mut self, s: &str) {
3126 self.h_helpers.push_str(s);
3127 }
3128 fn c_fns(&mut self, s: &str) {
3129 self.c_fns.push_str(s);
3130 }
3131 fn c_helpers(&mut self, s: &str) {
3132 self.c_helpers.push_str(s);
3133 }
3134 fn c_adapters(&mut self, s: &str) {
3135 self.c_adapters.push_str(s);
3136 }
3137}
3138
3139fn wasm_type(ty: WasmType) -> &'static str {
3140 match ty {
3141 WasmType::I32 => "int32_t",
3142 WasmType::I64 => "int64_t",
3143 WasmType::F32 => "float",
3144 WasmType::F64 => "double",
3145 WasmType::Pointer => "uint8_t *",
3146 WasmType::PointerOrI64 => "int64_t",
3147 WasmType::Length => "size_t",
3148 }
3149}
3150
3151pub fn int_repr(ty: Int) -> &'static str {
3152 match ty {
3153 Int::U8 => "uint8_t",
3154 Int::U16 => "uint16_t",
3155 Int::U32 => "uint32_t",
3156 Int::U64 => "uint64_t",
3157 }
3158}
3159
3160pub fn flags_repr(f: &Flags) -> Int {
3161 match f.repr() {
3162 FlagsRepr::U8 => Int::U8,
3163 FlagsRepr::U16 => Int::U16,
3164 FlagsRepr::U32(1) => Int::U32,
3165 FlagsRepr::U32(2) => Int::U64,
3166 repr => panic!("unimplemented flags {:?}", repr),
3167 }
3168}
3169
3170pub fn is_arg_by_pointer(resolve: &Resolve, ty: &Type) -> bool {
3171 match ty {
3172 Type::Id(id) => match resolve.types[*id].kind {
3173 TypeDefKind::Type(t) => is_arg_by_pointer(resolve, &t),
3174 TypeDefKind::Variant(_) => true,
3175 TypeDefKind::Option(_) => true,
3176 TypeDefKind::Result(_) => true,
3177 TypeDefKind::Enum(_) => false,
3178 TypeDefKind::Flags(_) => false,
3179 TypeDefKind::Handle(_) => false,
3180 TypeDefKind::Tuple(_) | TypeDefKind::Record(_) | TypeDefKind::List(_) => true,
3181 TypeDefKind::Future(_) => todo!("is_arg_by_pointer for future"),
3182 TypeDefKind::Stream(_) => todo!("is_arg_by_pointer for stream"),
3183 TypeDefKind::Resource => todo!("is_arg_by_pointer for resource"),
3184 TypeDefKind::Unknown => unreachable!(),
3185 },
3186 Type::String => true,
3187 _ => false,
3188 }
3189}
3190
3191pub fn to_c_ident(name: &str) -> String {
3192 match name {
3193 "alignas" => "alignas_".into(),
3196 "alignof" => "alignof_".into(),
3197 "and" => "and_".into(),
3198 "and_eq" => "and_eq_".into(),
3199 "asm" => "asm_".into(),
3200 "atomic_cancel" => "atomic_cancel_".into(),
3201 "atomic_commit" => "atomic_commit_".into(),
3202 "atomic_noexcept" => "atomic_noexcept_".into(),
3203 "auto" => "auto_".into(),
3204 "bitand" => "bitand_".into(),
3205 "bitor" => "bitor_".into(),
3206 "bool" => "bool_".into(),
3207 "break" => "break_".into(),
3208 "case" => "case_".into(),
3209 "catch" => "catch_".into(),
3210 "char" => "char_".into(),
3211 "char8_t" => "char8_t_".into(),
3212 "char16_t" => "char16_t_".into(),
3213 "char32_t" => "char32_t_".into(),
3214 "class" => "class_".into(),
3215 "compl" => "compl_".into(),
3216 "concept" => "concept_".into(),
3217 "const" => "const_".into(),
3218 "consteval" => "consteval_".into(),
3219 "constexpr" => "constexpr_".into(),
3220 "constinit" => "constinit_".into(),
3221 "const_cast" => "const_cast_".into(),
3222 "continue" => "continue_".into(),
3223 "co_await" => "co_await_".into(),
3224 "co_return" => "co_return_".into(),
3225 "co_yield" => "co_yield_".into(),
3226 "decltype" => "decltype_".into(),
3227 "default" => "default_".into(),
3228 "delete" => "delete_".into(),
3229 "do" => "do_".into(),
3230 "double" => "double_".into(),
3231 "dynamic_cast" => "dynamic_cast_".into(),
3232 "else" => "else_".into(),
3233 "enum" => "enum_".into(),
3234 "explicit" => "explicit_".into(),
3235 "export" => "export_".into(),
3236 "extern" => "extern_".into(),
3237 "false" => "false_".into(),
3238 "float" => "float_".into(),
3239 "for" => "for_".into(),
3240 "friend" => "friend_".into(),
3241 "goto" => "goto_".into(),
3242 "if" => "if_".into(),
3243 "inline" => "inline_".into(),
3244 "int" => "int_".into(),
3245 "long" => "long_".into(),
3246 "mutable" => "mutable_".into(),
3247 "namespace" => "namespace_".into(),
3248 "new" => "new_".into(),
3249 "noexcept" => "noexcept_".into(),
3250 "not" => "not_".into(),
3251 "not_eq" => "not_eq_".into(),
3252 "nullptr" => "nullptr_".into(),
3253 "operator" => "operator_".into(),
3254 "or" => "or_".into(),
3255 "or_eq" => "or_eq_".into(),
3256 "private" => "private_".into(),
3257 "protected" => "protected_".into(),
3258 "public" => "public_".into(),
3259 "reflexpr" => "reflexpr_".into(),
3260 "register" => "register_".into(),
3261 "reinterpret_cast" => "reinterpret_cast_".into(),
3262 "requires" => "requires_".into(),
3263 "return" => "return_".into(),
3264 "short" => "short_".into(),
3265 "signed" => "signed_".into(),
3266 "sizeof" => "sizeof_".into(),
3267 "static" => "static_".into(),
3268 "static_assert" => "static_assert_".into(),
3269 "static_cast" => "static_cast_".into(),
3270 "struct" => "struct_".into(),
3271 "switch" => "switch_".into(),
3272 "synchronized" => "synchronized_".into(),
3273 "template" => "template_".into(),
3274 "this" => "this_".into(),
3275 "thread_local" => "thread_local_".into(),
3276 "throw" => "throw_".into(),
3277 "true" => "true_".into(),
3278 "try" => "try_".into(),
3279 "typedef" => "typedef_".into(),
3280 "typeid" => "typeid_".into(),
3281 "typename" => "typename_".into(),
3282 "union" => "union_".into(),
3283 "unsigned" => "unsigned_".into(),
3284 "using" => "using_".into(),
3285 "virtual" => "virtual_".into(),
3286 "void" => "void_".into(),
3287 "volatile" => "volatile_".into(),
3288 "wchar_t" => "wchar_t_".into(),
3289 "while" => "while_".into(),
3290 "xor" => "xor_".into(),
3291 "xor_eq" => "xor_eq_".into(),
3292 "_Packed" => "_Packed_".into(),
3293 "ret" => "ret_".into(),
3296 "err" => "err_".into(),
3297 s => s.to_snake_case(),
3298 }
3299}
3300
3301const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)";