wit_bindgen_cpp/
lib.rs

1use anyhow::bail;
2use heck::{ToPascalCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
3use std::{
4    collections::{HashMap, HashSet},
5    fmt::{self, Display, Write as FmtWrite},
6    io::{Read, Write},
7    path::PathBuf,
8    process::{Command, Stdio},
9    str::FromStr,
10};
11use symbol_name::{make_external_component, make_external_symbol};
12use wit_bindgen_c::to_c_ident;
13use wit_bindgen_core::{
14    Files, InterfaceGenerator, Source, Types, WorldGenerator,
15    abi::{self, AbiVariant, Bindgen, Bitcast, LiftLower, WasmSignature, WasmType},
16    name_package_module, uwrite, uwriteln,
17    wit_parser::{
18        Alignment, ArchitectureSize, Docs, Function, FunctionKind, Handle, Int, InterfaceId,
19        Resolve, SizeAlign, Stability, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, WorldId,
20        WorldKey,
21    },
22};
23
24// mod wamr;
25mod symbol_name;
26
27pub const RESOURCE_IMPORT_BASE_CLASS_NAME: &str = "ResourceImportBase";
28pub const RESOURCE_EXPORT_BASE_CLASS_NAME: &str = "ResourceExportBase";
29pub const RESOURCE_TABLE_NAME: &str = "ResourceTable";
30pub const OWNED_CLASS_NAME: &str = "Owned";
31pub const POINTER_SIZE_EXPRESSION: &str = "sizeof(void*)";
32
33type CppType = String;
34
35#[derive(Clone, Copy, Debug)]
36enum Flavor {
37    Argument(AbiVariant),
38    Result(AbiVariant),
39    InStruct,
40    BorrowedArgument,
41}
42
43#[derive(Default)]
44struct HighlevelSignature {
45    /// this is a constructor or destructor without a written type
46    // implicit_result: bool, -> empty result
47    const_member: bool,
48    static_member: bool,
49    result: CppType,
50    arguments: Vec<(String, CppType)>,
51    name: String,
52    namespace: Vec<String>,
53    implicit_self: bool,
54    post_return: bool,
55}
56
57// follows https://google.github.io/styleguide/cppguide.html
58
59#[derive(Default)]
60struct Includes {
61    needs_vector: bool,
62    needs_expected: bool,
63    needs_string: bool,
64    needs_string_view: bool,
65    needs_optional: bool,
66    needs_cstring: bool,
67    needs_imported_resources: bool,
68    needs_exported_resources: bool,
69    needs_variant: bool,
70    needs_tuple: bool,
71    needs_assert: bool,
72    needs_bit: bool,
73    needs_span: bool,
74    // needs wit types
75    needs_wit: bool,
76    needs_memory: bool,
77}
78
79#[derive(Default)]
80struct SourceWithState {
81    src: Source,
82    namespace: Vec<String>,
83}
84
85#[derive(Eq, Hash, PartialEq, Clone, Copy, Debug)]
86enum Direction {
87    Import,
88    Export,
89}
90
91#[derive(Default)]
92struct Cpp {
93    opts: Opts,
94    c_src: SourceWithState,
95    h_src: SourceWithState,
96    c_src_head: Source,
97    extern_c_decls: Source,
98    dependencies: Includes,
99    includes: Vec<String>,
100    world: String,
101    world_id: Option<WorldId>,
102    imported_interfaces: HashSet<InterfaceId>,
103    user_class_files: HashMap<String, String>,
104    defined_types: HashSet<(Vec<String>, String)>,
105    types: Types,
106
107    // needed for symmetric disambiguation
108    interface_prefixes: HashMap<(Direction, WorldKey), String>,
109    import_prefix: Option<String>,
110}
111
112#[cfg(feature = "clap")]
113fn parse_with(s: &str) -> Result<(String, String), String> {
114    let (k, v) = s.split_once('=').ok_or_else(|| {
115        format!("expected string of form `<key>=<value>[,<key>=<value>...]`; got `{s}`")
116    })?;
117    Ok((k.to_string(), v.to_string()))
118}
119
120#[derive(Default, Debug, Clone)]
121#[cfg_attr(feature = "clap", derive(clap::Args))]
122pub struct Opts {
123    /// Call clang-format on the generated code
124    #[cfg_attr(feature = "clap", arg(long, default_value_t = bool::default()))]
125    pub format: bool,
126
127    /// Place each interface in its own file,
128    /// this enables sharing bindings across projects
129    #[cfg_attr(feature = "clap", arg(long, default_value_t = bool::default()))]
130    pub split_interfaces: bool,
131
132    /// Optionally prefix any export names with the specified value.
133    ///
134    /// This is useful to avoid name conflicts when testing.
135    #[cfg_attr(feature = "clap", arg(long))]
136    pub export_prefix: Option<String>,
137
138    /// Wrap all C++ classes inside a custom namespace.
139    ///
140    /// This avoids identical names across components, useful for native
141    #[cfg_attr(feature = "clap", arg(long))]
142    pub internal_prefix: Option<String>,
143
144    /// Set API style to symmetric or asymmetric
145    #[cfg_attr(
146        feature = "clap", 
147        arg(
148            long,
149            default_value_t = APIStyle::default(),
150            value_name = "STYLE",
151        ),
152    )]
153    pub api_style: APIStyle,
154
155    /// Whether to generate owning or borrowing type definitions for `record` arguments to imported functions.
156    ///
157    /// Valid values include:
158    ///
159    /// - `owning`: Generated types will be composed entirely of owning fields,
160    ///   regardless of whether they are used as parameters to imports or not.
161    ///
162    /// - `coarse-borrowing`: Generated types used as parameters to imports will be
163    ///   "deeply borrowing", i.e. contain references rather than owned values,
164    ///   so long as they don't contain resources, in which case they will be
165    ///   owning.
166    ///
167    /// - `fine-borrowing": Generated types used as parameters to imports will be
168    ///   "deeply borrowing", i.e. contain references rather than owned values
169    ///   for all fields that are not resources, which will be owning.
170    #[cfg_attr(feature = "clap", arg(long, default_value_t = Ownership::Owning))]
171    pub ownership: Ownership,
172
173    /// Where to place output files
174    #[cfg_attr(feature = "clap", arg(skip))]
175    out_dir: Option<PathBuf>,
176
177    /// Importing wit interface from custom include
178    ///
179    /// Argument must be of the form `k=v` and this option can be passed
180    /// multiple times or one option can be comma separated, for example
181    /// `k1=v1,k2=v2`.
182    #[cfg_attr(feature = "clap", arg(long, value_parser = parse_with, value_delimiter = ','))]
183    pub with: Vec<(String, String)>,
184}
185
186/// Supported API styles for the generated bindings.
187#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
188pub enum APIStyle {
189    /// Imported functions borrow arguments, while exported functions receive owned arguments. Reduces the allocation overhead for the canonical ABI.
190    #[default]
191    Asymmetric,
192    /// Same API for imported and exported functions. Reduces the allocation overhead for symmetric ABI.
193    Symmetric,
194}
195
196impl Display for APIStyle {
197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198        match self {
199            APIStyle::Asymmetric => write!(f, "asymmetric"),
200            APIStyle::Symmetric => write!(f, "symmetric"),
201        }
202    }
203}
204
205impl FromStr for APIStyle {
206    type Err = anyhow::Error;
207
208    fn from_str(s: &str) -> Result<Self, Self::Err> {
209        match s {
210            "asymmetric" => Ok(APIStyle::Asymmetric),
211            "symmetric" => Ok(APIStyle::Symmetric),
212            _ => bail!(
213                "unrecognized API style: `{}`; expected `asymmetric` or `symmetric`",
214                s
215            ),
216        }
217    }
218}
219
220#[derive(Default, Debug, Clone, Copy)]
221pub enum Ownership {
222    /// Generated types will be composed entirely of owning fields, regardless
223    /// of whether they are used as parameters to imports or not.
224    #[default]
225    Owning,
226
227    /// Generated types used as parameters to imports will be "deeply
228    /// borrowing", i.e. contain references rather than owned values when
229    /// applicable.
230    CoarseBorrowing,
231
232    /// Generated types used as parameters to imports will be "deeply
233    /// borrowing", i.e. contain references rather than owned values
234    /// for all fields that are not resources, which will be owning.
235    FineBorrowing,
236}
237
238impl FromStr for Ownership {
239    type Err = String;
240
241    fn from_str(s: &str) -> Result<Self, Self::Err> {
242        match s {
243            "owning" => Ok(Self::Owning),
244            "coarse-borrowing" => Ok(Self::CoarseBorrowing),
245            "fine-borrowing" => Ok(Self::FineBorrowing),
246            _ => Err(format!(
247                "unrecognized ownership: `{s}`; \
248                 expected `owning`, `coarse-borrowing`, or `fine-borrowing`"
249            )),
250        }
251    }
252}
253
254impl fmt::Display for Ownership {
255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256        f.write_str(match self {
257            Ownership::Owning => "owning",
258            Ownership::CoarseBorrowing => "coarse-borrowing",
259            Ownership::FineBorrowing => "fine-borrowing",
260        })
261    }
262}
263
264impl Opts {
265    pub fn build(mut self, out_dir: Option<&PathBuf>) -> Box<dyn WorldGenerator> {
266        let mut r = Cpp::new();
267        self.out_dir = out_dir.cloned();
268        r.opts = self;
269        Box::new(r)
270    }
271
272    fn is_only_handle(&self, variant: AbiVariant) -> bool {
273        !matches!(variant, AbiVariant::GuestExport)
274    }
275
276    fn ptr_type(&self) -> &'static str {
277        "uint8_t*"
278    }
279}
280
281impl Cpp {
282    fn new() -> Cpp {
283        Cpp::default()
284    }
285
286    pub fn is_first_definition(&mut self, ns: &Vec<String>, name: &str) -> bool {
287        let owned = (ns.to_owned(), name.to_owned());
288        if !self.defined_types.contains(&owned) {
289            self.defined_types.insert(owned);
290            true
291        } else {
292            false
293        }
294    }
295
296    fn include(&mut self, s: &str) {
297        self.includes.push(s.to_string());
298    }
299
300    /// Returns true if the function is a fallible constructor.
301    ///
302    /// Fallible constructors are constructors that return `result<T, E>` instead of just `T`.
303    /// In the generated C++ code, these become static factory methods named `Create` that
304    /// return `std::expected<T, E>`, rather than regular constructors.
305    fn is_fallible_constructor(&self, resolve: &Resolve, func: &Function) -> bool {
306        matches!(&func.kind, FunctionKind::Constructor(_))
307            && func.result.as_ref().is_some_and(|ty| {
308                if let Type::Id(id) = ty {
309                    matches!(&resolve.types[*id].kind, TypeDefKind::Result(_))
310                } else {
311                    false
312                }
313            })
314    }
315
316    fn interface<'a>(
317        &'a mut self,
318        resolve: &'a Resolve,
319        name: Option<&'a WorldKey>,
320        in_guest_import: bool,
321        wasm_import_module: Option<String>,
322    ) -> CppInterfaceGenerator<'a> {
323        let mut sizes = SizeAlign::default();
324        sizes.fill(resolve);
325
326        CppInterfaceGenerator {
327            _src: Source::default(),
328            r#gen: self,
329            resolve,
330            interface: None,
331            _name: name,
332            sizes,
333            in_guest_import,
334            wasm_import_module,
335        }
336    }
337
338    fn clang_format(code: &mut String) {
339        let mut child = Command::new("clang-format")
340            .stdin(Stdio::piped())
341            .stdout(Stdio::piped())
342            .spawn()
343            .expect("failed to spawn `clang-format`");
344        child
345            .stdin
346            .take()
347            .unwrap()
348            .write_all(code.as_bytes())
349            .unwrap();
350        code.truncate(0);
351        child.stdout.take().unwrap().read_to_string(code).unwrap();
352        let status = child.wait().unwrap();
353        assert!(status.success());
354    }
355
356    fn perform_cast(&mut self, op: &str, cast: &Bitcast) -> String {
357        match cast {
358            Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
359                self.dependencies.needs_bit = true;
360                format!("std::bit_cast<float, int32_t>({})", op)
361            }
362            Bitcast::F32ToI32 | Bitcast::F32ToI64 => {
363                self.dependencies.needs_bit = true;
364                format!("std::bit_cast<int32_t, float>({})", op)
365            }
366            Bitcast::I64ToF64 => {
367                self.dependencies.needs_bit = true;
368                format!("std::bit_cast<double, int64_t>({})", op)
369            }
370            Bitcast::F64ToI64 => {
371                self.dependencies.needs_bit = true;
372                format!("std::bit_cast<int64_t, double>({})", op)
373            }
374            Bitcast::I32ToI64 | Bitcast::LToI64 | Bitcast::PToP64 => {
375                format!("(int64_t) {}", op)
376            }
377            Bitcast::I64ToI32 | Bitcast::PToI32 | Bitcast::LToI32 => {
378                format!("(int32_t) {}", op)
379            }
380            Bitcast::P64ToI64 | Bitcast::None | Bitcast::I64ToP64 => op.to_string(),
381            Bitcast::P64ToP | Bitcast::I32ToP | Bitcast::LToP => {
382                format!("(uint8_t*) {}", op)
383            }
384            Bitcast::PToL | Bitcast::I32ToL | Bitcast::I64ToL => {
385                format!("(size_t) {}", op)
386            }
387            Bitcast::Sequence(sequence) => {
388                let [first, second] = &**sequence;
389                let inner = self.perform_cast(op, first);
390                self.perform_cast(&inner, second)
391            }
392        }
393    }
394
395    fn finish_includes(&mut self) {
396        self.include("<cstdint>");
397        self.include("<utility>"); // for std::move
398        if self.dependencies.needs_string {
399            self.include("<string>");
400        }
401        if self.dependencies.needs_string_view {
402            self.include("<string_view>");
403        }
404        if self.dependencies.needs_vector {
405            self.include("<vector>");
406        }
407        if self.dependencies.needs_expected {
408            self.include("<expected>");
409        }
410        if self.dependencies.needs_optional {
411            self.include("<optional>");
412        }
413        if self.dependencies.needs_cstring {
414            self.include("<cstring>");
415        }
416        if self.dependencies.needs_imported_resources {
417            self.include("<cassert>");
418        }
419        if self.dependencies.needs_exported_resources {
420            self.include("<map>");
421        }
422        if self.dependencies.needs_variant {
423            self.include("<variant>");
424        }
425        if self.dependencies.needs_tuple {
426            self.include("<tuple>");
427        }
428        if self.dependencies.needs_wit {
429            self.include("\"wit.h\"");
430        }
431        if self.dependencies.needs_memory {
432            self.include("<memory>");
433        }
434        if self.dependencies.needs_bit {
435            self.include("<bit>");
436        }
437    }
438
439    fn start_new_file(&mut self, condition: Option<bool>) -> FileContext {
440        if condition == Some(true) || self.opts.split_interfaces {
441            FileContext {
442                includes: std::mem::take(&mut self.includes),
443                src: std::mem::take(&mut self.h_src),
444                dependencies: std::mem::take(&mut self.dependencies),
445            }
446        } else {
447            Default::default()
448        }
449    }
450
451    fn finish_file(&mut self, namespace: &[String], store: FileContext) {
452        if !store.src.src.is_empty() {
453            let mut header = String::default();
454            self.finish_includes();
455            self.h_src.change_namespace(&[]);
456            uwriteln!(header, "#pragma once");
457            for include in self.includes.iter() {
458                uwriteln!(header, "#include {include}");
459            }
460            header.push_str(&self.h_src.src);
461            let mut filename = namespace.join("-");
462            filename.push_str(".h");
463            if self.opts.format {
464                Self::clang_format(&mut header);
465            }
466            self.user_class_files.insert(filename.clone(), header);
467
468            let _ = std::mem::replace(&mut self.includes, store.includes);
469            let _ = std::mem::replace(&mut self.h_src, store.src);
470            let _ = std::mem::replace(&mut self.dependencies, store.dependencies);
471            self.includes.push(String::from("\"") + &filename + "\"");
472        }
473    }
474}
475
476#[derive(Default)]
477struct FileContext {
478    includes: Vec<String>,
479    src: SourceWithState,
480    dependencies: Includes,
481}
482
483impl WorldGenerator for Cpp {
484    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
485        let name = &resolve.worlds[world].name;
486        self.world = name.to_string();
487        self.types.analyze(resolve);
488        self.world_id = Some(world);
489        uwriteln!(
490            self.c_src_head,
491            r#"#include "{}_cpp.h"
492            #include <cstdlib> // realloc
493
494            extern "C" void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size);
495
496            __attribute__((__weak__, __export_name__("cabi_realloc")))
497            void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) {{
498                (void) old_size;
499                if (new_size == 0) return (void*) align;
500                void *ret = realloc(ptr, new_size);
501                if (!ret) abort();
502                return ret;
503            }}
504
505            "#,
506            self.world.to_snake_case(),
507        );
508    }
509
510    fn import_interface(
511        &mut self,
512        resolve: &Resolve,
513        name: &WorldKey,
514        id: InterfaceId,
515        _files: &mut Files,
516    ) -> anyhow::Result<()> {
517        self.imported_interfaces.insert(id);
518
519        let full_name = resolve.name_world_key(name);
520        match self.opts.with.iter().find(|e| e.0 == full_name) {
521            None => {
522                if let Some(prefix) = self
523                    .interface_prefixes
524                    .get(&(Direction::Import, name.clone()))
525                {
526                    self.import_prefix = Some(prefix.clone());
527                }
528
529                let store = self.start_new_file(None);
530                let wasm_import_module = resolve.name_world_key(name);
531                let binding = Some(name);
532                let mut r#gen = self.interface(resolve, binding, true, Some(wasm_import_module));
533                r#gen.interface = Some(id);
534                r#gen.types(id);
535                let namespace =
536                    namespace(resolve, &TypeOwner::Interface(id), false, &r#gen.r#gen.opts);
537
538                for (_name, func) in resolve.interfaces[id].functions.iter() {
539                    if matches!(func.kind, FunctionKind::Freestanding) {
540                        r#gen.r#gen.h_src.change_namespace(&namespace);
541                        r#gen.generate_function(
542                            func,
543                            &TypeOwner::Interface(id),
544                            AbiVariant::GuestImport,
545                        );
546                    }
547                }
548                self.finish_file(&namespace, store);
549            }
550            Some((_, val)) => {
551                let with_quotes = format!("\"{val}\"");
552                if !self.includes.contains(&with_quotes) {
553                    self.includes.push(with_quotes);
554                }
555            }
556        }
557        let _ = self.import_prefix.take();
558        Ok(())
559    }
560
561    fn export_interface(
562        &mut self,
563        resolve: &Resolve,
564        name: &WorldKey,
565        id: InterfaceId,
566        _files: &mut Files,
567    ) -> anyhow::Result<()> {
568        let old_prefix = self.opts.export_prefix.clone();
569        if let Some(prefix) = self
570            .interface_prefixes
571            .get(&(Direction::Export, name.clone()))
572        {
573            self.opts.export_prefix =
574                Some(prefix.clone() + old_prefix.as_ref().unwrap_or(&String::new()));
575        }
576        let store = self.start_new_file(None);
577        self.h_src
578            .src
579            .push_str(&format!("// export_interface {name:?}\n"));
580        self.imported_interfaces.remove(&id);
581        let wasm_import_module = resolve.name_world_key(name);
582        let binding = Some(name);
583        let mut r#gen = self.interface(resolve, binding, false, Some(wasm_import_module));
584        r#gen.interface = Some(id);
585        r#gen.types(id);
586        let namespace = namespace(resolve, &TypeOwner::Interface(id), true, &r#gen.r#gen.opts);
587
588        for (_name, func) in resolve.interfaces[id].functions.iter() {
589            if matches!(func.kind, FunctionKind::Freestanding) {
590                r#gen.r#gen.h_src.change_namespace(&namespace);
591                r#gen.generate_function(func, &TypeOwner::Interface(id), AbiVariant::GuestExport);
592            }
593        }
594        self.finish_file(&namespace, store);
595        self.opts.export_prefix = old_prefix;
596        Ok(())
597    }
598
599    fn import_funcs(
600        &mut self,
601        resolve: &Resolve,
602        world: WorldId,
603        funcs: &[(&str, &Function)],
604        _files: &mut Files,
605    ) {
606        let name = WorldKey::Name("$root".to_string()); //WorldKey::Name(resolve.worlds[world].name.clone());
607        let wasm_import_module = resolve.name_world_key(&name);
608        let binding = Some(name);
609        let mut r#gen = self.interface(resolve, binding.as_ref(), true, Some(wasm_import_module));
610        let namespace = namespace(resolve, &TypeOwner::World(world), false, &r#gen.r#gen.opts);
611
612        for (_name, func) in funcs.iter() {
613            if matches!(func.kind, FunctionKind::Freestanding) {
614                r#gen.r#gen.h_src.change_namespace(&namespace);
615                r#gen.generate_function(func, &TypeOwner::World(world), AbiVariant::GuestImport);
616            }
617        }
618    }
619
620    fn export_funcs(
621        &mut self,
622        resolve: &Resolve,
623        world: WorldId,
624        funcs: &[(&str, &Function)],
625        _files: &mut Files,
626    ) -> anyhow::Result<()> {
627        let name = WorldKey::Name(resolve.worlds[world].name.clone());
628        let binding = Some(name);
629        let mut r#gen = self.interface(resolve, binding.as_ref(), false, None);
630        let namespace = namespace(resolve, &TypeOwner::World(world), true, &r#gen.r#gen.opts);
631
632        for (_name, func) in funcs.iter() {
633            if matches!(func.kind, FunctionKind::Freestanding) {
634                r#gen.r#gen.h_src.change_namespace(&namespace);
635                r#gen.generate_function(func, &TypeOwner::World(world), AbiVariant::GuestExport);
636            }
637        }
638        Ok(())
639    }
640
641    fn import_types(
642        &mut self,
643        resolve: &Resolve,
644        _world: WorldId,
645        types: &[(&str, TypeId)],
646        _files: &mut Files,
647    ) {
648        let mut r#gen = self.interface(resolve, None, true, Some("$root".to_string()));
649        for (name, id) in types.iter() {
650            r#gen.define_type(name, *id);
651        }
652    }
653
654    fn finish(
655        &mut self,
656        resolve: &Resolve,
657        world_id: WorldId,
658        files: &mut Files,
659    ) -> std::result::Result<(), anyhow::Error> {
660        let world = &resolve.worlds[world_id];
661        let snake = world.name.to_snake_case();
662        let linking_symbol = wit_bindgen_c::component_type_object::linking_symbol(&world.name);
663
664        let mut h_str = SourceWithState::default();
665        let mut c_str = SourceWithState::default();
666
667        let version = env!("CARGO_PKG_VERSION");
668        uwriteln!(
669            h_str.src,
670            "// Generated by `wit-bindgen` {version}. DO NOT EDIT!"
671        );
672
673        uwrite!(
674            h_str.src,
675            "#ifndef __CPP_GUEST_BINDINGS_{0}_H
676            #define __CPP_GUEST_BINDINGS_{0}_H\n",
677            world.name.to_shouty_snake_case(),
678        );
679        self.finish_includes();
680
681        for include in self.includes.iter() {
682            uwriteln!(h_str.src, "#include {include}");
683        }
684
685        uwriteln!(
686            c_str.src,
687            "// Generated by `wit-bindgen` {version}. DO NOT EDIT!"
688        );
689        uwriteln!(
690            c_str.src,
691            "\n// Ensure that the *_component_type.o object is linked in"
692        );
693        uwrite!(
694            c_str.src,
695            "#ifdef __wasm32__
696                   extern \"C\" void {linking_symbol}(void);
697                   __attribute__((used))
698                   void {linking_symbol}_public_use_in_this_compilation_unit(void) {{
699                       {linking_symbol}();
700                   }}
701                   #endif
702               ",
703        );
704        if self.dependencies.needs_assert {
705            uwriteln!(c_str.src, "#include <assert.h>");
706        }
707
708        h_str.change_namespace(&Vec::default());
709
710        self.c_src.change_namespace(&Vec::default());
711        c_str.src.push_str(&self.c_src_head);
712        c_str.src.push_str(&self.extern_c_decls);
713        c_str.src.push_str(&self.c_src.src);
714        self.h_src.change_namespace(&Vec::default());
715        h_str.src.push_str(&self.h_src.src);
716
717        uwriteln!(c_str.src, "\n// Component Adapters");
718
719        uwriteln!(
720            h_str.src,
721            "
722            #endif"
723        );
724
725        if self.opts.format {
726            Self::clang_format(c_str.src.as_mut_string());
727            Self::clang_format(h_str.src.as_mut_string());
728        }
729
730        files.push(&format!("{snake}.cpp"), c_str.src.as_bytes());
731        files.push(&format!("{snake}_cpp.h"), h_str.src.as_bytes());
732        for (name, content) in self.user_class_files.iter() {
733            // if the user class file exists create an updated .template
734            let dst = match &self.opts.out_dir {
735                Some(path) => path.join(name),
736                None => name.into(),
737            };
738            if std::path::Path::exists(&dst) {
739                files.push(&(String::from(name) + ".template"), content.as_bytes());
740            } else {
741                files.push(name, content.as_bytes());
742            }
743        }
744        files.push(
745            &format!("{snake}_component_type.o",),
746            wit_bindgen_c::component_type_object::object(
747                resolve,
748                world_id,
749                &world.name,
750                wit_component::StringEncoding::UTF8,
751                None,
752            )
753            .unwrap()
754            .as_slice(),
755        );
756
757        if self.dependencies.needs_wit {
758            files.push("wit.h", include_bytes!("../helper-types/wit.h"));
759        }
760        Ok(())
761    }
762}
763
764// determine namespace (for the lifted C++ function)
765fn namespace(resolve: &Resolve, owner: &TypeOwner, guest_export: bool, opts: &Opts) -> Vec<String> {
766    let mut result = Vec::default();
767    if let Some(prefix) = &opts.internal_prefix {
768        result.push(prefix.clone());
769    }
770    if guest_export {
771        result.push(String::from("exports"));
772    }
773    match owner {
774        TypeOwner::World(w) => result.push(to_c_ident(&resolve.worlds[*w].name)),
775        TypeOwner::Interface(i) => {
776            let iface = &resolve.interfaces[*i];
777            let pkg_id = iface.package.unwrap();
778            let pkg = &resolve.packages[pkg_id];
779            result.push(to_c_ident(&pkg.name.namespace));
780            // Use name_package_module to get version-specific package names
781            result.push(to_c_ident(&name_package_module(resolve, pkg_id)));
782            if let Some(name) = &iface.name {
783                result.push(to_c_ident(name));
784            }
785        }
786        TypeOwner::None => (),
787    }
788    result
789}
790
791impl SourceWithState {
792    fn change_namespace(&mut self, target: &[String]) {
793        let mut same = 0;
794        // itertools::fold_while?
795        for (a, b) in self.namespace.iter().zip(target.iter()) {
796            if a == b {
797                same += 1;
798            } else {
799                break;
800            }
801        }
802        for _i in same..self.namespace.len() {
803            uwrite!(self.src, "}}\n");
804        }
805        self.namespace.truncate(same);
806        for i in target.iter().skip(same) {
807            uwrite!(self.src, "namespace {} {{\n", i);
808            self.namespace.push(i.clone());
809        }
810    }
811
812    fn qualify(&mut self, target: &[String]) {
813        let mut same = 0;
814        // itertools::fold_while?
815        for (a, b) in self.namespace.iter().zip(target.iter()) {
816            if a == b {
817                same += 1;
818            } else {
819                break;
820            }
821        }
822        if same == 0 && !target.is_empty() {
823            // if the root namespace exists below the current namespace we need to start at root
824            // Also ensure absolute qualification when crossing from exports to imports
825            if self.namespace.contains(target.first().unwrap())
826                || (self.namespace.first().map(|s| s.as_str()) == Some("exports")
827                    && target.first().map(|s| s.as_str()) != Some("exports"))
828            {
829                self.src.push_str("::");
830            }
831        }
832        if same == target.len() && self.namespace.len() != target.len() && same > 0 {
833            // namespace is parent, qualify at least one namespace (and cross fingers)
834            uwrite!(self.src, "{}::", target[same - 1]);
835        } else {
836            for i in target.iter().skip(same) {
837                uwrite!(self.src, "{i}::");
838            }
839        }
840    }
841}
842
843struct CppInterfaceGenerator<'a> {
844    _src: Source,
845    r#gen: &'a mut Cpp,
846    resolve: &'a Resolve,
847    interface: Option<InterfaceId>,
848    _name: Option<&'a WorldKey>,
849    sizes: SizeAlign,
850    in_guest_import: bool,
851    pub wasm_import_module: Option<String>,
852}
853
854impl CppInterfaceGenerator<'_> {
855    fn types(&mut self, iface: InterfaceId) {
856        let iface_data = &self.resolve().interfaces[iface];
857
858        // First pass: emit forward declarations for all resources
859        // This ensures resources can reference each other in method signatures
860        for (name, id) in iface_data.types.iter() {
861            let ty = &self.resolve().types[*id];
862            if matches!(&ty.kind, TypeDefKind::Resource) {
863                let pascal = name.to_upper_camel_case();
864                let guest_import = self.r#gen.imported_interfaces.contains(&iface);
865                let namespc = namespace(self.resolve, &ty.owner, !guest_import, &self.r#gen.opts);
866                self.r#gen.h_src.change_namespace(&namespc);
867                uwriteln!(self.r#gen.h_src.src, "class {pascal};");
868            }
869        }
870
871        // Second pass: emit full type definitions
872        for (name, id) in iface_data.types.iter() {
873            self.define_type(name, *id);
874        }
875    }
876
877    fn define_type(&mut self, name: &str, id: TypeId) {
878        let ty = &self.resolve().types[id];
879        match &ty.kind {
880            TypeDefKind::Record(record) => self.type_record(id, name, record, &ty.docs),
881            TypeDefKind::Resource => self.type_resource(id, name, &ty.docs),
882            TypeDefKind::Flags(flags) => self.type_flags(id, name, flags, &ty.docs),
883            TypeDefKind::Tuple(tuple) => self.type_tuple(id, name, tuple, &ty.docs),
884            TypeDefKind::Enum(enum_) => self.type_enum(id, name, enum_, &ty.docs),
885            TypeDefKind::Variant(variant) => self.type_variant(id, name, variant, &ty.docs),
886            TypeDefKind::Option(t) => self.type_option(id, name, t, &ty.docs),
887            TypeDefKind::Result(r) => self.type_result(id, name, r, &ty.docs),
888            TypeDefKind::List(t) => self.type_list(id, name, t, &ty.docs),
889            TypeDefKind::Type(t) => self.type_alias(id, name, t, &ty.docs),
890            TypeDefKind::Future(_) => todo!("generate for future"),
891            TypeDefKind::Stream(_) => todo!("generate for stream"),
892            TypeDefKind::Handle(_) => todo!("generate for handle"),
893            TypeDefKind::FixedSizeList(_, _) => todo!(),
894            TypeDefKind::Unknown => unreachable!(),
895        }
896    }
897
898    /// This describes the C++ side name
899    fn func_namespace_name(
900        &self,
901        func: &Function,
902        guest_export: bool,
903        cpp_file: bool,
904    ) -> (Vec<String>, String) {
905        let (object, owner) = match &func.kind {
906            FunctionKind::Freestanding => None,
907            FunctionKind::Method(i) => Some(i),
908            FunctionKind::Static(i) => Some(i),
909            FunctionKind::Constructor(i) => Some(i),
910            FunctionKind::AsyncFreestanding => todo!(),
911            FunctionKind::AsyncMethod(_id) => todo!(),
912            FunctionKind::AsyncStatic(_id) => todo!(),
913        }
914        .map(|i| {
915            let ty = &self.resolve.types[*i];
916            (ty.name.as_ref().unwrap().to_pascal_case(), ty.owner)
917        })
918        .unwrap_or((
919            Default::default(),
920            self.interface
921                .map(TypeOwner::Interface)
922                .unwrap_or(TypeOwner::World(self.r#gen.world_id.unwrap())),
923        ));
924        let mut namespace = namespace(self.resolve, &owner, guest_export, &self.r#gen.opts);
925        let is_drop = is_special_method(func);
926        let func_name_h = if !matches!(&func.kind, FunctionKind::Freestanding) {
927            namespace.push(object.clone());
928            if let FunctionKind::Constructor(_i) = &func.kind {
929                // Fallible constructors return result<T, E> and are static factory methods
930                let is_fallible_constructor =
931                    self.r#gen.is_fallible_constructor(self.resolve, func);
932
933                if is_fallible_constructor {
934                    String::from("Create")
935                } else if guest_export && cpp_file {
936                    String::from("New")
937                } else {
938                    object.clone()
939                }
940            } else {
941                match is_drop {
942                    SpecialMethod::ResourceDrop => {
943                        if guest_export {
944                            "ResourceDrop".to_string()
945                        } else {
946                            "~".to_string() + &object
947                        }
948                    }
949                    SpecialMethod::Dtor => "Dtor".to_string(),
950                    SpecialMethod::ResourceNew => "ResourceNew".to_string(),
951                    SpecialMethod::ResourceRep => "ResourceRep".to_string(),
952                    SpecialMethod::Allocate => "New".to_string(),
953                    SpecialMethod::None => func.item_name().to_pascal_case(),
954                }
955            }
956        } else {
957            func.name.to_pascal_case()
958        };
959        (namespace, func_name_h)
960    }
961
962    // print the signature of the guest export (lowered (wasm) function calling into highlevel)
963    fn print_export_signature(&mut self, func: &Function, variant: AbiVariant) -> Vec<String> {
964        let is_drop = is_special_method(func);
965        let id_type = WasmType::I32;
966        let signature = match is_drop {
967            SpecialMethod::ResourceDrop => WasmSignature {
968                params: vec![id_type],
969                results: Vec::new(),
970                indirect_params: false,
971                retptr: false,
972            },
973            SpecialMethod::ResourceRep => WasmSignature {
974                params: vec![id_type],
975                results: vec![WasmType::Pointer],
976                indirect_params: false,
977                retptr: false,
978            },
979            SpecialMethod::Dtor => WasmSignature {
980                params: vec![WasmType::Pointer],
981                results: Vec::new(),
982                indirect_params: false,
983                retptr: false,
984            },
985            SpecialMethod::ResourceNew => WasmSignature {
986                params: vec![WasmType::Pointer],
987                results: vec![id_type],
988                indirect_params: false,
989                retptr: false,
990            },
991            SpecialMethod::None => {
992                // TODO perhaps remember better names for the arguments
993                self.resolve.wasm_signature(variant, func)
994            }
995            SpecialMethod::Allocate => WasmSignature {
996                params: vec![],
997                results: vec![],
998                indirect_params: false,
999                retptr: false,
1000            },
1001        };
1002        let mut module_name = self.wasm_import_module.clone();
1003        let symbol_variant = variant;
1004        if matches!(variant, AbiVariant::GuestExport)
1005            && matches!(
1006                is_drop,
1007                SpecialMethod::ResourceNew
1008                    | SpecialMethod::ResourceDrop
1009                    | SpecialMethod::ResourceRep
1010            )
1011        {
1012            module_name = Some(String::from("[export]") + &module_name.unwrap());
1013        }
1014        let func_name = func.name.clone();
1015        let module_prefix = module_name.as_ref().map_or(String::default(), |name| {
1016            let mut res = name.clone();
1017            res.push('#');
1018            res
1019        });
1020        uwriteln!(
1021            self.r#gen.c_src.src,
1022            r#"extern "C" __attribute__((__export_name__("{module_prefix}{func_name}")))"#
1023        );
1024        let return_via_pointer = false;
1025        self.r#gen
1026            .c_src
1027            .src
1028            .push_str(if signature.results.is_empty() || return_via_pointer {
1029                "void"
1030            } else {
1031                wit_bindgen_c::wasm_type(signature.results[0])
1032            });
1033        self.r#gen.c_src.src.push_str(" ");
1034        let export_name = match module_name {
1035            Some(ref module_name) => make_external_symbol(module_name, &func_name, symbol_variant),
1036            None => make_external_component(&func_name),
1037        };
1038        // Add prefix to C ABI export functions to avoid conflicts with C++ namespaces
1039        self.r#gen.c_src.src.push_str("__wasm_export_");
1040        if let Some(prefix) = self.r#gen.opts.export_prefix.as_ref() {
1041            self.r#gen.c_src.src.push_str(prefix);
1042        }
1043        self.r#gen.c_src.src.push_str(&export_name);
1044        self.r#gen.c_src.src.push_str("(");
1045        let mut first_arg = true;
1046        let mut params = Vec::new();
1047        for (n, ty) in signature.params.iter().enumerate() {
1048            let name = format!("arg{n}");
1049            if !first_arg {
1050                self.r#gen.c_src.src.push_str(", ");
1051            } else {
1052                first_arg = false;
1053            }
1054            self.r#gen.c_src.src.push_str(wit_bindgen_c::wasm_type(*ty));
1055            self.r#gen.c_src.src.push_str(" ");
1056            self.r#gen.c_src.src.push_str(&name);
1057            params.push(name);
1058        }
1059        if return_via_pointer {
1060            if !first_arg {
1061                self.r#gen.c_src.src.push_str(", ");
1062            }
1063            self.r#gen.c_src.src.push_str(self.r#gen.opts.ptr_type());
1064            self.r#gen.c_src.src.push_str(" resultptr");
1065            params.push("resultptr".into());
1066        }
1067        self.r#gen.c_src.src.push_str(")\n");
1068        params
1069    }
1070
1071    fn high_level_signature(
1072        &mut self,
1073        func: &Function,
1074        abi_variant: AbiVariant,
1075        outer_namespace: &[String],
1076    ) -> HighlevelSignature {
1077        let mut res = HighlevelSignature::default();
1078
1079        let (namespace, func_name_h) =
1080            self.func_namespace_name(func, matches!(abi_variant, AbiVariant::GuestExport), false);
1081        res.name = func_name_h;
1082        res.namespace = namespace;
1083        let is_drop = is_special_method(func);
1084        // we might want to separate c_sig and h_sig
1085        // let mut sig = String::new();
1086
1087        // Check if this is a fallible constructor (returns result<T, E>)
1088        let is_fallible_constructor = self.r#gen.is_fallible_constructor(self.resolve, func);
1089
1090        // not for ctor nor imported dtor on guest (except fallible constructors)
1091        if (!matches!(&func.kind, FunctionKind::Constructor(_)) || is_fallible_constructor)
1092            && !(matches!(is_drop, SpecialMethod::ResourceDrop)
1093                && matches!(abi_variant, AbiVariant::GuestImport))
1094        {
1095            if matches!(is_drop, SpecialMethod::Allocate) {
1096                res.result.push_str("Owned");
1097            } else if let Some(ty) = &func.result {
1098                res.result.push_str(
1099                    &(self.type_name(ty, outer_namespace, Flavor::Result(abi_variant))
1100                        + if matches!(is_drop, SpecialMethod::ResourceRep) {
1101                            "*"
1102                        } else {
1103                            ""
1104                        }),
1105                );
1106            } else {
1107                res.result = "void".into();
1108            }
1109            if matches!(abi_variant, AbiVariant::GuestExport)
1110                && abi::guest_export_needs_post_return(self.resolve, func)
1111            {
1112                res.post_return = true;
1113            }
1114        }
1115        if (matches!(func.kind, FunctionKind::Static(_)) || is_fallible_constructor)
1116            && !(matches!(&is_drop, SpecialMethod::ResourceDrop)
1117                && matches!(abi_variant, AbiVariant::GuestImport))
1118        {
1119            res.static_member = true;
1120        }
1121        for (i, (name, param)) in func.params.iter().enumerate() {
1122            if i == 0
1123                && name == "self"
1124                && (matches!(&func.kind, FunctionKind::Method(_))
1125                    || (matches!(&is_drop, SpecialMethod::ResourceDrop)
1126                        && matches!(abi_variant, AbiVariant::GuestImport)))
1127            {
1128                res.implicit_self = true;
1129                continue;
1130            }
1131            let is_pointer = if i == 0
1132                && name == "self"
1133                && matches!(&is_drop, SpecialMethod::Dtor | SpecialMethod::ResourceNew)
1134                && matches!(abi_variant, AbiVariant::GuestExport)
1135            {
1136                "*"
1137            } else {
1138                ""
1139            };
1140            res.arguments.push((
1141                to_c_ident(name),
1142                self.type_name(param, &res.namespace, Flavor::Argument(abi_variant)) + is_pointer,
1143            ));
1144        }
1145        // default to non-const when exporting a method
1146        let import = matches!(abi_variant, AbiVariant::GuestImport);
1147        if matches!(func.kind, FunctionKind::Method(_)) && import {
1148            res.const_member = true;
1149        }
1150        res
1151    }
1152
1153    fn print_signature(
1154        &mut self,
1155        func: &Function,
1156        variant: AbiVariant,
1157        import: bool,
1158    ) -> Vec<String> {
1159        let is_special = is_special_method(func);
1160        let from_namespace = self.r#gen.h_src.namespace.clone();
1161        let cpp_sig = self.high_level_signature(func, variant, &from_namespace);
1162        if cpp_sig.static_member {
1163            self.r#gen.h_src.src.push_str("static ");
1164        }
1165        self.r#gen.h_src.src.push_str(&cpp_sig.result);
1166        if !cpp_sig.result.is_empty() {
1167            self.r#gen.h_src.src.push_str(" ");
1168        }
1169        self.r#gen.h_src.src.push_str(&cpp_sig.name);
1170        self.r#gen.h_src.src.push_str("(");
1171        for (num, (arg, typ)) in cpp_sig.arguments.iter().enumerate() {
1172            if num > 0 {
1173                self.r#gen.h_src.src.push_str(", ");
1174            }
1175            self.r#gen.h_src.src.push_str(typ);
1176            self.r#gen.h_src.src.push_str(" ");
1177            self.r#gen.h_src.src.push_str(arg);
1178        }
1179        self.r#gen.h_src.src.push_str(")");
1180        if cpp_sig.const_member {
1181            self.r#gen.h_src.src.push_str(" const");
1182        }
1183        match (&is_special, false, &variant) {
1184            (SpecialMethod::Allocate, _, _) => {
1185                uwriteln!(
1186                    self.r#gen.h_src.src,
1187                    "{{\
1188                        return {OWNED_CLASS_NAME}(new {}({}));\
1189                    }}",
1190                    cpp_sig.namespace.last().unwrap(), //join("::"),
1191                    cpp_sig
1192                        .arguments
1193                        .iter()
1194                        .map(|(arg, _)| format!("std::move({})", arg))
1195                        .collect::<Vec<_>>()
1196                        .join(", ")
1197                );
1198                // body is inside the header
1199                return Vec::default();
1200            }
1201            (SpecialMethod::Dtor, _, _ /*AbiVariant::GuestImport*/)
1202            | (SpecialMethod::ResourceDrop, true, _) => {
1203                uwriteln!(
1204                    self.r#gen.h_src.src,
1205                    "{{\
1206                        delete {};\
1207                    }}",
1208                    cpp_sig.arguments.first().unwrap().0
1209                );
1210            }
1211            _ => self.r#gen.h_src.src.push_str(";\n"),
1212        }
1213
1214        // we want to separate the lowered signature (wasm) and the high level signature
1215        if !import
1216            && !matches!(
1217                &is_special,
1218                SpecialMethod::ResourceDrop
1219                    | SpecialMethod::ResourceNew
1220                    | SpecialMethod::ResourceRep
1221            )
1222        {
1223            self.print_export_signature(func, variant)
1224        } else {
1225            // recalulate with c file namespace
1226            let c_namespace = self.r#gen.c_src.namespace.clone();
1227            let cpp_sig = self.high_level_signature(func, variant, &c_namespace);
1228            let mut params = Vec::new();
1229            self.r#gen.c_src.src.push_str(&cpp_sig.result);
1230            if !cpp_sig.result.is_empty() {
1231                self.r#gen.c_src.src.push_str(" ");
1232            }
1233            self.r#gen.c_src.qualify(&cpp_sig.namespace);
1234            self.r#gen.c_src.src.push_str(&cpp_sig.name);
1235            self.r#gen.c_src.src.push_str("(");
1236            if cpp_sig.implicit_self {
1237                params.push("(*this)".into());
1238            }
1239            for (num, (arg, typ)) in cpp_sig.arguments.iter().enumerate() {
1240                if num > 0 {
1241                    self.r#gen.c_src.src.push_str(", ");
1242                }
1243                self.r#gen.c_src.src.push_str(typ);
1244                self.r#gen.c_src.src.push_str(" ");
1245                self.r#gen.c_src.src.push_str(arg);
1246                params.push(arg.clone());
1247            }
1248            self.r#gen.c_src.src.push_str(")");
1249            if cpp_sig.const_member {
1250                self.r#gen.c_src.src.push_str(" const");
1251            }
1252            self.r#gen.c_src.src.push_str("\n");
1253            params
1254        }
1255    }
1256
1257    fn generate_function(&mut self, func: &Function, owner: &TypeOwner, variant: AbiVariant) {
1258        fn class_namespace(
1259            cifg: &CppInterfaceGenerator,
1260            func: &Function,
1261            variant: AbiVariant,
1262        ) -> Vec<String> {
1263            let owner = &cifg.resolve.types[match &func.kind {
1264                FunctionKind::Static(id) => *id,
1265                _ => panic!("special func should be static"),
1266            }];
1267            let mut namespace = namespace(
1268                cifg.resolve,
1269                &owner.owner,
1270                matches!(variant, AbiVariant::GuestExport),
1271                &cifg.r#gen.opts,
1272            );
1273            namespace.push(owner.name.as_ref().unwrap().to_upper_camel_case());
1274            namespace
1275        }
1276
1277        let export = match variant {
1278            AbiVariant::GuestImport => false,
1279            AbiVariant::GuestExport => true,
1280            AbiVariant::GuestImportAsync => todo!(),
1281            AbiVariant::GuestExportAsync => todo!(),
1282            AbiVariant::GuestExportAsyncStackful => todo!(),
1283        };
1284        let params = self.print_signature(func, variant, !export);
1285        let special = is_special_method(func);
1286        if !matches!(special, SpecialMethod::Allocate) {
1287            self.r#gen.c_src.src.push_str("{\n");
1288            let needs_dealloc = if self.r#gen.opts.api_style == APIStyle::Symmetric
1289                && matches!(variant, AbiVariant::GuestExport)
1290            {
1291                self.r#gen
1292                    .c_src
1293                    .src
1294                    .push_str("std::vector<void*> _deallocate;\n");
1295                self.r#gen.dependencies.needs_vector = true;
1296                true
1297            } else {
1298                false
1299            };
1300            let lift_lower = if export {
1301                LiftLower::LiftArgsLowerResults
1302            } else {
1303                LiftLower::LowerArgsLiftResults
1304            };
1305            match is_special_method(func) {
1306                SpecialMethod::ResourceDrop => match lift_lower {
1307                    LiftLower::LiftArgsLowerResults => {
1308                        let module_name =
1309                            String::from("[export]") + &self.wasm_import_module.clone().unwrap();
1310                        let wasm_sig =
1311                            self.declare_import(&module_name, &func.name, &[WasmType::I32], &[]);
1312                        uwriteln!(
1313                            self.r#gen.c_src.src,
1314                            "{wasm_sig}({});",
1315                            func.params.first().unwrap().0
1316                        );
1317                    }
1318                    LiftLower::LowerArgsLiftResults => {
1319                        let module_name = self.wasm_import_module.clone().unwrap();
1320                        let name =
1321                            self.declare_import(&module_name, &func.name, &[WasmType::I32], &[]);
1322                        uwriteln!(
1323                            self.r#gen.c_src.src,
1324                            "   if (handle>=0) {{
1325                                {name}(handle);
1326                            }}"
1327                        );
1328                    }
1329                },
1330                SpecialMethod::Dtor => {
1331                    let classname = class_namespace(self, func, variant).join("::");
1332                    uwriteln!(self.r#gen.c_src.src, "(({classname}*)arg0)->handle=-1;");
1333                    uwriteln!(self.r#gen.c_src.src, "{0}::Dtor(({0}*)arg0);", classname);
1334                }
1335                SpecialMethod::ResourceNew => {
1336                    let module_name =
1337                        String::from("[export]") + &self.wasm_import_module.clone().unwrap();
1338                    let wasm_sig = self.declare_import(
1339                        &module_name,
1340                        &func.name,
1341                        &[WasmType::Pointer],
1342                        &[WasmType::I32],
1343                    );
1344                    uwriteln!(
1345                        self.r#gen.c_src.src,
1346                        "return {wasm_sig}(({}){});",
1347                        self.r#gen.opts.ptr_type(),
1348                        func.params.first().unwrap().0
1349                    );
1350                }
1351                SpecialMethod::ResourceRep => {
1352                    let module_name =
1353                        String::from("[export]") + &self.wasm_import_module.clone().unwrap();
1354                    let wasm_sig = self.declare_import(
1355                        &module_name,
1356                        &func.name,
1357                        &[WasmType::I32],
1358                        &[WasmType::Pointer],
1359                    );
1360                    let classname = class_namespace(self, func, variant).join("::");
1361                    uwriteln!(
1362                        self.r#gen.c_src.src,
1363                        "return ({}*){wasm_sig}({});",
1364                        classname,
1365                        func.params.first().unwrap().0
1366                    );
1367                }
1368                SpecialMethod::Allocate => unreachable!(),
1369                SpecialMethod::None => {
1370                    // normal methods
1371                    let namespace = if matches!(func.kind, FunctionKind::Freestanding) {
1372                        namespace(
1373                            self.resolve,
1374                            owner,
1375                            matches!(variant, AbiVariant::GuestExport),
1376                            &self.r#gen.opts,
1377                        )
1378                    } else {
1379                        let owner = &self.resolve.types[match &func.kind {
1380                            FunctionKind::Static(id) => *id,
1381                            FunctionKind::Constructor(id) => *id,
1382                            FunctionKind::Method(id) => *id,
1383                            FunctionKind::Freestanding => unreachable!(),
1384                            FunctionKind::AsyncFreestanding => todo!(),
1385                            FunctionKind::AsyncMethod(_id) => todo!(),
1386                            FunctionKind::AsyncStatic(_id) => todo!(),
1387                        }]
1388                        .clone();
1389                        let mut namespace = namespace(
1390                            self.resolve,
1391                            &owner.owner,
1392                            matches!(variant, AbiVariant::GuestExport),
1393                            &self.r#gen.opts,
1394                        );
1395                        namespace.push(owner.name.as_ref().unwrap().to_upper_camel_case());
1396                        namespace
1397                    };
1398                    let mut f = FunctionBindgen::new(self, params);
1399                    if !export {
1400                        f.namespace = namespace.clone();
1401                    }
1402                    f.variant = variant;
1403                    f.needs_dealloc = needs_dealloc;
1404                    f.cabi_post = None;
1405                    abi::call(f.r#gen.resolve, variant, lift_lower, func, &mut f, false);
1406                    let ret_area_decl = f.emit_ret_area_if_needed();
1407                    let code = format!("{}{}", ret_area_decl, String::from(f.src));
1408                    self.r#gen.c_src.src.push_str(&code);
1409                }
1410            }
1411            self.r#gen.c_src.src.push_str("}\n");
1412            // cabi_post
1413            if matches!(variant, AbiVariant::GuestExport)
1414                && abi::guest_export_needs_post_return(self.resolve, func)
1415            {
1416                let sig = self.resolve.wasm_signature(variant, func);
1417                let module_name = self.wasm_import_module.clone();
1418                let export_name = match module_name {
1419                    Some(ref module_name) => {
1420                        format!("{module_name}#{}", func.name)
1421                    }
1422                    None => make_external_component(&func.name),
1423                };
1424                let import_name = match module_name {
1425                    Some(ref module_name) => {
1426                        make_external_symbol(module_name, &func.name, AbiVariant::GuestExport)
1427                    }
1428                    None => make_external_component(&func.name),
1429                };
1430                uwriteln!(
1431                    self.r#gen.c_src.src,
1432                    "extern \"C\" __attribute__((__weak__, __export_name__(\"cabi_post_{export_name}\")))"
1433                );
1434                uwrite!(self.r#gen.c_src.src, "void cabi_post_{import_name}(");
1435
1436                let mut params = Vec::new();
1437                for (i, result) in sig.results.iter().enumerate() {
1438                    let name = format!("arg{i}");
1439                    uwrite!(
1440                        self.r#gen.c_src.src,
1441                        "{} {name}",
1442                        wit_bindgen_c::wasm_type(*result)
1443                    );
1444                    params.push(name);
1445                }
1446                self.r#gen.c_src.src.push_str(") {\n");
1447
1448                let mut f = FunctionBindgen::new(self, params.clone());
1449                f.params = params;
1450                abi::post_return(f.r#gen.resolve, func, &mut f);
1451                let ret_area_decl = f.emit_ret_area_if_needed();
1452                let code = format!("{}{}", ret_area_decl, String::from(f.src));
1453                self.r#gen.c_src.src.push_str(&code);
1454                self.r#gen.c_src.src.push_str("}\n");
1455            }
1456        }
1457    }
1458
1459    // in C this is print_optional_ty
1460    fn optional_type_name(
1461        &mut self,
1462        ty: Option<&Type>,
1463        from_namespace: &[String],
1464        flavor: Flavor,
1465    ) -> String {
1466        match ty {
1467            Some(ty) => self.type_name(ty, from_namespace, flavor),
1468            None => "void".into(),
1469        }
1470    }
1471
1472    fn scoped_record_name(
1473        &self,
1474        id: TypeId,
1475        from_namespace: &[String],
1476        guest_export: bool,
1477        flavor: Flavor,
1478    ) -> String {
1479        let name = self.scoped_type_name(id, from_namespace, guest_export);
1480
1481        if let Flavor::Argument(AbiVariant::GuestImport) = flavor {
1482            match self.r#gen.opts.ownership {
1483                Ownership::Owning => name.to_string(),
1484                Ownership::CoarseBorrowing => {
1485                    if self.r#gen.types.get(id).has_own_handle {
1486                        name.to_string()
1487                    } else {
1488                        format!("{}Param", name)
1489                    }
1490                }
1491                Ownership::FineBorrowing => {
1492                    format!("{}Param", name)
1493                }
1494            }
1495        } else {
1496            name
1497        }
1498    }
1499
1500    fn scoped_type_name(
1501        &self,
1502        id: TypeId,
1503        from_namespace: &[String],
1504        guest_export: bool,
1505    ) -> String {
1506        let ty = &self.resolve.types[id];
1507        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
1508        let mut relative = SourceWithState {
1509            namespace: Vec::from(from_namespace),
1510            ..Default::default()
1511        };
1512        relative.qualify(&namespc);
1513        format!(
1514            "{}{}",
1515            &*relative.src,
1516            ty.name.as_ref().unwrap().to_pascal_case()
1517        )
1518    }
1519
1520    fn type_name(&mut self, ty: &Type, from_namespace: &[String], flavor: Flavor) -> String {
1521        match ty {
1522            Type::Bool => "bool".into(),
1523            Type::Char => "uint32_t".into(),
1524            Type::U8 => "uint8_t".into(),
1525            Type::S8 => "int8_t".into(),
1526            Type::U16 => "uint16_t".into(),
1527            Type::S16 => "int16_t".into(),
1528            Type::U32 => "uint32_t".into(),
1529            Type::S32 => "int32_t".into(),
1530            Type::U64 => "uint64_t".into(),
1531            Type::S64 => "int64_t".into(),
1532            Type::F32 => "float".into(),
1533            Type::F64 => "double".into(),
1534            Type::String => match flavor {
1535                Flavor::BorrowedArgument => {
1536                    self.r#gen.dependencies.needs_string_view = true;
1537                    "std::string_view".into()
1538                }
1539                Flavor::Argument(var)
1540                    if matches!(var, AbiVariant::GuestImport)
1541                        || self.r#gen.opts.api_style == APIStyle::Symmetric =>
1542                {
1543                    self.r#gen.dependencies.needs_string_view = true;
1544                    "std::string_view".into()
1545                }
1546                Flavor::Argument(AbiVariant::GuestExport) => {
1547                    self.r#gen.dependencies.needs_wit = true;
1548                    "wit::string".into()
1549                }
1550                _ => {
1551                    self.r#gen.dependencies.needs_wit = true;
1552                    "wit::string".into()
1553                }
1554            },
1555            Type::Id(id) => match &self.resolve.types[*id].kind {
1556                TypeDefKind::Record(_) => {
1557                    let guest_export = self.is_exported_type(&self.resolve.types[*id]);
1558                    self.scoped_record_name(*id, from_namespace, guest_export, flavor)
1559                }
1560                TypeDefKind::Resource => {
1561                    let guest_export = self.is_exported_type(&self.resolve.types[*id]);
1562                    self.scoped_type_name(*id, from_namespace, guest_export)
1563                }
1564                TypeDefKind::Handle(Handle::Own(id)) => {
1565                    let mut typename = self.type_name(&Type::Id(*id), from_namespace, flavor);
1566                    let ty = &self.resolve.types[*id];
1567
1568                    // Follow type aliases to find the actual resource definition
1569                    // When a resource is `use`d in another interface, we have a type alias
1570                    // with the new interface as owner. We need to follow to the original resource.
1571                    let resource_ty = match &ty.kind {
1572                        TypeDefKind::Type(Type::Id(resource_id)) => {
1573                            &self.resolve.types[*resource_id]
1574                        }
1575                        _ => ty,
1576                    };
1577
1578                    let is_exported = self.is_exported_type(resource_ty);
1579                    match (false, flavor) {
1580                        (false, Flavor::Argument(AbiVariant::GuestImport))
1581                        | (true, Flavor::Argument(AbiVariant::GuestExport)) => {
1582                            typename.push_str("&&")
1583                        }
1584                        (false, Flavor::Argument(AbiVariant::GuestExport))
1585                        | (false, Flavor::Result(AbiVariant::GuestExport))
1586                        | (true, Flavor::Argument(AbiVariant::GuestImport))
1587                        | (true, Flavor::Result(AbiVariant::GuestImport)) => {
1588                            // Only exported resources have ::Owned typedef
1589                            if is_exported {
1590                                typename.push_str(&format!("::{OWNED_CLASS_NAME}"))
1591                            } else {
1592                                typename.push_str("&&")
1593                            }
1594                        }
1595                        (false, Flavor::Result(AbiVariant::GuestImport))
1596                        | (true, Flavor::Result(AbiVariant::GuestExport)) => (),
1597                        (_, Flavor::InStruct) => (),
1598                        (false, Flavor::BorrowedArgument) => (),
1599                        (_, _) => todo!(),
1600                    }
1601                    if matches!(flavor, Flavor::InStruct) && is_exported {
1602                        typename.push_str(&format!("::{OWNED_CLASS_NAME}"))
1603                    }
1604                    typename
1605                }
1606                TypeDefKind::Handle(Handle::Borrow(id)) => {
1607                    "std::reference_wrapper<const ".to_string()
1608                        + &self.type_name(&Type::Id(*id), from_namespace, flavor)
1609                        + ">"
1610                }
1611                TypeDefKind::Flags(_f) => {
1612                    let ty = &self.resolve.types[*id];
1613                    let guest_export = self.is_exported_type(ty);
1614                    self.scoped_type_name(*id, from_namespace, guest_export)
1615                }
1616                TypeDefKind::Tuple(t) => {
1617                    let types = t.types.iter().fold(String::new(), |mut a, b| {
1618                        if !a.is_empty() {
1619                            a += ", ";
1620                        }
1621                        a + &self.type_name(b, from_namespace, flavor)
1622                    });
1623                    self.r#gen.dependencies.needs_tuple = true;
1624                    String::from("std::tuple<") + &types + ">"
1625                }
1626                TypeDefKind::Variant(_v) => {
1627                    let ty = &self.resolve.types[*id];
1628                    let guest_export = self.is_exported_type(ty);
1629                    self.scoped_type_name(*id, from_namespace, guest_export)
1630                }
1631                TypeDefKind::Enum(_e) => {
1632                    let ty = &self.resolve.types[*id];
1633                    let guest_export = self.is_exported_type(ty);
1634                    self.scoped_type_name(*id, from_namespace, guest_export)
1635                }
1636                TypeDefKind::Option(o) => {
1637                    // Template parameters need base types without && or other decorations
1638                    // For import arguments, use BorrowedArgument flavor to get string_view
1639                    let template_flavor = match flavor {
1640                        Flavor::Argument(AbiVariant::GuestImport) => Flavor::BorrowedArgument,
1641                        _ => Flavor::InStruct,
1642                    };
1643                    self.r#gen.dependencies.needs_optional = true;
1644                    "std::optional<".to_string()
1645                        + &self.type_name(o, from_namespace, template_flavor)
1646                        + ">"
1647                }
1648                TypeDefKind::Result(r) => {
1649                    // Template parameters need base types without && or other decorations
1650                    let template_flavor = Flavor::InStruct;
1651                    let err_type = r.err.as_ref().map_or(String::from("wit::Void"), |ty| {
1652                        self.type_name(ty, from_namespace, template_flavor)
1653                    });
1654                    self.r#gen.dependencies.needs_expected = true;
1655                    "std::expected<".to_string()
1656                        + &self.optional_type_name(r.ok.as_ref(), from_namespace, template_flavor)
1657                        + ", "
1658                        + &err_type
1659                        + ">"
1660                }
1661                TypeDefKind::List(ty) => {
1662                    // For list elements, use BorrowedArgument flavor for imported functions
1663                    // to get std::string_view instead of wit::string. Otherwise use InStruct
1664                    // flavor to avoid adding && to owned resources (lists contain values, not rvalue references)
1665                    let element_flavor = match flavor {
1666                        Flavor::BorrowedArgument | Flavor::Argument(AbiVariant::GuestImport) => {
1667                            Flavor::BorrowedArgument
1668                        }
1669                        _ => Flavor::InStruct,
1670                    };
1671                    let inner = self.type_name(ty, from_namespace, element_flavor);
1672                    match flavor {
1673                        Flavor::BorrowedArgument => {
1674                            self.r#gen.dependencies.needs_span = true;
1675                            format!("std::span<{inner} const>")
1676                        }
1677                        Flavor::Argument(var)
1678                            if matches!(var, AbiVariant::GuestImport)
1679                                || self.r#gen.opts.api_style == APIStyle::Symmetric =>
1680                        {
1681                            self.r#gen.dependencies.needs_span = true;
1682                            // If the list has an owning handle, it must support moving, so can't be const
1683                            let constness = if self.r#gen.types.get(*id).has_own_handle {
1684                                ""
1685                            } else {
1686                                " const"
1687                            };
1688                            format!("std::span<{inner}{constness}>")
1689                        }
1690                        Flavor::Argument(AbiVariant::GuestExport) => {
1691                            self.r#gen.dependencies.needs_wit = true;
1692                            format!("wit::vector<{inner}>")
1693                        }
1694                        _ => {
1695                            self.r#gen.dependencies.needs_wit = true;
1696                            format!("wit::vector<{inner}>")
1697                        }
1698                    }
1699                }
1700                TypeDefKind::Future(_) => todo!(),
1701                TypeDefKind::Stream(_) => todo!(),
1702                TypeDefKind::Type(ty) => self.type_name(ty, from_namespace, flavor),
1703                TypeDefKind::FixedSizeList(_, _) => todo!(),
1704                TypeDefKind::Unknown => todo!(),
1705            },
1706            Type::ErrorContext => todo!(),
1707        }
1708    }
1709
1710    fn declare_import2(
1711        &self,
1712        module_name: &str,
1713        name: &str,
1714        args: &str,
1715        result: &str,
1716        variant: AbiVariant,
1717    ) -> (String, String) {
1718        let mut extern_name = String::from("__wasm_import_");
1719        extern_name.push_str(&make_external_symbol(module_name, name, variant));
1720        let import = format!(
1721            "extern \"C\" __attribute__((import_module(\"{module_name}\")))\n __attribute__((import_name(\"{name}\")))\n {result} {extern_name}({args});\n"
1722        );
1723        (extern_name, import)
1724    }
1725
1726    fn declare_import(
1727        &mut self,
1728        module_name: &str,
1729        name: &str,
1730        params: &[WasmType],
1731        results: &[WasmType],
1732    ) -> String {
1733        let mut args = String::default();
1734        for (n, param) in params.iter().enumerate() {
1735            args.push_str(wit_bindgen_c::wasm_type(*param));
1736            if n + 1 != params.len() {
1737                args.push_str(", ");
1738            }
1739        }
1740        let result = if results.is_empty() {
1741            "void"
1742        } else {
1743            wit_bindgen_c::wasm_type(results[0])
1744        };
1745        let variant = AbiVariant::GuestImport;
1746        let (name, code) = self.declare_import2(module_name, name, &args, result, variant);
1747        self.r#gen.extern_c_decls.push_str(&code);
1748        name
1749    }
1750
1751    fn docs(src: &mut Source, docs: &Docs) {
1752        if let Some(docs) = docs.contents.as_ref() {
1753            for line in docs.trim().lines() {
1754                src.push_str("/// ");
1755                src.push_str(line);
1756                src.push_str("\n");
1757            }
1758        }
1759    }
1760
1761    fn type_record_param(
1762        &mut self,
1763        id: TypeId,
1764        name: &str,
1765        record: &wit_bindgen_core::wit_parser::Record,
1766        namespc: &[String],
1767    ) {
1768        let (flavor, needs_param_type) = {
1769            match self.r#gen.opts.ownership {
1770                Ownership::Owning => (Flavor::InStruct, false),
1771                Ownership::CoarseBorrowing => {
1772                    if self.r#gen.types.get(id).has_own_handle {
1773                        (Flavor::InStruct, false)
1774                    } else {
1775                        (Flavor::BorrowedArgument, true)
1776                    }
1777                }
1778                Ownership::FineBorrowing => (Flavor::BorrowedArgument, true),
1779            }
1780        };
1781
1782        if needs_param_type {
1783            let pascal = format!("{name}-param").to_pascal_case();
1784
1785            uwriteln!(self.r#gen.h_src.src, "struct {pascal} {{");
1786            for field in record.fields.iter() {
1787                let typename = self.type_name(&field.ty, namespc, flavor);
1788                let fname = to_c_ident(&field.name);
1789                uwriteln!(self.r#gen.h_src.src, "{typename} {fname};");
1790            }
1791            uwriteln!(self.r#gen.h_src.src, "}};");
1792        }
1793    }
1794
1795    fn is_exported_type(&self, ty: &TypeDef) -> bool {
1796        match ty.owner {
1797            TypeOwner::Interface(intf) => {
1798                // For resources used in export functions, check if the resource's owner
1799                // interface is in imported_interfaces (which was populated during import())
1800                !self.r#gen.imported_interfaces.contains(&intf)
1801            }
1802            TypeOwner::World(_) => {
1803                // World-level resources are treated as imports, not exports
1804                false
1805            }
1806            TypeOwner::None => true,
1807        }
1808    }
1809}
1810
1811impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for CppInterfaceGenerator<'a> {
1812    fn resolve(&self) -> &'a Resolve {
1813        self.resolve
1814    }
1815
1816    fn type_record(
1817        &mut self,
1818        id: TypeId,
1819        name: &str,
1820        record: &wit_bindgen_core::wit_parser::Record,
1821        docs: &wit_bindgen_core::wit_parser::Docs,
1822    ) {
1823        let ty = &self.resolve.types[id];
1824        let guest_export = self.is_exported_type(ty);
1825        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
1826
1827        if self.r#gen.is_first_definition(&namespc, name) {
1828            self.r#gen.h_src.change_namespace(&namespc);
1829            Self::docs(&mut self.r#gen.h_src.src, docs);
1830            let pascal = name.to_pascal_case();
1831
1832            uwriteln!(self.r#gen.h_src.src, "struct {pascal} {{");
1833            for field in record.fields.iter() {
1834                Self::docs(&mut self.r#gen.h_src.src, &field.docs);
1835                let typename = self.type_name(&field.ty, &namespc, Flavor::InStruct);
1836                let fname = to_c_ident(&field.name);
1837                uwriteln!(self.r#gen.h_src.src, "{typename} {fname};");
1838            }
1839            uwriteln!(self.r#gen.h_src.src, "}};");
1840            self.type_record_param(id, name, record, namespc.as_slice());
1841        }
1842    }
1843
1844    fn type_resource(
1845        &mut self,
1846        id: TypeId,
1847        name: &str,
1848        _docs: &wit_bindgen_core::wit_parser::Docs,
1849    ) {
1850        let type_ = &self.resolve.types[id];
1851        if let TypeOwner::Interface(intf) = type_.owner {
1852            let guest_import = self.r#gen.imported_interfaces.contains(&intf);
1853            let definition = !(guest_import);
1854            let store = self.r#gen.start_new_file(Some(definition));
1855            let mut world_name = to_c_ident(&self.r#gen.world);
1856            world_name.push_str("::");
1857            let namespc = namespace(self.resolve, &type_.owner, !guest_import, &self.r#gen.opts);
1858            let pascal = name.to_upper_camel_case();
1859            let mut user_filename = namespc.clone();
1860            user_filename.push(pascal.clone());
1861            if definition {
1862                uwriteln!(
1863                    self.r#gen.h_src.src,
1864                    r#"/* User class definition file, autogenerated once, then user modified
1865                    * Updated versions of this file are generated into {pascal}.template.
1866                    */"#
1867                );
1868            }
1869            self.r#gen.h_src.change_namespace(&namespc);
1870
1871            if !definition {
1872                self.r#gen.dependencies.needs_imported_resources = true;
1873            } else {
1874                self.r#gen.dependencies.needs_exported_resources = true;
1875            }
1876            self.r#gen.dependencies.needs_wit = true;
1877
1878            let base_type = match (definition, false) {
1879                (true, false) => format!("wit::{RESOURCE_EXPORT_BASE_CLASS_NAME}<{pascal}>"),
1880                (false, false) => {
1881                    String::from_str("wit::").unwrap() + RESOURCE_IMPORT_BASE_CLASS_NAME
1882                }
1883                (false, true) => {
1884                    String::from_str("wit::").unwrap() + RESOURCE_EXPORT_BASE_CLASS_NAME
1885                }
1886                (true, true) => format!("wit::{RESOURCE_IMPORT_BASE_CLASS_NAME}<{pascal}>"),
1887            };
1888            let derive = format!(" : public {base_type}");
1889            uwriteln!(self.r#gen.h_src.src, "class {pascal}{derive} {{\n");
1890            uwriteln!(self.r#gen.h_src.src, "public:\n");
1891            let variant = if guest_import {
1892                AbiVariant::GuestImport
1893            } else {
1894                AbiVariant::GuestExport
1895            };
1896            {
1897                // destructor
1898                let name = match variant {
1899                    AbiVariant::GuestImport => "[resource-drop]",
1900                    AbiVariant::GuestExport => "[dtor]",
1901                    AbiVariant::GuestImportAsync => todo!(),
1902                    AbiVariant::GuestExportAsync => todo!(),
1903                    AbiVariant::GuestExportAsyncStackful => todo!(),
1904                }
1905                .to_string()
1906                    + name;
1907                let func = Function {
1908                    name,
1909                    kind: FunctionKind::Static(id),
1910                    params: vec![("self".into(), Type::Id(id))],
1911                    result: None,
1912                    docs: Docs::default(),
1913                    stability: Stability::Unknown,
1914                };
1915                self.generate_function(&func, &TypeOwner::Interface(intf), variant);
1916            }
1917            let funcs = self.resolve.interfaces[intf].functions.values();
1918            for func in funcs {
1919                if match &func.kind {
1920                    FunctionKind::Freestanding => false,
1921                    FunctionKind::Method(mid) => *mid == id,
1922                    FunctionKind::Static(mid) => *mid == id,
1923                    FunctionKind::Constructor(mid) => *mid == id,
1924                    FunctionKind::AsyncFreestanding => todo!(),
1925                    FunctionKind::AsyncMethod(_id) => todo!(),
1926                    FunctionKind::AsyncStatic(_id) => todo!(),
1927                } {
1928                    self.generate_function(func, &TypeOwner::Interface(intf), variant);
1929                    // For non-fallible constructors on export side, generate a New allocator method
1930                    // For fallible constructors, the user provides their own Create method
1931                    let is_fallible_constructor =
1932                        self.r#gen.is_fallible_constructor(self.resolve, func);
1933
1934                    if matches!(func.kind, FunctionKind::Constructor(_))
1935                        && matches!(variant, AbiVariant::GuestExport)
1936                        && !is_fallible_constructor
1937                    {
1938                        // functional safety requires the option to use a different allocator, so move new into the implementation
1939                        let func2 = Function {
1940                            name: "$alloc".to_string(),
1941                            kind: FunctionKind::Static(id),
1942                            // same params as constructor
1943                            params: func.params.clone(),
1944                            result: Some(Type::Id(id)),
1945                            docs: Docs::default(),
1946                            stability: Stability::Unknown,
1947                        };
1948                        self.generate_function(&func2, &TypeOwner::Interface(intf), variant);
1949                    }
1950                }
1951            }
1952
1953            if !definition {
1954                // consuming constructor from handle (bindings)
1955                uwriteln!(self.r#gen.h_src.src, "{pascal}({base_type} &&);",);
1956                uwriteln!(self.r#gen.h_src.src, "{pascal}({pascal}&&) = default;");
1957                uwriteln!(
1958                    self.r#gen.h_src.src,
1959                    "{pascal}& operator=({pascal}&&) = default;"
1960                );
1961                self.r#gen.c_src.qualify(&namespc);
1962                uwriteln!(
1963                    self.r#gen.c_src.src,
1964                    "{pascal}::{pascal}({base_type}&&b) : {base_type}(std::move(b)) {{}}"
1965                );
1966            }
1967            if matches!(variant, AbiVariant::GuestExport) {
1968                let id_type = Type::S32;
1969                let func = Function {
1970                    name: "[resource-new]".to_string() + name,
1971                    kind: FunctionKind::Static(id),
1972                    params: vec![("self".into(), Type::Id(id))],
1973                    result: Some(id_type),
1974                    docs: Docs::default(),
1975                    stability: Stability::Unknown,
1976                };
1977                self.generate_function(&func, &TypeOwner::Interface(intf), variant);
1978
1979                let func1 = Function {
1980                    name: "[resource-rep]".to_string() + name,
1981                    kind: FunctionKind::Static(id),
1982                    params: vec![("id".into(), id_type)],
1983                    result: Some(Type::Id(id)),
1984                    docs: Docs::default(),
1985                    stability: Stability::Unknown,
1986                };
1987                self.generate_function(&func1, &TypeOwner::Interface(intf), variant);
1988
1989                let func2 = Function {
1990                    name: "[resource-drop]".to_string() + name,
1991                    kind: FunctionKind::Static(id),
1992                    params: vec![("id".into(), id_type)],
1993                    result: None,
1994                    docs: Docs::default(),
1995                    stability: Stability::Unknown,
1996                };
1997                self.generate_function(&func2, &TypeOwner::Interface(intf), variant);
1998            }
1999            uwriteln!(self.r#gen.h_src.src, "}};\n");
2000            self.r#gen.finish_file(&user_filename, store);
2001        } else if matches!(type_.owner, TypeOwner::World(_)) {
2002            // Handle world-level resources - treat as imported resources
2003            let guest_export = false; // World-level resources are treated as imports
2004            let namespc = namespace(self.resolve, &type_.owner, guest_export, &self.r#gen.opts);
2005            self.r#gen.h_src.change_namespace(&namespc);
2006
2007            let pascal = name.to_upper_camel_case();
2008            self.r#gen.dependencies.needs_imported_resources = true;
2009            self.r#gen.dependencies.needs_wit = true;
2010
2011            let base_type = format!("wit::{RESOURCE_IMPORT_BASE_CLASS_NAME}");
2012            let derive = format!(" : public {base_type}");
2013            uwriteln!(self.r#gen.h_src.src, "class {pascal}{derive}{{\n");
2014            uwriteln!(self.r#gen.h_src.src, "public:\n");
2015
2016            // Add destructor and constructor
2017            uwriteln!(self.r#gen.h_src.src, "~{pascal}();");
2018            uwriteln!(
2019                self.r#gen.h_src.src,
2020                "{pascal}(wit::{RESOURCE_IMPORT_BASE_CLASS_NAME} &&);"
2021            );
2022            uwriteln!(self.r#gen.h_src.src, "{pascal}({pascal}&&) = default;");
2023            uwriteln!(
2024                self.r#gen.h_src.src,
2025                "{pascal}& operator=({pascal}&&) = default;"
2026            );
2027            uwriteln!(self.r#gen.h_src.src, "}};\n");
2028        }
2029    }
2030
2031    fn type_flags(
2032        &mut self,
2033        id: TypeId,
2034        name: &str,
2035        flags: &wit_bindgen_core::wit_parser::Flags,
2036        docs: &wit_bindgen_core::wit_parser::Docs,
2037    ) {
2038        let ty = &self.resolve.types[id];
2039        let guest_export = self.is_exported_type(ty);
2040        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
2041        if self.r#gen.is_first_definition(&namespc, name) {
2042            self.r#gen.h_src.change_namespace(&namespc);
2043            Self::docs(&mut self.r#gen.h_src.src, docs);
2044            let pascal = name.to_pascal_case();
2045            let int_repr = wit_bindgen_c::int_repr(wit_bindgen_c::flags_repr(flags));
2046            uwriteln!(self.r#gen.h_src.src, "enum class {pascal} : {int_repr} {{");
2047            uwriteln!(self.r#gen.h_src.src, "k_None = 0,");
2048            for (n, field) in flags.flags.iter().enumerate() {
2049                Self::docs(&mut self.r#gen.h_src.src, &field.docs);
2050                let fname = to_c_ident(&field.name).to_pascal_case();
2051                uwriteln!(self.r#gen.h_src.src, "k{fname} = (1ULL<<{n}),");
2052            }
2053            uwriteln!(self.r#gen.h_src.src, "}};");
2054            uwriteln!(
2055                self.r#gen.h_src.src,
2056                r#"static inline {pascal} operator|({pascal} a, {pascal} b) {{ return {pascal}({int_repr}(a)|{int_repr}(b)); }}
2057        static inline {pascal} operator&({pascal} a, {pascal} b) {{ return {pascal}({int_repr}(a)&{int_repr}(b)); }}"#
2058            );
2059        }
2060    }
2061
2062    fn type_tuple(
2063        &mut self,
2064        _id: TypeId,
2065        _name: &str,
2066        _flags: &wit_bindgen_core::wit_parser::Tuple,
2067        _docs: &wit_bindgen_core::wit_parser::Docs,
2068    ) {
2069        // I assume I don't need to do anything ...
2070    }
2071
2072    fn type_variant(
2073        &mut self,
2074        id: TypeId,
2075        name: &str,
2076        variant: &wit_bindgen_core::wit_parser::Variant,
2077        docs: &wit_bindgen_core::wit_parser::Docs,
2078    ) {
2079        let ty = &self.resolve.types[id];
2080        let guest_export = self.is_exported_type(ty);
2081        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
2082        if self.r#gen.is_first_definition(&namespc, name) {
2083            self.r#gen.h_src.change_namespace(&namespc);
2084            Self::docs(&mut self.r#gen.h_src.src, docs);
2085            let pascal = name.to_pascal_case();
2086            uwriteln!(self.r#gen.h_src.src, "struct {pascal} {{");
2087            let mut inner_namespace = namespc.clone();
2088            inner_namespace.push(pascal.clone());
2089            let mut all_types = String::new();
2090            for case in variant.cases.iter() {
2091                Self::docs(&mut self.r#gen.h_src.src, &case.docs);
2092                let case_pascal = to_c_ident(&case.name).to_pascal_case();
2093                if !all_types.is_empty() {
2094                    all_types += ", ";
2095                }
2096                all_types += &case_pascal;
2097                uwrite!(self.r#gen.h_src.src, "struct {case_pascal} {{");
2098                if let Some(ty) = case.ty.as_ref() {
2099                    let typestr = self.type_name(ty, &inner_namespace, Flavor::InStruct);
2100                    uwrite!(self.r#gen.h_src.src, " {typestr} value; ")
2101                }
2102                uwriteln!(self.r#gen.h_src.src, "}};");
2103            }
2104            uwriteln!(
2105                self.r#gen.h_src.src,
2106                "  std::variant<{all_types}> variants;"
2107            );
2108            uwriteln!(self.r#gen.h_src.src, "}};");
2109            self.r#gen.dependencies.needs_variant = true;
2110        }
2111    }
2112
2113    fn type_option(
2114        &mut self,
2115        _id: TypeId,
2116        _name: &str,
2117        _payload: &wit_bindgen_core::wit_parser::Type,
2118        _docs: &wit_bindgen_core::wit_parser::Docs,
2119    ) {
2120        // nothing to do here
2121    }
2122
2123    fn type_result(
2124        &mut self,
2125        _id: TypeId,
2126        _name: &str,
2127        _result: &wit_bindgen_core::wit_parser::Result_,
2128        _docs: &wit_bindgen_core::wit_parser::Docs,
2129    ) {
2130        // nothing to do here
2131    }
2132
2133    fn type_enum(
2134        &mut self,
2135        id: TypeId,
2136        name: &str,
2137        enum_: &wit_bindgen_core::wit_parser::Enum,
2138        docs: &wit_bindgen_core::wit_parser::Docs,
2139    ) {
2140        let ty = &self.resolve.types[id];
2141        let guest_export = self.is_exported_type(ty);
2142        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
2143        if self.r#gen.is_first_definition(&namespc, name) {
2144            self.r#gen.h_src.change_namespace(&namespc);
2145            let pascal = name.to_pascal_case();
2146            Self::docs(&mut self.r#gen.h_src.src, docs);
2147            let int_t = wit_bindgen_c::int_repr(enum_.tag());
2148            uwriteln!(self.r#gen.h_src.src, "enum class {pascal} : {int_t} {{");
2149            for (i, case) in enum_.cases.iter().enumerate() {
2150                Self::docs(&mut self.r#gen.h_src.src, &case.docs);
2151                uwriteln!(
2152                    self.r#gen.h_src.src,
2153                    " k{} = {i},",
2154                    to_c_ident(&case.name).to_pascal_case(),
2155                );
2156            }
2157            uwriteln!(self.r#gen.h_src.src, "}};\n");
2158        }
2159    }
2160
2161    fn type_alias(
2162        &mut self,
2163        id: TypeId,
2164        name: &str,
2165        alias_type: &wit_bindgen_core::wit_parser::Type,
2166        docs: &wit_bindgen_core::wit_parser::Docs,
2167    ) {
2168        let ty = &self.resolve.types[id];
2169        let guest_export = self.is_exported_type(ty);
2170        let namespc = namespace(self.resolve, &ty.owner, guest_export, &self.r#gen.opts);
2171        self.r#gen.h_src.change_namespace(&namespc);
2172        let pascal = name.to_pascal_case();
2173        Self::docs(&mut self.r#gen.h_src.src, docs);
2174        let typename = self.type_name(alias_type, &namespc, Flavor::InStruct);
2175        uwriteln!(self.r#gen.h_src.src, "using {pascal} = {typename};");
2176    }
2177
2178    fn type_list(
2179        &mut self,
2180        _id: TypeId,
2181        _name: &str,
2182        _ty: &wit_bindgen_core::wit_parser::Type,
2183        _docs: &wit_bindgen_core::wit_parser::Docs,
2184    ) {
2185        // nothing to do here
2186    }
2187
2188    fn type_builtin(
2189        &mut self,
2190        _id: TypeId,
2191        _name: &str,
2192        _ty: &wit_bindgen_core::wit_parser::Type,
2193        _docs: &wit_bindgen_core::wit_parser::Docs,
2194    ) {
2195        todo!()
2196    }
2197
2198    fn type_future(&mut self, _id: TypeId, _name: &str, _ty: &Option<Type>, _docs: &Docs) {
2199        todo!()
2200    }
2201
2202    fn type_stream(&mut self, _id: TypeId, _name: &str, _ty: &Option<Type>, _docs: &Docs) {
2203        todo!()
2204    }
2205}
2206
2207struct CabiPostInformation {
2208    module: String,
2209    name: String,
2210    ret_type: String,
2211}
2212
2213struct FunctionBindgen<'a, 'b> {
2214    r#gen: &'b mut CppInterfaceGenerator<'a>,
2215    params: Vec<String>,
2216    tmp: usize,
2217    namespace: Vec<String>,
2218    src: Source,
2219    block_storage: Vec<wit_bindgen_core::Source>,
2220    /// intermediate calculations for contained objects
2221    blocks: Vec<(String, Vec<String>)>,
2222    payloads: Vec<String>,
2223    // caching for wasm
2224    variant: AbiVariant,
2225    cabi_post: Option<CabiPostInformation>,
2226    needs_dealloc: bool,
2227    leak_on_insertion: Option<String>,
2228    return_pointer_area_size: ArchitectureSize,
2229    return_pointer_area_align: Alignment,
2230}
2231
2232impl<'a, 'b> FunctionBindgen<'a, 'b> {
2233    fn new(r#gen: &'b mut CppInterfaceGenerator<'a>, params: Vec<String>) -> Self {
2234        Self {
2235            r#gen,
2236            params,
2237            tmp: 0,
2238            namespace: Default::default(),
2239            src: Default::default(),
2240            block_storage: Default::default(),
2241            blocks: Default::default(),
2242            payloads: Default::default(),
2243            variant: AbiVariant::GuestImport,
2244            cabi_post: None,
2245            needs_dealloc: false,
2246            leak_on_insertion: None,
2247            return_pointer_area_size: Default::default(),
2248            return_pointer_area_align: Default::default(),
2249        }
2250    }
2251
2252    fn tmp(&mut self) -> usize {
2253        let ret = self.tmp;
2254        self.tmp += 1;
2255        ret
2256    }
2257
2258    fn tempname(&self, base: &str, idx: usize) -> String {
2259        format!("{base}{idx}")
2260    }
2261
2262    fn push_str(&mut self, s: &str) {
2263        self.src.push_str(s);
2264    }
2265
2266    fn let_results(&mut self, amt: usize, results: &mut Vec<String>) {
2267        if amt > 0 {
2268            let tmp = self.tmp();
2269            let res = format!("result{}", tmp);
2270            self.push_str("auto ");
2271            self.push_str(&res);
2272            self.push_str(" = ");
2273            if amt == 1 {
2274                results.push(res);
2275            } else {
2276                for i in 0..amt {
2277                    results.push(format!("std::get<{i}>({res})"));
2278                }
2279            }
2280        }
2281    }
2282
2283    fn load(
2284        &mut self,
2285        ty: &str,
2286        offset: ArchitectureSize,
2287        operands: &[String],
2288        results: &mut Vec<String>,
2289    ) {
2290        results.push(format!(
2291            "*(({}*) ({} + {}))",
2292            ty,
2293            operands[0],
2294            offset.format(POINTER_SIZE_EXPRESSION)
2295        ));
2296    }
2297
2298    fn load_ext(
2299        &mut self,
2300        ty: &str,
2301        offset: ArchitectureSize,
2302        operands: &[String],
2303        results: &mut Vec<String>,
2304    ) {
2305        self.load(ty, offset, operands, results);
2306        let result = results.pop().unwrap();
2307        results.push(format!("(int32_t) ({})", result));
2308    }
2309
2310    fn store(&mut self, ty: &str, offset: ArchitectureSize, operands: &[String]) {
2311        uwriteln!(
2312            self.src,
2313            "*(({}*)({} + {})) = {};",
2314            ty,
2315            operands[1],
2316            offset.format(POINTER_SIZE_EXPRESSION),
2317            operands[0]
2318        );
2319    }
2320
2321    /// Emits a shared return area declaration if needed by this function.
2322    ///
2323    /// During code generation, `return_pointer()` may be called multiple times for:
2324    /// - Indirect parameter storage (when too many/large params)
2325    /// - Return value storage (when return type is too large)
2326    ///
2327    /// **Safety:** This is safe because return pointers are used sequentially:
2328    /// 1. Parameter marshaling (before call)
2329    /// 2. Function execution
2330    /// 3. Return value unmarshaling (after call)
2331    ///
2332    /// The scratch space is reused but never accessed simultaneously.
2333    fn emit_ret_area_if_needed(&self) -> String {
2334        if !self.return_pointer_area_size.is_empty() {
2335            let size_string = self
2336                .return_pointer_area_size
2337                .format(POINTER_SIZE_EXPRESSION);
2338            let tp = match self.return_pointer_area_align {
2339                Alignment::Bytes(bytes) => match bytes.get() {
2340                    1 => "uint8_t",
2341                    2 => "uint16_t",
2342                    4 => "uint32_t",
2343                    8 => "uint64_t",
2344                    // Fallback to uint8_t for unusual alignments (e.g., 16-byte SIMD).
2345                    // This is safe: the size calculation ensures correct buffer size,
2346                    // and uint8_t arrays can store any data regardless of alignment.
2347                    _ => "uint8_t",
2348                },
2349                Alignment::Pointer => "uintptr_t",
2350            };
2351            let static_var = if self.r#gen.in_guest_import {
2352                ""
2353            } else {
2354                "static "
2355            };
2356            format!("{static_var}{tp} ret_area[({size_string}+sizeof({tp})-1)/sizeof({tp})];\n")
2357        } else {
2358            String::new()
2359        }
2360    }
2361}
2362
2363fn move_if_necessary(arg: &str) -> String {
2364    // if it is a name of a variable move it
2365    if !arg.is_empty() && arg.chars().all(char::is_alphanumeric) {
2366        format!("std::move({arg})")
2367    } else {
2368        arg.into()
2369    }
2370}
2371
2372impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
2373    type Operand = String;
2374
2375    fn emit(
2376        &mut self,
2377        _resolve: &Resolve,
2378        inst: &wit_bindgen_core::abi::Instruction<'_>,
2379        operands: &mut Vec<Self::Operand>,
2380        results: &mut Vec<Self::Operand>,
2381    ) {
2382        let mut top_as = |cvt: &str| {
2383            results.push(format!("({cvt}({}))", operands.pop().unwrap()));
2384        };
2385
2386        match inst {
2387            abi::Instruction::GetArg { nth } => {
2388                if *nth == 0 && self.params[0].as_str() == "self" {
2389                    if self.r#gen.in_guest_import {
2390                        results.push("(*this)".to_string());
2391                    } else {
2392                        results.push("(*lookup_resource(self))".to_string());
2393                    }
2394                } else {
2395                    results.push(self.params[*nth].clone());
2396                }
2397            }
2398            abi::Instruction::I32Const { val } => results.push(format!("(int32_t({}))", val)),
2399            abi::Instruction::Bitcasts { casts } => {
2400                for (cast, op) in casts.iter().zip(operands) {
2401                    // let op = op;
2402                    results.push(self.r#gen.r#gen.perform_cast(op, cast));
2403                }
2404            }
2405            abi::Instruction::ConstZero { tys } => {
2406                for ty in tys.iter() {
2407                    match ty {
2408                        WasmType::I32 => results.push("int32_t(0)".to_string()),
2409                        WasmType::I64 => results.push("int64_t(0)".to_string()),
2410                        WasmType::F32 => results.push("0.0f".to_string()),
2411                        WasmType::F64 => results.push("0.0".to_string()),
2412                        WasmType::Length => results.push("size_t(0)".to_string()),
2413                        WasmType::Pointer => results.push("nullptr".to_string()),
2414                        WasmType::PointerOrI64 => results.push("int64_t(0)".to_string()),
2415                    }
2416                }
2417            }
2418            abi::Instruction::I32Load { offset } => {
2419                let tmp = self.tmp();
2420                uwriteln!(
2421                    self.src,
2422                    "int32_t l{tmp} = *((int32_t const*)({} + {offset}));",
2423                    operands[0],
2424                    offset = offset.format(POINTER_SIZE_EXPRESSION)
2425                );
2426                results.push(format!("l{tmp}"));
2427            }
2428            abi::Instruction::I32Load8U { offset } => {
2429                self.load_ext("uint8_t", *offset, operands, results)
2430            }
2431            abi::Instruction::I32Load8S { offset } => {
2432                self.load_ext("int8_t", *offset, operands, results)
2433            }
2434            abi::Instruction::I32Load16U { offset } => {
2435                self.load_ext("uint16_t", *offset, operands, results)
2436            }
2437            abi::Instruction::I32Load16S { offset } => {
2438                self.load_ext("int16_t", *offset, operands, results)
2439            }
2440            abi::Instruction::I64Load { offset } => {
2441                self.load("int64_t", *offset, operands, results)
2442            }
2443            abi::Instruction::F32Load { offset } => self.load("float", *offset, operands, results),
2444            abi::Instruction::F64Load { offset } => self.load("double", *offset, operands, results),
2445            abi::Instruction::I32Store { offset } => self.store("int32_t", *offset, operands),
2446            abi::Instruction::I32Store8 { offset } => self.store("int8_t", *offset, operands),
2447            abi::Instruction::I32Store16 { offset } => self.store("int16_t", *offset, operands),
2448            abi::Instruction::I64Store { offset } => self.store("int64_t", *offset, operands),
2449            abi::Instruction::F32Store { offset } => self.store("float", *offset, operands),
2450            abi::Instruction::F64Store { offset } => self.store("double", *offset, operands),
2451            abi::Instruction::I32FromChar
2452            | abi::Instruction::I32FromBool
2453            | abi::Instruction::I32FromU8
2454            | abi::Instruction::I32FromS8
2455            | abi::Instruction::I32FromU16
2456            | abi::Instruction::I32FromS16
2457            | abi::Instruction::I32FromU32
2458            | abi::Instruction::I32FromS32 => top_as("int32_t"),
2459            abi::Instruction::I64FromU64 | abi::Instruction::I64FromS64 => top_as("int64_t"),
2460            abi::Instruction::F32FromCoreF32 => top_as("float"),
2461            abi::Instruction::F64FromCoreF64 => top_as("double"),
2462            abi::Instruction::S8FromI32 => top_as("int8_t"),
2463            abi::Instruction::U8FromI32 => top_as("uint8_t"),
2464            abi::Instruction::S16FromI32 => top_as("int16_t"),
2465            abi::Instruction::U16FromI32 => top_as("uint16_t"),
2466            abi::Instruction::S32FromI32 => top_as("int32_t"),
2467            abi::Instruction::U32FromI32 => top_as("uint32_t"),
2468            abi::Instruction::S64FromI64 => top_as("int64_t"),
2469            abi::Instruction::U64FromI64 => top_as("uint64_t"),
2470            abi::Instruction::CharFromI32 => top_as("uint32_t"),
2471            abi::Instruction::CoreF32FromF32 => top_as("float"),
2472            abi::Instruction::CoreF64FromF64 => top_as("double"),
2473            abi::Instruction::BoolFromI32 => top_as("bool"),
2474            abi::Instruction::ListCanonLower { realloc, .. } => {
2475                let tmp = self.tmp();
2476                let val = format!("vec{}", tmp);
2477                let ptr = format!("ptr{}", tmp);
2478                let len = format!("len{}", tmp);
2479                self.push_str(&format!("auto&& {} = {};\n", val, operands[0]));
2480                self.push_str(&format!(
2481                    "auto {} = ({})({}.data());\n",
2482                    ptr,
2483                    self.r#gen.r#gen.opts.ptr_type(),
2484                    val
2485                ));
2486                self.push_str(&format!("auto {} = (size_t)({}.size());\n", len, val));
2487                if realloc.is_none() {
2488                    results.push(ptr);
2489                } else {
2490                    uwriteln!(self.src, "{}.leak();\n", operands[0]);
2491                    results.push(ptr);
2492                }
2493                results.push(len);
2494            }
2495            abi::Instruction::StringLower { realloc } => {
2496                let tmp = self.tmp();
2497                let val = format!("vec{}", tmp);
2498                let ptr = format!("ptr{}", tmp);
2499                let len = format!("len{}", tmp);
2500                self.push_str(&format!("auto&& {} = {};\n", val, operands[0]));
2501                self.push_str(&format!(
2502                    "auto {} = ({})({}.data());\n",
2503                    ptr,
2504                    self.r#gen.r#gen.opts.ptr_type(),
2505                    val
2506                ));
2507                self.push_str(&format!("auto {} = (size_t)({}.size());\n", len, val));
2508                if realloc.is_none() {
2509                    results.push(ptr);
2510                } else {
2511                    uwriteln!(self.src, "{}.leak();\n", operands[0]);
2512                    results.push(ptr);
2513                }
2514                results.push(len);
2515            }
2516            abi::Instruction::ListLower { element, realloc } => {
2517                let tmp = self.tmp();
2518                let body = self.blocks.pop().unwrap();
2519                let val = format!("vec{}", tmp);
2520                let ptr = format!("ptr{}", tmp);
2521                let len = format!("len{}", tmp);
2522                let size = self.r#gen.sizes.size(element);
2523                self.push_str(&format!("auto&& {} = {};\n", val, operands[0]));
2524                self.push_str(&format!(
2525                    "auto {} = ({})({}.data());\n",
2526                    ptr,
2527                    self.r#gen.r#gen.opts.ptr_type(),
2528                    val
2529                ));
2530                self.push_str(&format!("auto {} = (size_t)({}.size());\n", len, val));
2531                self.push_str(&format!("for (size_t i = 0; i < {len}; ++i) {{\n"));
2532                self.push_str(&format!(
2533                    "auto base = {ptr} + i * {size};\n",
2534                    size = size.format(POINTER_SIZE_EXPRESSION)
2535                ));
2536                self.push_str(&format!("auto&& IterElem = {val}[i];\n"));
2537                self.push_str(&format!("{}\n", body.0));
2538                self.push_str("}\n");
2539                if realloc.is_none() {
2540                    results.push(ptr);
2541                } else {
2542                    uwriteln!(self.src, "{}.leak();\n", operands[0]);
2543                    results.push(ptr);
2544                }
2545                results.push(len);
2546            }
2547            abi::Instruction::ListCanonLift { element, .. } => {
2548                let tmp = self.tmp();
2549                let len = format!("len{}", tmp);
2550                let inner = self
2551                    .r#gen
2552                    .type_name(element, &self.namespace, Flavor::InStruct);
2553                self.push_str(&format!("auto {} = {};\n", len, operands[1]));
2554                let result = if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2555                    && matches!(self.variant, AbiVariant::GuestExport)
2556                {
2557                    format!(
2558                        "wit::vector<{inner} const>(({inner}*)({}), {len}).get_view()",
2559                        operands[0]
2560                    )
2561                } else {
2562                    format!("wit::vector<{inner}>(({inner}*)({}), {len})", operands[0])
2563                };
2564                results.push(result);
2565            }
2566            abi::Instruction::StringLift => {
2567                let tmp = self.tmp();
2568                let len = format!("len{}", tmp);
2569                uwriteln!(self.src, "auto {} = {};\n", len, operands[1]);
2570                let result = if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2571                    && matches!(self.variant, AbiVariant::GuestExport)
2572                {
2573                    assert!(self.needs_dealloc);
2574                    uwriteln!(
2575                        self.src,
2576                        "if ({len}>0) _deallocate.push_back({});\n",
2577                        operands[0]
2578                    );
2579                    format!("std::string_view((char const*)({}), {len})", operands[0])
2580                } else {
2581                    format!("wit::string((char const*)({}), {len})", operands[0])
2582                };
2583                results.push(result);
2584            }
2585            abi::Instruction::ListLift { element, .. } => {
2586                let body = self.blocks.pop().unwrap();
2587                let tmp = self.tmp();
2588                let size = self.r#gen.sizes.size(element);
2589                let _align = self.r#gen.sizes.align(element);
2590                let flavor = if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2591                    && matches!(self.variant, AbiVariant::GuestExport)
2592                {
2593                    Flavor::BorrowedArgument
2594                } else {
2595                    Flavor::InStruct
2596                };
2597                let vtype = self.r#gen.type_name(element, &self.namespace, flavor);
2598                let len = format!("len{tmp}");
2599                let base = format!("base{tmp}");
2600                let result = format!("result{tmp}");
2601                self.push_str(&format!(
2602                    "auto {base} = {operand0};\n",
2603                    operand0 = operands[0]
2604                ));
2605                self.push_str(&format!(
2606                    "auto {len} = {operand1};\n",
2607                    operand1 = operands[1]
2608                ));
2609                self.push_str(&format!(
2610                    r#"auto {result} = wit::vector<{vtype}>::allocate({len});
2611                    "#,
2612                ));
2613
2614                if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2615                    && matches!(self.variant, AbiVariant::GuestExport)
2616                {
2617                    assert!(self.needs_dealloc);
2618                    self.push_str(&format!("if ({len}>0) _deallocate.push_back({base});\n"));
2619                }
2620
2621                uwriteln!(self.src, "for (unsigned i=0; i<{len}; ++i) {{");
2622                uwriteln!(
2623                    self.src,
2624                    "auto base = {base} + i * {size};",
2625                    size = size.format(POINTER_SIZE_EXPRESSION)
2626                );
2627                uwrite!(self.src, "{}", body.0);
2628                uwriteln!(self.src, "auto e{tmp} = {};", move_if_necessary(&body.1[0]));
2629                if let Some(code) = self.leak_on_insertion.take() {
2630                    assert!(self.needs_dealloc);
2631                    uwriteln!(self.src, "{code}");
2632                }
2633                // inplace construct
2634                uwriteln!(self.src, "{result}.initialize(i, std::move(e{tmp}));");
2635                uwriteln!(self.src, "}}");
2636
2637                if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2638                    && matches!(self.variant, AbiVariant::GuestExport)
2639                {
2640                    results.push(format!("{result}.get_const_view()"));
2641                    if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
2642                        && matches!(self.variant, AbiVariant::GuestExport)
2643                    {
2644                        self.leak_on_insertion.replace(format!(
2645                            "if ({len}>0) _deallocate.push_back((void*){result}.leak());\n"
2646                        ));
2647                    }
2648                } else {
2649                    results.push(move_if_necessary(&result));
2650                }
2651            }
2652            abi::Instruction::IterElem { .. } => results.push("IterElem".to_string()),
2653            abi::Instruction::IterBasePointer => results.push("base".to_string()),
2654            abi::Instruction::RecordLower { record, .. } => {
2655                let op = &operands[0];
2656                for f in record.fields.iter() {
2657                    results.push(format!("({}).{}", op, to_c_ident(&f.name)));
2658                }
2659            }
2660            abi::Instruction::RecordLift { record, ty, .. } => {
2661                let mut result =
2662                    self.r#gen
2663                        .type_name(&Type::Id(*ty), &self.namespace, Flavor::InStruct);
2664                result.push('{');
2665                for (_field, val) in record.fields.iter().zip(operands) {
2666                    result.push_str(&(move_if_necessary(val) + ", "));
2667                }
2668                result.push('}');
2669                results.push(result);
2670            }
2671            abi::Instruction::HandleLower {
2672                handle: Handle::Own(ty),
2673                ..
2674            } => {
2675                let op = &operands[0];
2676
2677                // Check if this is an imported or exported resource
2678                let resource_ty = &self.r#gen.resolve.types[*ty];
2679                let resource_ty = match &resource_ty.kind {
2680                    TypeDefKind::Type(Type::Id(id)) => &self.r#gen.resolve.types[*id],
2681                    _ => resource_ty,
2682                };
2683                let is_exported = self.r#gen.is_exported_type(resource_ty);
2684
2685                if is_exported {
2686                    // Exported resources use .release()->handle
2687                    results.push(format!("{op}.release()->handle"));
2688                } else {
2689                    // Imported resources use .into_handle()
2690                    results.push(format!("{op}.into_handle()"));
2691                }
2692            }
2693            abi::Instruction::HandleLower {
2694                handle: Handle::Borrow(_),
2695                ..
2696            } => {
2697                let op = &operands[0];
2698                if op == "(*this)" {
2699                    // TODO is there a better way to decide?
2700                    results.push(format!("{op}.get_handle()"));
2701                } else {
2702                    results.push(format!("{op}.get().get_handle()"));
2703                }
2704            }
2705            abi::Instruction::HandleLift { handle, .. } => {
2706                let op = &operands[0];
2707                match (handle, false) {
2708                    (Handle::Own(ty), true) => match self.variant {
2709                        AbiVariant::GuestExport => {
2710                            results.push(format!("wit::{RESOURCE_EXPORT_BASE_CLASS_NAME}{{{op}}}"))
2711                        }
2712                        AbiVariant::GuestImport => {
2713                            let tmp = self.tmp();
2714                            let var = self.tempname("obj", tmp);
2715                            let tname = self.r#gen.type_name(
2716                                &Type::Id(*ty),
2717                                &self.namespace,
2718                                Flavor::Argument(self.variant),
2719                            );
2720                            uwriteln!(
2721                                self.src,
2722                                "auto {var} = {tname}::remove_resource({op});
2723                                assert({var}.has_value());"
2724                            );
2725                            results.push(format!("{tname}::Owned(*{var})"));
2726                        }
2727                        AbiVariant::GuestImportAsync => todo!(),
2728                        AbiVariant::GuestExportAsync => todo!(),
2729                        AbiVariant::GuestExportAsyncStackful => todo!(),
2730                    },
2731                    (Handle::Own(ty), false) => match self.variant {
2732                        AbiVariant::GuestImport => {
2733                            results.push(format!("wit::{RESOURCE_IMPORT_BASE_CLASS_NAME}{{{op}}}"))
2734                        }
2735                        AbiVariant::GuestExport => {
2736                            let tmp = self.tmp();
2737                            let var = self.tempname("obj", tmp);
2738                            let tname = self.r#gen.type_name(
2739                                &Type::Id(*ty),
2740                                &self.namespace,
2741                                Flavor::Argument(self.variant),
2742                            );
2743
2744                            // Check if this is an imported or exported resource
2745                            let resource_ty = &self.r#gen.resolve.types[*ty];
2746                            let resource_ty = match &resource_ty.kind {
2747                                TypeDefKind::Type(Type::Id(id)) => &self.r#gen.resolve.types[*id],
2748                                _ => resource_ty,
2749                            };
2750                            let is_exported = self.r#gen.is_exported_type(resource_ty);
2751
2752                            if is_exported {
2753                                // Exported resources use ::Owned typedef
2754                                uwriteln!(
2755                                    self.src,
2756                                    "auto {var} = {tname}::Owned({tname}::ResourceRep({op}));"
2757                                );
2758                            } else {
2759                                // Imported resources construct from ResourceImportBase
2760                                uwriteln!(
2761                                    self.src,
2762                                    "auto {var} = {tname}(wit::{RESOURCE_IMPORT_BASE_CLASS_NAME}{{{op}}});"
2763                                );
2764                            }
2765
2766                            results.push(format!("std::move({var})"))
2767                        }
2768                        AbiVariant::GuestImportAsync => todo!(),
2769                        AbiVariant::GuestExportAsync => todo!(),
2770                        AbiVariant::GuestExportAsyncStackful => todo!(),
2771                    },
2772                    (Handle::Borrow(ty), true) => {
2773                        let tname = self.r#gen.type_name(
2774                            &Type::Id(*ty),
2775                            &self.namespace,
2776                            Flavor::Argument(self.variant),
2777                        );
2778                        results.push(format!("**{tname}::lookup_resource({op})"));
2779                    }
2780                    (Handle::Borrow(ty), false) => match self.variant {
2781                        AbiVariant::GuestImport => results.push(op.clone()),
2782                        AbiVariant::GuestExport => {
2783                            let tname = self.r#gen.type_name(
2784                                &Type::Id(*ty),
2785                                &self.namespace,
2786                                Flavor::Argument(self.variant),
2787                            );
2788                            results.push(format!("std::ref(*({tname} *){op})"));
2789                        }
2790                        AbiVariant::GuestImportAsync => todo!(),
2791                        AbiVariant::GuestExportAsync => todo!(),
2792                        AbiVariant::GuestExportAsyncStackful => todo!(),
2793                    },
2794                }
2795            }
2796            abi::Instruction::TupleLower { tuple, .. } => {
2797                let op = &operands[0];
2798                for n in 0..tuple.types.len() {
2799                    results.push(format!("std::get<{n}>({op})"));
2800                }
2801            }
2802            abi::Instruction::TupleLift { tuple, .. } => {
2803                let name = format!("tuple{}", self.tmp());
2804                uwrite!(self.src, "auto {name} = std::tuple<");
2805                self.src.push_str(
2806                    &(tuple
2807                        .types
2808                        .iter()
2809                        .map(|t| self.r#gen.type_name(t, &self.namespace, Flavor::InStruct)))
2810                    .collect::<Vec<_>>()
2811                    .join(", "),
2812                );
2813                self.src.push_str(">(");
2814                self.src.push_str(
2815                    &operands
2816                        .iter()
2817                        .map(|op| move_if_necessary(op))
2818                        .collect::<Vec<_>>()
2819                        .join(", "),
2820                );
2821                self.src.push_str(");\n");
2822                results.push(format!("std::move({name})"));
2823            }
2824            abi::Instruction::FlagsLower { flags, ty, .. } => {
2825                match wit_bindgen_c::flags_repr(flags) {
2826                    Int::U8 | Int::U16 | Int::U32 => {
2827                        results.push(format!("((int32_t){})", operands.pop().unwrap()));
2828                    }
2829                    Int::U64 => {
2830                        let name =
2831                            self.r#gen
2832                                .type_name(&Type::Id(*ty), &self.namespace, Flavor::InStruct);
2833                        let tmp = self.tmp();
2834                        let tempname = self.tempname("flags", tmp);
2835                        uwriteln!(self.src, "{name} {tempname} = {};", operands[0]);
2836                        results.push(format!("(int32_t)(((uint64_t){tempname}) & 0xffffffff)"));
2837                        results.push(format!(
2838                            "(int32_t)((((uint64_t){tempname}) >> 32) & 0xffffffff)"
2839                        ));
2840                    }
2841                }
2842            }
2843            abi::Instruction::FlagsLift { flags, ty, .. } => {
2844                let typename =
2845                    self.r#gen
2846                        .type_name(&Type::Id(*ty), &self.namespace, Flavor::InStruct);
2847                match wit_bindgen_c::flags_repr(flags) {
2848                    Int::U8 | Int::U16 | Int::U32 => {
2849                        results.push(format!("(({typename}){})", operands.pop().unwrap()));
2850                    }
2851                    Int::U64 => {
2852                        let op0 = &operands[0];
2853                        let op1 = &operands[1];
2854                        results.push(format!(
2855                            "(({typename})(({op0}) | (((uint64_t)({op1})) << 32)))"
2856                        ));
2857                    }
2858                }
2859            }
2860            abi::Instruction::VariantPayloadName => {
2861                let name = format!("payload{}", self.tmp());
2862                results.push(name.clone());
2863                self.payloads.push(name);
2864            }
2865            abi::Instruction::VariantLower {
2866                variant,
2867                results: result_types,
2868                ty: var_ty,
2869                name: _var_name,
2870                ..
2871            } => {
2872                let blocks = self
2873                    .blocks
2874                    .drain(self.blocks.len() - variant.cases.len()..)
2875                    .collect::<Vec<_>>();
2876                let payloads = self
2877                    .payloads
2878                    .drain(self.payloads.len() - variant.cases.len()..)
2879                    .collect::<Vec<_>>();
2880
2881                let mut variant_results = Vec::with_capacity(result_types.len());
2882                for ty in result_types.iter() {
2883                    let name = format!("variant{}", self.tmp());
2884                    results.push(name.clone());
2885                    self.src.push_str(wit_bindgen_c::wasm_type(*ty));
2886                    self.src.push_str(" ");
2887                    self.src.push_str(&name);
2888                    self.src.push_str(";\n");
2889                    variant_results.push(name);
2890                }
2891
2892                let expr_to_match = format!("({}).variants.index()", operands[0]);
2893                let elem_ns =
2894                    self.r#gen
2895                        .type_name(&Type::Id(*var_ty), &self.namespace, Flavor::InStruct);
2896
2897                uwriteln!(self.src, "switch ((int32_t) {}) {{", expr_to_match);
2898                for (i, ((case, (block, block_results)), payload)) in
2899                    variant.cases.iter().zip(blocks).zip(payloads).enumerate()
2900                {
2901                    uwriteln!(self.src, "case {}: {{", i);
2902                    if case.ty.is_some() {
2903                        let case =
2904                            format!("{elem_ns}::{}", to_c_ident(&case.name).to_pascal_case());
2905                        uwriteln!(
2906                            self.src,
2907                            "auto& {} = std::get<{case}>({}.variants).value;",
2908                            payload,
2909                            operands[0],
2910                        );
2911                    }
2912
2913                    self.src.push_str(&block);
2914
2915                    for (name, result) in variant_results.iter().zip(&block_results) {
2916                        uwriteln!(self.src, "{} = {};", name, result);
2917                    }
2918                    self.src.push_str("break;\n}\n");
2919                }
2920                self.src.push_str("}\n");
2921            }
2922            abi::Instruction::VariantLift { variant, ty, .. } => {
2923                let blocks = self
2924                    .blocks
2925                    .drain(self.blocks.len() - variant.cases.len()..)
2926                    .collect::<Vec<_>>();
2927
2928                let ty = self
2929                    .r#gen
2930                    .type_name(&Type::Id(*ty), &self.namespace, Flavor::InStruct);
2931                let resultno = self.tmp();
2932                let result = format!("variant{resultno}");
2933
2934                let op0 = &operands[0];
2935
2936                // Use std::optional to avoid default constructor issues
2937                self.r#gen.r#gen.dependencies.needs_optional = true;
2938                uwriteln!(self.src, "std::optional<{ty}> {result}_opt;");
2939                uwriteln!(self.src, "switch ({op0}) {{");
2940                for (i, (case, (block, block_results))) in
2941                    variant.cases.iter().zip(blocks).enumerate()
2942                {
2943                    let tp = to_c_ident(&case.name).to_pascal_case();
2944                    uwriteln!(self.src, "case {i}: {{ {block}");
2945                    uwriteln!(
2946                        self.src,
2947                        "{result}_opt = {ty}{{{{{ty}::{tp}{{{}}}}}}};",
2948                        move_if_necessary(&block_results.first().cloned().unwrap_or_default())
2949                    );
2950                    uwriteln!(self.src, "}} break;");
2951                }
2952                uwriteln!(self.src, "}}");
2953                uwriteln!(self.src, "{ty} {result} = std::move(*{result}_opt);");
2954
2955                results.push(result);
2956            }
2957            abi::Instruction::EnumLower { .. } => results.push(format!("int32_t({})", operands[0])),
2958            abi::Instruction::EnumLift { ty, .. } => {
2959                let typename =
2960                    self.r#gen
2961                        .type_name(&Type::Id(*ty), &self.namespace, Flavor::InStruct);
2962                results.push(format!("({typename}){}", &operands[0]));
2963            }
2964            abi::Instruction::OptionLower {
2965                payload,
2966                results: result_types,
2967                ..
2968            } => {
2969                let (mut some, some_results) = self.blocks.pop().unwrap();
2970                let (mut none, none_results) = self.blocks.pop().unwrap();
2971                let some_payload = self.payloads.pop().unwrap();
2972                let _none_payload = self.payloads.pop().unwrap();
2973
2974                for (i, ty) in result_types.iter().enumerate() {
2975                    let tmp = self.tmp();
2976                    let name = self.tempname("option", tmp);
2977                    results.push(name.clone());
2978                    self.src.push_str(wit_bindgen_c::wasm_type(*ty));
2979                    self.src.push_str(" ");
2980                    self.src.push_str(&name);
2981                    self.src.push_str(";\n");
2982                    let some_result = &some_results[i];
2983                    uwriteln!(some, "{name} = {some_result};");
2984                    let none_result = &none_results[i];
2985                    uwriteln!(none, "{name} = {none_result};");
2986                }
2987
2988                let op0 = &operands[0];
2989                let flavor = if matches!(self.variant, AbiVariant::GuestImport) {
2990                    Flavor::BorrowedArgument
2991                } else {
2992                    Flavor::InStruct
2993                };
2994                let ty = self.r#gen.type_name(payload, &self.namespace, flavor);
2995                let is_function_param = self.params.iter().any(|p| p == op0);
2996                let value_extract = if matches!(payload, Type::String)
2997                    && matches!(self.variant, AbiVariant::GuestImport)
2998                    && !is_function_param
2999                {
3000                    // Import from struct/variant field: optional<wit::string> needs .get_view()
3001                    format!("(std::move({op0})).value().get_view()")
3002                } else {
3003                    // Direct parameter, export, or non-string: just .value()
3004                    format!("(std::move({op0})).value()")
3005                };
3006                let bind_some = format!("{ty} {some_payload} = {value_extract};");
3007
3008                uwrite!(
3009                    self.src,
3010                    "\
3011                    if (({op0}).has_value()) {{
3012                        {bind_some}
3013                        {some}}} else {{
3014                        {none}}}
3015                    "
3016                );
3017            }
3018            abi::Instruction::OptionLift { payload, .. } => {
3019                let (some, some_results) = self.blocks.pop().unwrap();
3020                let (_none, none_results) = self.blocks.pop().unwrap();
3021                assert!(none_results.is_empty());
3022                assert!(some_results.len() == 1);
3023                let flavor = if self.r#gen.r#gen.opts.api_style == APIStyle::Symmetric
3024                    && matches!(self.variant, AbiVariant::GuestExport)
3025                {
3026                    Flavor::BorrowedArgument
3027                } else {
3028                    Flavor::InStruct
3029                };
3030                let type_name = self.r#gen.type_name(payload, &self.namespace, flavor);
3031                let full_type = format!("std::optional<{type_name}>");
3032                let op0 = &operands[0];
3033
3034                let tmp = self.tmp();
3035                let resultname = self.tempname("option", tmp);
3036                let some_value = move_if_necessary(&some_results[0]);
3037                uwriteln!(
3038                    self.src,
3039                    "{full_type} {resultname};
3040                    if ({op0}) {{
3041                        {some}
3042                        {resultname}.emplace({some_value});
3043                    }}"
3044                );
3045                results.push(format!("std::move({resultname})"));
3046            }
3047            abi::Instruction::ResultLower {
3048                results: result_types,
3049                result,
3050                ..
3051            } => {
3052                let (mut err, err_results) = self.blocks.pop().unwrap();
3053                let (mut ok, ok_results) = self.blocks.pop().unwrap();
3054                let err_payload = self.payloads.pop().unwrap();
3055                let ok_payload = self.payloads.pop().unwrap();
3056
3057                for (i, ty) in result_types.iter().enumerate() {
3058                    let tmp = self.tmp();
3059                    let name = self.tempname("result", tmp);
3060                    results.push(name.clone());
3061                    self.src.push_str(wit_bindgen_c::wasm_type(*ty));
3062                    self.src.push_str(" ");
3063                    self.src.push_str(&name);
3064                    self.src.push_str(";\n");
3065                    let ok_result = &ok_results[i];
3066                    uwriteln!(ok, "{name} = {ok_result};");
3067                    let err_result = &err_results[i];
3068                    uwriteln!(err, "{name} = {err_result};");
3069                }
3070
3071                let op0 = &operands[0];
3072                let ok_ty = self.r#gen.optional_type_name(
3073                    result.ok.as_ref(),
3074                    &self.namespace,
3075                    Flavor::InStruct,
3076                );
3077                let err_ty = self.r#gen.optional_type_name(
3078                    result.err.as_ref(),
3079                    &self.namespace,
3080                    Flavor::InStruct,
3081                );
3082                let bind_ok = if let Some(_ok) = result.ok.as_ref() {
3083                    format!("{ok_ty} {ok_payload} = std::move({op0}).value();")
3084                } else {
3085                    String::new()
3086                };
3087                let bind_err = if let Some(_err) = result.err.as_ref() {
3088                    format!("{err_ty} {err_payload} = std::move({op0}).error();")
3089                } else {
3090                    String::new()
3091                };
3092
3093                uwrite!(
3094                    self.src,
3095                    "\
3096                    if (({op0}).has_value()) {{
3097                        {bind_ok}
3098                        {ok}}} else {{
3099                        {bind_err}
3100                        {err}}}
3101                    "
3102                );
3103            }
3104            abi::Instruction::ResultLift { result, .. } => {
3105                let (mut err, err_results) = self.blocks.pop().unwrap();
3106                let (mut ok, ok_results) = self.blocks.pop().unwrap();
3107                let mut ok_result = String::new();
3108                let err_result;
3109                if result.ok.is_none() {
3110                    ok.clear();
3111                } else {
3112                    ok_result = move_if_necessary(&ok_results[0]);
3113                }
3114                if result.err.is_none() {
3115                    err.clear();
3116                    self.r#gen.r#gen.dependencies.needs_wit = true;
3117                    err_result = String::from("wit::Void{}");
3118                } else {
3119                    err_result = move_if_necessary(&err_results[0]);
3120                }
3121                let ok_type = self.r#gen.optional_type_name(
3122                    result.ok.as_ref(),
3123                    &self.namespace,
3124                    Flavor::InStruct,
3125                );
3126                let err_type = result.err.as_ref().map_or(String::from("wit::Void"), |ty| {
3127                    self.r#gen.type_name(ty, &self.namespace, Flavor::InStruct)
3128                });
3129                let full_type = format!("std::expected<{ok_type}, {err_type}>",);
3130                let err_type = "std::unexpected";
3131                let operand = &operands[0];
3132
3133                let tmp = self.tmp();
3134                let resultname = self.tempname("result", tmp);
3135                // Use std::optional to avoid default constructor issues with std::expected
3136                self.r#gen.r#gen.dependencies.needs_optional = true;
3137                let ok_assign = if result.ok.is_some() {
3138                    format!("{resultname}_opt.emplace({full_type}({ok_result}));")
3139                } else {
3140                    format!("{resultname}_opt.emplace({full_type}());")
3141                };
3142                uwriteln!(
3143                    self.src,
3144                    "std::optional<{full_type}> {resultname}_opt;
3145                    if ({operand}==0) {{
3146                        {ok}
3147                        {ok_assign}
3148                    }} else {{
3149                        {err}
3150                        {resultname}_opt.emplace({err_type}{{{err_result}}});
3151                    }}
3152                    {full_type} {resultname} = std::move(*{resultname}_opt);"
3153                );
3154                results.push(resultname);
3155            }
3156            abi::Instruction::CallWasm { name, sig } => {
3157                let module_name = self
3158                    .r#gen
3159                    .wasm_import_module
3160                    .as_ref()
3161                    .map(|e| {
3162                        self.r#gen
3163                            .r#gen
3164                            .import_prefix
3165                            .as_ref()
3166                            .cloned()
3167                            .unwrap_or_default()
3168                            + e
3169                    })
3170                    .unwrap();
3171
3172                let func = self
3173                    .r#gen
3174                    .declare_import(&module_name, name, &sig.params, &sig.results);
3175
3176                // ... then call the function with all our operands
3177                if !sig.results.is_empty() {
3178                    self.src.push_str("auto ret = ");
3179                    results.push("ret".to_string());
3180                }
3181                self.src.push_str(&func);
3182                self.src.push_str("(");
3183                self.src.push_str(
3184                    &operands
3185                        .iter()
3186                        .map(|op| move_if_necessary(op))
3187                        .collect::<Vec<_>>()
3188                        .join(", "),
3189                );
3190                self.src.push_str(");\n");
3191            }
3192            abi::Instruction::CallInterface { func, .. } => {
3193                // dbg!(func);
3194                self.let_results(if func.result.is_some() { 1 } else { 0 }, results);
3195                let (namespace, func_name_h) = self.r#gen.func_namespace_name(func, true, true);
3196                if matches!(func.kind, FunctionKind::Method(_)) {
3197                    let this = operands.remove(0);
3198                    uwrite!(self.src, "({this}).get().");
3199                } else {
3200                    let mut relative = SourceWithState::default();
3201                    relative.qualify(&namespace);
3202                    self.push_str(&relative.src);
3203                }
3204                self.src.push_str(&func_name_h);
3205                self.push_str("(");
3206                self.push_str(
3207                    &operands
3208                        .iter()
3209                        .map(|op| move_if_necessary(op))
3210                        .collect::<Vec<_>>()
3211                        .join(", "),
3212                );
3213                self.push_str(");\n");
3214                if self.needs_dealloc {
3215                    uwriteln!(
3216                        self.src,
3217                        "for (auto i: _deallocate) {{ free(i); }}\n
3218                        _deallocate.clear();"
3219                    );
3220                }
3221            }
3222            abi::Instruction::Return { amt, func } => {
3223                match amt {
3224                    0 => {}
3225                    _ => {
3226                        assert!(*amt == operands.len());
3227                        // Fallible constructors return expected, not void
3228                        let is_fallible_constructor = self
3229                            .r#gen
3230                            .r#gen
3231                            .is_fallible_constructor(self.r#gen.resolve, func);
3232
3233                        match &func.kind {
3234                            FunctionKind::Constructor(_)
3235                                if self.r#gen.r#gen.opts.is_only_handle(self.variant)
3236                                    && !is_fallible_constructor =>
3237                            {
3238                                // strange but works
3239                                if matches!(self.variant, AbiVariant::GuestExport) {
3240                                    self.src.push_str("this->index = ");
3241                                } else {
3242                                    self.src.push_str("this->handle = ");
3243                                }
3244                            }
3245                            _ => self.src.push_str("return "),
3246                        }
3247                        if let Some(CabiPostInformation {
3248                            module: _,
3249                            name: _cabi_post_name,
3250                            ret_type: cabi_post_type,
3251                        }) = self.cabi_post.as_ref()
3252                        {
3253                            self.src.push_str("wit::guest_owned<");
3254                            self.src.push_str(cabi_post_type);
3255                            self.src.push_str(">(");
3256                        }
3257                        if *amt == 1 {
3258                            if operands[0].starts_with("std::move(") {
3259                                // remove the std::move due to return value optimization (and complex rules about when std::move harms)
3260                                self.src.push_str(&operands[0][9..]);
3261                            } else {
3262                                self.src.push_str(&operands[0]);
3263                            }
3264                        } else {
3265                            todo!();
3266                        }
3267                        if let Some(CabiPostInformation {
3268                            module: func_module,
3269                            name: func_name,
3270                            ret_type: _cabi_post_type,
3271                        }) = self.cabi_post.as_ref()
3272                        {
3273                            let cabi_post_name = self.r#gen.declare_import(
3274                                &format!("cabi_post_{func_module}"),
3275                                func_name,
3276                                &[WasmType::Pointer],
3277                                &[],
3278                            );
3279                            self.src.push_str(&format!(", ret, {})", cabi_post_name));
3280                        }
3281                        if matches!(func.kind, FunctionKind::Constructor(_))
3282                            && self.r#gen.r#gen.opts.is_only_handle(self.variant)
3283                            && !is_fallible_constructor
3284                        {
3285                            // we wrapped the handle in an object, so unpack it
3286
3287                            self.src.push_str(".into_handle()");
3288                        }
3289                        self.src.push_str(";\n");
3290                    }
3291                }
3292            }
3293            abi::Instruction::Malloc { .. } => todo!(),
3294            abi::Instruction::GuestDeallocate { .. } => {
3295                uwriteln!(self.src, "free((void*) ({}));", operands[0]);
3296            }
3297            abi::Instruction::GuestDeallocateString => {
3298                uwriteln!(self.src, "if (({}) > 0) {{", operands[1]);
3299                uwriteln!(
3300                    self.src,
3301                    "wit::string::drop_raw((void*) ({}));",
3302                    operands[0]
3303                );
3304                uwriteln!(self.src, "}}");
3305            }
3306            abi::Instruction::GuestDeallocateList { element } => {
3307                let (body, results) = self.blocks.pop().unwrap();
3308                assert!(results.is_empty());
3309                let tmp = self.tmp();
3310                let ptr = self.tempname("ptr", tmp);
3311                let len = self.tempname("len", tmp);
3312                uwriteln!(self.src, "uint8_t* {ptr} = {};", operands[0]);
3313                uwriteln!(self.src, "size_t {len} = {};", operands[1]);
3314                let i = self.tempname("i", tmp);
3315                uwriteln!(self.src, "for (size_t {i} = 0; {i} < {len}; {i}++) {{");
3316                let size = self.r#gen.sizes.size(element);
3317                uwriteln!(
3318                    self.src,
3319                    "uint8_t* base = {ptr} + {i} * {size};",
3320                    size = size.format(POINTER_SIZE_EXPRESSION)
3321                );
3322                uwriteln!(self.src, "(void) base;");
3323                uwrite!(self.src, "{body}");
3324                uwriteln!(self.src, "}}");
3325                uwriteln!(self.src, "if ({len} > 0) {{");
3326                uwriteln!(self.src, "free((void*) ({ptr}));");
3327                uwriteln!(self.src, "}}");
3328            }
3329            abi::Instruction::GuestDeallocateVariant { blocks } => {
3330                let blocks = self
3331                    .blocks
3332                    .drain(self.blocks.len() - blocks..)
3333                    .collect::<Vec<_>>();
3334
3335                uwriteln!(self.src, "switch ((int32_t) {}) {{", operands[0]);
3336                for (i, (block, results)) in blocks.into_iter().enumerate() {
3337                    assert!(results.is_empty());
3338                    uwriteln!(self.src, "case {}: {{", i);
3339                    self.src.push_str(&block);
3340                    self.src.push_str("break;\n}\n");
3341                }
3342                self.src.push_str("}\n");
3343            }
3344            abi::Instruction::PointerLoad { offset } => {
3345                let ptr_type = self.r#gen.r#gen.opts.ptr_type();
3346                self.load(ptr_type, *offset, operands, results)
3347            }
3348            abi::Instruction::LengthLoad { offset } => {
3349                self.load("size_t", *offset, operands, results)
3350            }
3351            abi::Instruction::PointerStore { offset } => {
3352                let ptr_type = self.r#gen.r#gen.opts.ptr_type();
3353                self.store(ptr_type, *offset, operands)
3354            }
3355            abi::Instruction::LengthStore { offset } => self.store("size_t", *offset, operands),
3356            abi::Instruction::FutureLower { .. } => todo!(),
3357            abi::Instruction::FutureLift { .. } => todo!(),
3358            abi::Instruction::StreamLower { .. } => todo!(),
3359            abi::Instruction::StreamLift { .. } => todo!(),
3360            abi::Instruction::ErrorContextLower { .. } => todo!(),
3361            abi::Instruction::ErrorContextLift { .. } => todo!(),
3362            abi::Instruction::Flush { amt } => {
3363                for i in operands.iter().take(*amt) {
3364                    let tmp = self.tmp();
3365                    let result = format!("result{}", tmp);
3366                    uwriteln!(self.src, "auto {result} = {};", move_if_necessary(i));
3367                    results.push(result);
3368                }
3369            }
3370            abi::Instruction::AsyncTaskReturn { .. } => todo!(),
3371            abi::Instruction::DropHandle { .. } => todo!(),
3372        }
3373    }
3374
3375    fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> Self::Operand {
3376        // Track maximum return area requirements
3377        self.return_pointer_area_size = self.return_pointer_area_size.max(size);
3378        self.return_pointer_area_align = self.return_pointer_area_align.max(align);
3379
3380        // Generate pointer to shared ret_area
3381        let tmp = self.tmp();
3382        uwriteln!(
3383            self.src,
3384            "{} ptr{tmp} = ({0})(&ret_area);",
3385            self.r#gen.r#gen.opts.ptr_type(),
3386        );
3387
3388        format!("ptr{}", tmp)
3389    }
3390
3391    fn push_block(&mut self) {
3392        let prev = core::mem::take(&mut self.src);
3393        self.block_storage.push(prev);
3394    }
3395
3396    fn finish_block(&mut self, operands: &mut Vec<Self::Operand>) {
3397        let to_restore = self.block_storage.pop().unwrap();
3398        let src = core::mem::replace(&mut self.src, to_restore);
3399        self.blocks.push((src.into(), core::mem::take(operands)));
3400    }
3401
3402    fn sizes(&self) -> &wit_bindgen_core::wit_parser::SizeAlign {
3403        &self.r#gen.sizes
3404    }
3405
3406    fn is_list_canonical(
3407        &self,
3408        resolve: &Resolve,
3409        ty: &wit_bindgen_core::wit_parser::Type,
3410    ) -> bool {
3411        if !resolve.all_bits_valid(ty) {
3412            return false;
3413        }
3414        match ty {
3415            Type::Id(id) => !self.r#gen.r#gen.types.get(*id).has_resource,
3416            _ => true,
3417        }
3418    }
3419}
3420
3421/// This describes the common ABI function referenced or implemented, the C++ side might correspond to a different type
3422enum SpecialMethod {
3423    None,
3424    ResourceDrop, // ([export]) [resource-drop]
3425    ResourceNew,  // [export][resource-new]
3426    ResourceRep,  // [export][resource-rep]
3427    Dtor,         // [dtor] (guest export only)
3428    Allocate,     // internal: allocate new object (called from generated code)
3429}
3430
3431fn is_special_method(func: &Function) -> SpecialMethod {
3432    if matches!(func.kind, FunctionKind::Static(_)) {
3433        if func.name.starts_with("[resource-drop]") {
3434            SpecialMethod::ResourceDrop
3435        } else if func.name.starts_with("[resource-new]") {
3436            SpecialMethod::ResourceNew
3437        } else if func.name.starts_with("[resource-rep]") {
3438            SpecialMethod::ResourceRep
3439        } else if func.name.starts_with("[dtor]") {
3440            SpecialMethod::Dtor
3441        } else if func.name == "$alloc" {
3442            SpecialMethod::Allocate
3443        } else {
3444            SpecialMethod::None
3445        }
3446    } else {
3447        SpecialMethod::None
3448    }
3449}