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