wit_bindgen_c/
lib.rs

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    /// Skip emitting component allocation helper functions
69    #[cfg_attr(feature = "clap", arg(long))]
70    pub no_helpers: bool,
71
72    /// Set component string encoding
73    #[cfg_attr(feature = "clap", arg(long, default_value_t = StringEncoding::default()))]
74    pub string_encoding: StringEncoding,
75
76    /// Skip optional null pointer and boolean result argument signature
77    /// flattening
78    #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
79    pub no_sig_flattening: bool,
80
81    /// Skip generating an object file which contains type information for the
82    /// world that is being generated.
83    #[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
84    pub no_object_file: bool,
85
86    /// Rename the interface `K` to `V` in the generated source code.
87    #[cfg_attr(feature = "clap", arg(long, name = "K=V", value_parser = parse_rename))]
88    pub rename: Vec<(String, String)>,
89
90    /// Rename the world in the generated source code and file names.
91    #[cfg_attr(feature = "clap", arg(long))]
92    pub rename_world: Option<String>,
93
94    /// Add the specified suffix to the name of the custome section containing
95    /// the component type.
96    #[cfg_attr(feature = "clap", arg(long))]
97    pub type_section_suffix: Option<String>,
98
99    /// Configure the autodropping of borrows in exported functions.
100    #[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        // Deindent the extern C { declaration
414        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        // Declare a statically-allocated return area, if needed. We only do
464        // this for export bindings, because import bindings allocate their
465        // return-area on the stack.
466        if !self.return_pointer_area_size.is_empty() {
467            // Automatic indentation avoided due to `extern "C" {` declaration
468            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"), // TODO: better type?
560            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    /// Removes all types from `self.{dtor_funcs,type_names,resources}` which
589    /// are redefined in exports.
590    ///
591    /// WIT interfaces can be both imported and exported but they're represented
592    /// with the same `TypeId` internally within the `wit-parser`
593    /// representation. This means that duplicate types need to be generated for
594    /// exports, even if the same interface was already imported. If nothing
595    /// were done here though then the same type imported and exported wouldn't
596    /// generate anything new since preexisting types are skipped in
597    /// `define_live_types`.
598    ///
599    /// This function will trim the sets on `self` to only retain those types
600    /// which exports refer to that come from imports.
601    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            // P64 is currently represented as int64_t, so no conversion is needed.
633            Bitcast::I64ToP64 | Bitcast::P64ToI64 => {
634                format!("{}", op)
635            }
636            Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
637                format!("(uint8_t *) {}", op)
638            }
639
640            // Cast to uintptr_t to avoid implicit pointer-to-int conversions.
641            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    // First build up a set of all types used by exports and all the
659    // exported interfaces.
660    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    // Using the above sets a set of required import interfaces can be
674    // calculated. This is all referred-to-types that are owned by an
675    // interface that aren't present in an export. Note that the topological
676    // sorting and WIT requirements are what makes this check possible.
677    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    // With the set of imports used that aren't shadowed by exports the set
687    // of types on `self` can now be trimmed. All live types in all the
688    // imports are calculated and then everything except these are removed.
689    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        // If this type is owned by an interface, then we must be generating
813        // bindings for that interface to proceed.
814        (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        // If this type is owned by a world then we must not be generating
821        // bindings for an interface.
822        (TypeOwner::World(_), None) => world.to_snake_case(),
823        (TypeOwner::World(_), Some(_)) => unreachable!(),
824
825        // If this type has no owner then it's an anonymous type. Here it's
826        // assigned to whatever we happen to be generating bindings for.
827        (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        // Note that these intrinsics are declared as `weak` so they can be
924        // overridden from some other symbol.
925        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            // Flags are returned as their bare values, and enums and handles are scalars
966            TypeDefKind::Flags(_) | TypeDefKind::Enum(_) | TypeDefKind::Handle(_) => {
967                self.scalar = Some(Scalar::Type(*orig_ty));
968                return;
969            }
970
971            // Unpack optional returns where a boolean discriminant is
972            // returned and then the actual type returned is returned
973            // through a return pointer.
974            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            // Unpack a result as a boolean return type, with two
983            // return pointers for ok and err values
984            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            // These types are always returned indirectly.
998            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        // All resources, whether or not they're imported or exported, get the
1047        // ability to drop handles.
1048        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        // All resources, whether or not they're imported or exported, have an
1077        // handle-index-based representation for "own" handles.
1078        self.src.h_defs(&format!(
1079            "\ntypedef struct {own} {{\nint32_t __handle;\n}} {own};\n"
1080        ));
1081
1082        if self.in_import {
1083            // For imported resources borrowed handles are represented the same
1084            // way as owned handles. They're given a unique type, however, to
1085            // prevent type confusion at runtime in theory.
1086            self.src.h_defs(&format!(
1087                "\ntypedef struct {borrow} {{\nint32_t __handle;\n}} {borrow};\n"
1088            ));
1089
1090            if self.autodrop_enabled() {
1091                // As we have two different types for owned vs borrowed resources,
1092                // but owns and borrows are dropped using the same intrinsic we
1093                // also generate a version of the drop function for borrows that we
1094                // possibly acquire through our exports.
1095                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            // To handle the two types generated for borrow/own this helper
1109            // function enables converting an own handle to a borrow handle
1110            // which will have the same index internally.
1111            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            // For exported resources first generate a typedef that the user
1126            // will be required to fill in. This is an empty struct.
1127            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            // Exported resources use a different representation than imports
1137            // for borrows which is a raw pointer to the struct declared just
1138            // above.
1139            self.src
1140                .h_defs(&format!("\ntypedef {ty_name}* {borrow};\n"));
1141
1142            // Exported resources are defined by this module which means they
1143            // get access to more intrinsics:
1144            //
1145            // * construction of a resource (rep to handle)
1146            // * extraction of the representation of a resource (handle to rep)
1147            //
1148            // Additionally users must define a destructor for this resource, so
1149            // declare its prototype here.
1150            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        // we should skip generating `typedef` for `Resource` types because they aren't even
1327        // defined anywhere, not even in `type_resource`. Only its `Handle` types are defined.
1328        // The aliasing handle types are defined in `define_anonymous_type`.
1329        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
1464/// Generate the type part of a c identifier, missing the namespace and the `_t` suffix.
1465/// Additionally return a `CTypeNameInfo` that describes what sort of name has been produced.
1466pub 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        // In the private C file, print a function declaration which is the
1689        // actual wasm import that we'll be calling, and this has the raw wasm
1690        // signature.
1691        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        // Print the public facing signature into the header, and since that's
1723        // what we are defining also print it into the C file.
1724        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        // construct optional adapters from maybe pointers to real optional
1731        // structs internally
1732        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(&param).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        // Print the actual header for this function into the header file, and
1808        // it's what we'll be calling.
1809        let h_sig = self.print_sig(interface_name, func, !self.gen.opts.no_sig_flattening);
1810
1811        // Generate, in the C source file, the raw wasm signature that has the
1812        // canonical ABI.
1813        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        // Perform all lifting/lowering and append it to our src.
1843        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            // optional param pointer sig_flattening
1921            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                    // Handles to imported resources will need to be dropped, if the context
2058                    // they're used in is an export.
2059                    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 observed during lifting an export, that will need to be dropped when the guest
2132    /// function exits.
2133    borrows: Vec<DroppableBorrow>,
2134
2135    /// Forward declarations for temporary storage of borrow copies.
2136    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        // Empty types have no state, so we don't emit stores for them. But we
2219        // do need to keep track of which return variable we're looking at.
2220        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        // Use a stack-based return area for imports, because exports need
2258        // their return area to be live until the post-return call.
2259        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            // Declare a statically-allocated return area.
2269            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            // TODO: checked?
2296            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            // f32/f64 have the same representation in the import type and in C,
2317            // so no conversions necessary.
2318            Instruction::CoreF32FromF32
2319            | Instruction::CoreF64FromF64
2320            | Instruction::F32FromCoreF32
2321            | Instruction::F64FromCoreF64 => {
2322                results.push(operands[0].clone());
2323            }
2324
2325            // TODO: checked
2326            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                    // Here we've received a borrow of a resource which we've exported ourselves, so we can treat
2391                    // it as a raw pointer rather than an opaque handle.
2392                    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                            // Here we've received a borrow of an imported resource, which is the
2407                            // kind we'll need to drop when the exported function is returning.
2408                            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            // TODO: checked
2421            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                // Emit all temporary borrow decls
2979                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    // HHelpers,
3086    // CDefs,
3087    // CFns,
3088    // CHelpers,
3089    // CAdapters,
3090}
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        // Escape C and C++ keywords.
3194        // Source: https://en.cppreference.com/w/cpp/keyword
3195        "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 and err needs to be escaped because they are used as
3294        //  variable names for option and result flattening.
3295        "ret" => "ret_".into(),
3296        "err" => "err_".into(),
3297        s => s.to_snake_case(),
3298    }
3299}
3300
3301const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)";