Skip to main content

wit_bindgen_go/
lib.rs

1use anyhow::Result;
2use heck::{ToLowerCamelCase as _, ToSnakeCase as _, ToUpperCamelCase as _};
3use std::borrow::Cow;
4use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, hash_map};
5use std::fmt;
6use std::fmt::Write as _;
7use std::io::{self, Write as _};
8use std::iter;
9use std::mem;
10use std::process::Command;
11use std::str::FromStr;
12use std::thread;
13use wit_bindgen_core::abi::{
14    self, AbiVariant, Bindgen, Bitcast, FlatTypes, Instruction, LiftLower, WasmType,
15};
16use wit_bindgen_core::wit_parser::{
17    Alignment, ArchitectureSize, Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Handle, Int,
18    InterfaceId, Package, PackageName, Param, Record, Resolve, Result_, SizeAlign, Tuple, Type,
19    TypeDefKind, TypeId, TypeOwner, Variant, WorldId, WorldKey,
20};
21use wit_bindgen_core::{
22    AsyncFilterSet, Direction, Files, InterfaceGenerator as _, Ns, WorldGenerator, uwriteln,
23};
24
25const MAX_FLAT_PARAMS: usize = 16;
26
27const POINTER_SIZE_EXPRESSION: &str = "4";
28const VARIANT_PAYLOAD_NAME: &str = "payload";
29const ITER_BASE_POINTER: &str = "base";
30const ITER_ELEMENT: &str = "element";
31const IMPORT_RETURN_AREA: &str = "returnArea";
32const EXPORT_RETURN_AREA: &str = "exportReturnArea";
33const SYNC_EXPORT_PINNER: &str = "syncExportPinner";
34const PINNER: &str = "pinner";
35
36/// Adds the shared package repository prefix to a package name.
37fn remote_pkg(name: &str) -> String {
38    let prefix = match name {
39        "types" => "witTypes",
40        "async" => "witAsync",
41        "runtime" => "witRuntime",
42        _ => unimplemented!(),
43    };
44    format!(r#"{prefix} "go.bytecodealliance.org/pkg/wit/{name}""#)
45}
46
47/// The version of github.com/bytecodealliance/go-pkg that's being used
48const REMOTE_PKG_VERSION: &str = "v0.2.1";
49
50/// If a user specifies the `pkg_name` flag, the required version for the
51/// shared remote package isn't recorded. This enables downstream users to retrieve the version programmatically.
52pub fn remote_pkg_version() -> String {
53    format!("go.bytecodealliance.org/pkg {REMOTE_PKG_VERSION}")
54}
55
56#[derive(Default, Debug, Copy, Clone)]
57pub enum Format {
58    #[default]
59    True,
60    False,
61}
62
63impl fmt::Display for Format {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        write!(
66            f,
67            "{}",
68            match self {
69                Self::True => "true",
70                Self::False => "false",
71            }
72        )
73    }
74}
75
76impl FromStr for Format {
77    type Err = String;
78
79    fn from_str(s: &str) -> Result<Format, String> {
80        match s {
81            "true" => Ok(Format::True),
82            "false" => Ok(Format::False),
83            _ => Err(format!("expected `true` or `false`; got `{s}`")),
84        }
85    }
86}
87
88#[derive(Default, Debug, Clone)]
89#[cfg_attr(feature = "clap", derive(clap::Parser))]
90pub struct Opts {
91    /// Whether or not `gofmt` should be used (if present) to format generated
92    /// code.
93    #[cfg_attr(
94        feature = "clap",
95        arg(
96            long,
97            default_value = "true",
98            default_missing_value = "true",
99            num_args = 0..=1,
100            require_equals = true,
101        )
102    )]
103    pub format: Format,
104
105    #[cfg_attr(feature = "clap", clap(flatten))]
106    pub async_: AsyncFilterSet,
107
108    /// If true, generate stub functions for any exported functions and/or
109    /// resources.
110    #[cfg_attr(feature = "clap", clap(long))]
111    pub generate_stubs: bool,
112
113    /// If specified, organize the bindings into a package for use as a library;
114    /// otherwise (if `None`), the bindings will be organized for use as a
115    /// standalone executable.
116    #[cfg_attr(feature = "clap", clap(long))]
117    pub pkg_name: Option<String>,
118
119    /// When `--pkg-name` is specified, optionally specify a different package
120    /// for exports.
121    ///
122    /// This allows you to put the exports and imports in separate packages when
123    /// building a library.  If only `--pkg-name` is specified, this will
124    /// default to that value.
125    #[cfg_attr(feature = "clap", clap(long, requires = "pkg_name"))]
126    pub export_pkg_name: Option<String>,
127
128    /// Print the version of the remote package being used for the shared WIT types.
129    ///
130    /// Must be specified in addition to the `pkg-name` flag.
131    #[cfg_attr(feature = "clap", clap(long))]
132    pub print_remote_pkg_version: bool,
133
134    /// When generating Go package names, include the WIT package version even
135    /// if only one version of that package is referenced by the specified
136    /// world.
137    ///
138    /// By default, the version will only be included in the name if the world
139    /// references more than one version of the WIT package.
140    #[cfg_attr(feature = "clap", clap(long))]
141    pub include_versions: bool,
142}
143
144impl Opts {
145    pub fn build(&self) -> Box<dyn WorldGenerator> {
146        Box::new(Go {
147            opts: self.clone(),
148            ..Go::default()
149        })
150    }
151}
152
153#[derive(Default)]
154struct InterfaceData {
155    code: String,
156    imports: BTreeSet<String>,
157    need_unsafe: bool,
158    need_runtime: bool,
159    need_math: bool,
160}
161
162impl InterfaceData {
163    fn extend(&mut self, data: InterfaceData) {
164        self.code.push_str(&data.code);
165        self.imports.extend(data.imports);
166        self.need_unsafe |= data.need_unsafe;
167        self.need_runtime |= data.need_runtime;
168        self.need_math |= data.need_math;
169    }
170
171    fn imports(&self) -> String {
172        self.imports
173            .iter()
174            .map(|s| s.to_string())
175            .chain(self.need_unsafe.then(|| r#""unsafe""#.into()))
176            .chain(self.need_runtime.then(|| r#""runtime""#.into()))
177            .chain(self.need_math.then(|| r#""math""#.into()))
178            .collect::<Vec<_>>()
179            .join("\n")
180    }
181
182    fn from_generator_and_code(generator: FunctionGenerator<'_>, code: String) -> Self {
183        Self {
184            code,
185            imports: generator.imports,
186            need_unsafe: generator.need_unsafe,
187            need_runtime: generator.need_pinner,
188            need_math: generator.need_math,
189        }
190    }
191}
192
193impl From<InterfaceGenerator<'_>> for InterfaceData {
194    fn from(generator: InterfaceGenerator<'_>) -> Self {
195        Self {
196            code: generator.src,
197            imports: generator.imports,
198            need_unsafe: generator.need_unsafe,
199            need_runtime: generator.need_runtime,
200            need_math: false,
201        }
202    }
203}
204
205#[derive(Default)]
206struct Go {
207    opts: Opts,
208    src: String,
209    sizes: SizeAlign,
210    return_area_size: ArchitectureSize,
211    return_area_align: Alignment,
212    imports: BTreeSet<String>,
213    tuples: BTreeSet<usize>,
214    need_option: bool,
215    need_result: bool,
216    need_math: bool,
217    need_unit: bool,
218    need_future: bool,
219    need_stream: bool,
220    need_unsafe: bool,
221    interface_names: HashMap<InterfaceId, WorldKey>,
222    interfaces: BTreeMap<String, InterfaceData>,
223    export_interfaces: BTreeMap<String, InterfaceData>,
224    types: HashSet<TypeId>,
225    resources: HashMap<TypeId, Direction>,
226    futures_and_streams: HashMap<(TypeId, bool), Option<WorldKey>>,
227}
228
229impl Go {
230    /// Adds the bindings module prefix to a package name.
231    fn mod_pkg(&self, for_export: bool, name: &str) -> String {
232        let prefix = for_export
233            .then_some(())
234            .and(self.opts.export_pkg_name.as_deref())
235            .or(self.opts.pkg_name.as_deref())
236            .unwrap_or("wit_component");
237        format!(r#""{prefix}/{name}""#)
238    }
239
240    fn package_for_owner(
241        &mut self,
242        resolve: &Resolve,
243        owner: Option<&WorldKey>,
244        id: TypeId,
245        local: Option<&WorldKey>,
246        in_import: bool,
247        imports: &mut BTreeSet<String>,
248    ) -> String {
249        let exported = self.has_exported_resource(resolve, Type::Id(id));
250
251        if local == owner && (exported ^ in_import) {
252            String::new()
253        } else {
254            let package = self.interface_name(resolve, owner);
255            let package = if exported {
256                format!("export_{package}")
257            } else {
258                package
259            };
260            let prefix = format!("{package}.");
261            imports.insert(self.mod_pkg(exported, &package));
262            prefix
263        }
264    }
265
266    fn package(
267        &mut self,
268        resolve: &Resolve,
269        id: TypeId,
270        local: Option<&WorldKey>,
271        in_import: bool,
272        imports: &mut BTreeSet<String>,
273    ) -> String {
274        let ty = &resolve.types[id];
275        let owner = match ty.owner {
276            TypeOwner::World(_) => None,
277            TypeOwner::Interface(id) => Some(
278                self.interface_names
279                    .get(&id)
280                    .cloned()
281                    .unwrap_or(WorldKey::Interface(id)),
282            ),
283            TypeOwner::None => unreachable!(),
284        };
285
286        self.package_for_owner(resolve, owner.as_ref(), id, local, in_import, imports)
287    }
288
289    fn type_name(
290        &mut self,
291        resolve: &Resolve,
292        ty: Type,
293        local: Option<&WorldKey>,
294        in_import: bool,
295        imports: &mut BTreeSet<String>,
296    ) -> String {
297        match ty {
298            Type::Bool => "bool".into(),
299            Type::U8 => "uint8".into(),
300            Type::S8 => "int8".into(),
301            Type::U16 => "uint16".into(),
302            Type::S16 => "int16".into(),
303            Type::U32 => "uint32".into(),
304            Type::S32 => "int32".into(),
305            Type::U64 => "uint64".into(),
306            Type::S64 => "int64".into(),
307            Type::F32 => "float32".into(),
308            Type::F64 => "float64".into(),
309            Type::Char => "rune".into(),
310            Type::String => "string".into(),
311            Type::Id(id) => {
312                let ty = &resolve.types[id];
313                match &ty.kind {
314                    TypeDefKind::Record(_)
315                    | TypeDefKind::Flags(_)
316                    | TypeDefKind::Variant(_)
317                    | TypeDefKind::Enum(_)
318                    | TypeDefKind::Resource => {
319                        let package = self.package(resolve, id, local, in_import, imports);
320                        let name = ty.name.as_ref().unwrap().to_upper_camel_case();
321                        format!("{package}{name}")
322                    }
323                    TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
324                        let name =
325                            self.type_name(resolve, Type::Id(*ty), local, in_import, imports);
326                        format!("*{name}")
327                    }
328                    TypeDefKind::Option(ty) => {
329                        imports.insert(remote_pkg("types"));
330                        let ty = self.type_name(resolve, *ty, local, in_import, imports);
331                        format!("witTypes.Option[{ty}]")
332                    }
333                    TypeDefKind::List(ty) => {
334                        let ty = self.type_name(resolve, *ty, local, in_import, imports);
335                        format!("[]{ty}")
336                    }
337                    TypeDefKind::Result(result) => {
338                        imports.insert(remote_pkg("types"));
339                        let ok_type = result
340                            .ok
341                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
342                            .unwrap_or_else(|| {
343                                self.need_unit = true;
344                                "witTypes.Unit".into()
345                            });
346                        let err_type = result
347                            .err
348                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
349                            .unwrap_or_else(|| {
350                                self.need_unit = true;
351                                "witTypes.Unit".into()
352                            });
353                        format!("witTypes.Result[{ok_type}, {err_type}]")
354                    }
355                    TypeDefKind::Tuple(tuple) => {
356                        imports.insert(remote_pkg("types"));
357                        let count = tuple.types.len();
358                        if count > 16 {
359                            todo!(
360                                "tuples can not have a capacity greater than 16: {:?}",
361                                ty.kind
362                            )
363                        }
364                        self.tuples.insert(count);
365                        let types = tuple
366                            .types
367                            .iter()
368                            .map(|ty| self.type_name(resolve, *ty, local, in_import, imports))
369                            .collect::<Vec<_>>()
370                            .join(", ");
371                        format!("witTypes.Tuple{count}[{types}]")
372                    }
373                    TypeDefKind::Future(ty) => {
374                        self.need_future = true;
375                        imports.insert(remote_pkg("types"));
376                        let ty = ty
377                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
378                            .unwrap_or_else(|| {
379                                self.need_unit = true;
380                                "witTypes.Unit".into()
381                            });
382                        format!("*witTypes.FutureReader[{ty}]")
383                    }
384                    TypeDefKind::Stream(ty) => {
385                        self.need_stream = true;
386                        imports.insert(remote_pkg("types"));
387                        let ty = ty
388                            .map(|ty| self.type_name(resolve, ty, local, in_import, imports))
389                            .unwrap_or_else(|| {
390                                self.need_unit = true;
391                                "witTypes.Unit".into()
392                            });
393                        format!("*witTypes.StreamReader[{ty}]")
394                    }
395                    TypeDefKind::Type(ty) => {
396                        self.type_name(resolve, *ty, local, in_import, imports)
397                    }
398                    _ => todo!("{:?}", ty.kind),
399                }
400            }
401            _ => todo!("{ty:?}"),
402        }
403    }
404
405    #[expect(clippy::too_many_arguments, reason = "required context codegen")]
406    fn future_or_stream(
407        &mut self,
408        resolve: &Resolve,
409        ty: TypeId,
410        index: usize,
411        in_import: bool,
412        imported_type: bool,
413        interface: Option<&WorldKey>,
414        func_name: &str,
415    ) -> InterfaceData {
416        let prefix = if in_import { "" } else { "[export]" };
417
418        let module = format!(
419            "{prefix}{}",
420            interface
421                .as_ref()
422                .map(|name| resolve.name_world_key(name))
423                .unwrap_or_else(|| "$root".into())
424        );
425
426        let (payload_ty, kind, count) = match &resolve.types[ty].kind {
427            TypeDefKind::Future(ty) => (*ty, "future", ""),
428            TypeDefKind::Stream(ty) => (*ty, "stream", ", count uint32"),
429            _ => unreachable!(),
430        };
431
432        let upper_kind = kind.to_upper_camel_case();
433
434        let mut data = InterfaceData {
435            need_unsafe: true,
436            ..InterfaceData::default()
437        };
438        data.imports.insert(remote_pkg("types"));
439
440        let (payload, snake) = if let Some(ty) = payload_ty {
441            (
442                self.type_name(resolve, ty, interface, imported_type, &mut data.imports),
443                self.mangle_name(resolve, ty, interface),
444            )
445        } else {
446            self.need_unit = true;
447            ("witTypes.Unit".into(), "unit".into())
448        };
449        let camel = snake.to_upper_camel_case();
450
451        let abi = self.sizes.record(payload_ty.as_ref());
452        let size = abi.size.format(POINTER_SIZE_EXPRESSION);
453        let align = abi.align.format(POINTER_SIZE_EXPRESSION);
454
455        // TODO: Skip lifting/lowering other types that can be used directly in
456        // their canonical form:
457        let (lift, lift_name, lower, lower_name) = match payload_ty {
458            None => (
459                format!(
460                    "func wasm_{kind}_lift_{snake}(src unsafe.Pointer) {payload} {{
461	return witTypes.Unit{{}}
462}}
463"
464                ),
465                format!("wasm_{kind}_lift_{snake}"),
466                String::new(),
467                "nil".to_string(),
468            ),
469            Some(Type::U8 | Type::S8) => (
470                String::new(),
471                "nil".to_string(),
472                String::new(),
473                "nil".to_string(),
474            ),
475            Some(ty) => {
476                data.need_runtime = true;
477
478                let mut generator = FunctionGenerator::new(
479                    self,
480                    None,
481                    None,
482                    interface,
483                    "INVALID",
484                    Vec::new(),
485                    false,
486                    imported_type,
487                );
488                generator.collect_lifters = true;
489
490                let lift_result =
491                    abi::lift_from_memory(resolve, &mut generator, "src".to_string(), &ty);
492                let lift = mem::take(&mut generator.src);
493
494                abi::lower_to_memory(
495                    resolve,
496                    &mut generator,
497                    "dst".to_string(),
498                    "value".to_string(),
499                    &ty,
500                );
501
502                let lifter_count = generator.lifter_count;
503                let (prefix, suffix) = if lifter_count > 0 {
504                    (
505                        format!("lifters := make([]func(), 0, {lifter_count})\n"),
506                        "\nreturn func() {
507        for _, lifter := range lifters {
508                lifter()
509        }
510}",
511                    )
512                } else {
513                    (String::new(), "\nreturn func() {}")
514                };
515
516                let lower = mem::take(&mut generator.src);
517                data.extend(InterfaceData::from_generator_and_code(
518                    generator,
519                    String::new(),
520                ));
521
522                (
523                    format!(
524                        "func wasm_{kind}_lift_{snake}(src unsafe.Pointer) {payload} {{
525        {lift}
526	return {lift_result}
527}}
528"
529                    ),
530                    format!("wasm_{kind}_lift_{snake}"),
531                    format!(
532                        "func wasm_{kind}_lower_{snake}(
533        pinner *runtime.Pinner,
534        value {payload},
535        dst unsafe.Pointer,
536) func() {{
537        {prefix}{lower}{suffix}
538}}
539"
540                    ),
541                    format!("wasm_{kind}_lower_{snake}"),
542                )
543            }
544        };
545
546        data.code = format!(
547            r#"
548//go:wasmimport {module} [{kind}-new-{index}]{func_name}
549func wasm_{kind}_new_{snake}() uint64
550
551//go:wasmimport {module} [async-lower][{kind}-read-{index}]{func_name}
552func wasm_{kind}_read_{snake}(handle int32, item unsafe.Pointer{count}) uint32
553
554//go:wasmimport {module} [async-lower][{kind}-write-{index}]{func_name}
555func wasm_{kind}_write_{snake}(handle int32, item unsafe.Pointer{count}) uint32
556
557//go:wasmimport {module} [{kind}-drop-readable-{index}]{func_name}
558func wasm_{kind}_drop_readable_{snake}(handle int32)
559
560//go:wasmimport {module} [{kind}-drop-writable-{index}]{func_name}
561func wasm_{kind}_drop_writable_{snake}(handle int32)
562
563{lift}
564
565{lower}
566
567var wasm_{kind}_vtable_{snake} = witTypes.{upper_kind}Vtable[{payload}]{{
568	{size},
569	{align},
570	wasm_{kind}_read_{snake},
571	wasm_{kind}_write_{snake},
572	nil,
573	nil,
574	wasm_{kind}_drop_readable_{snake},
575	wasm_{kind}_drop_writable_{snake},
576	{lift_name},
577	{lower_name},
578}}
579
580func Make{upper_kind}{camel}() (*witTypes.{upper_kind}Writer[{payload}], *witTypes.{upper_kind}Reader[{payload}]) {{
581	pair := wasm_{kind}_new_{snake}()
582	return witTypes.Make{upper_kind}Writer[{payload}](&wasm_{kind}_vtable_{snake}, int32(pair >> 32)),
583		witTypes.Make{upper_kind}Reader[{payload}](&wasm_{kind}_vtable_{snake}, int32(pair & 0xFFFFFFFF))
584}}
585
586func Lift{upper_kind}{camel}(handle int32) *witTypes.{upper_kind}Reader[{payload}] {{
587	return witTypes.Make{upper_kind}Reader[{payload}](&wasm_{kind}_vtable_{snake}, handle)
588}}
589"#
590        );
591
592        data
593    }
594
595    fn mangle_name(&self, resolve: &Resolve, ty: Type, local: Option<&WorldKey>) -> String {
596        // TODO: Ensure the returned name is always distinct for distinct types
597        // (e.g. by incorporating interface version numbers and/or additional
598        // mangling as needed).
599        match ty {
600            Type::Bool => "bool".into(),
601            Type::U8 => "u8".into(),
602            Type::U16 => "u16".into(),
603            Type::U32 => "u32".into(),
604            Type::U64 => "u64".into(),
605            Type::S8 => "s8".into(),
606            Type::S16 => "s16".into(),
607            Type::S32 => "s32".into(),
608            Type::S64 => "s64".into(),
609            Type::ErrorContext => "error_context".into(),
610            Type::F32 => "f32".into(),
611            Type::F64 => "f64".into(),
612            Type::Char => "char".into(),
613            Type::String => "string".into(),
614            Type::Id(id) => {
615                let ty = &resolve.types[id];
616                match &ty.kind {
617                    TypeDefKind::Record(_)
618                    | TypeDefKind::Variant(_)
619                    | TypeDefKind::Enum(_)
620                    | TypeDefKind::Flags(_)
621                    | TypeDefKind::Resource => {
622                        let package = match ty.owner {
623                            TypeOwner::Interface(interface) => {
624                                let key = self
625                                    .interface_names
626                                    .get(&interface)
627                                    .cloned()
628                                    .unwrap_or(WorldKey::Interface(interface));
629
630                                if local == Some(&key) {
631                                    String::new()
632                                } else {
633                                    format!(
634                                        "{}_",
635                                        self.interface_name(
636                                            resolve,
637                                            Some(
638                                                &self
639                                                    .interface_names
640                                                    .get(&interface)
641                                                    .cloned()
642                                                    .unwrap_or(WorldKey::Interface(interface))
643                                            )
644                                        )
645                                    )
646                                }
647                            }
648                            _ => String::new(),
649                        };
650
651                        let name = ty.name.as_ref().unwrap().to_snake_case();
652
653                        format!("{package}{name}")
654                    }
655                    TypeDefKind::Option(some) => {
656                        format!("option_{}", self.mangle_name(resolve, *some, local))
657                    }
658                    TypeDefKind::Result(result) => format!(
659                        "result_{}_{}",
660                        result
661                            .ok
662                            .map(|ty| self.mangle_name(resolve, ty, local))
663                            .unwrap_or_else(|| "unit".into()),
664                        result
665                            .err
666                            .map(|ty| self.mangle_name(resolve, ty, local))
667                            .unwrap_or_else(|| "unit".into())
668                    ),
669                    TypeDefKind::List(ty) => {
670                        format!("list_{}", self.mangle_name(resolve, *ty, local))
671                    }
672                    TypeDefKind::Tuple(tuple) => {
673                        let types = tuple
674                            .types
675                            .iter()
676                            .map(|ty| self.mangle_name(resolve, *ty, local))
677                            .collect::<Vec<_>>()
678                            .join("_");
679                        format!("tuple{}_{types}", tuple.types.len())
680                    }
681                    TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
682                        self.mangle_name(resolve, Type::Id(*ty), local)
683                    }
684                    TypeDefKind::Type(ty) => self.mangle_name(resolve, *ty, local),
685                    TypeDefKind::Stream(ty) => {
686                        format!(
687                            "stream_{}",
688                            ty.map(|ty| self.mangle_name(resolve, ty, local))
689                                .unwrap_or_else(|| "unit".into())
690                        )
691                    }
692                    TypeDefKind::Future(ty) => {
693                        format!(
694                            "future_{}",
695                            ty.map(|ty| self.mangle_name(resolve, ty, local))
696                                .unwrap_or_else(|| "unit".into())
697                        )
698                    }
699                    kind => todo!("{kind:?}"),
700                }
701            }
702        }
703    }
704}
705
706impl WorldGenerator for Go {
707    // FIXME(#1527): this caused failures in CI at
708    // https://github.com/bytecodealliance/wit-bindgen/actions/runs/21880247244/job/63160400774?pr=1526
709    // and should be fixed at some point by deleting this method and getting
710    // tests passing again.
711    fn uses_nominal_type_ids(&self) -> bool {
712        false
713    }
714
715    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
716        _ = world;
717        self.sizes.fill(resolve);
718        self.imports.insert(remote_pkg("runtime"));
719    }
720
721    fn import_interface(
722        &mut self,
723        resolve: &Resolve,
724        name: &WorldKey,
725        id: InterfaceId,
726        _files: &mut Files,
727    ) -> Result<()> {
728        if let WorldKey::Name(_) = name {
729            self.interface_names.insert(id, name.clone());
730        }
731
732        let mut data = {
733            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), true);
734            for (name, ty) in resolve.interfaces[id].types.iter() {
735                if !generator.generator.types.contains(ty) {
736                    generator.generator.types.insert(*ty);
737                    generator.define_type(name, *ty);
738                }
739            }
740            InterfaceData::from(generator)
741        };
742
743        for (_, func) in &resolve.interfaces[id].functions {
744            data.extend(self.import(resolve, func, Some(name)));
745        }
746        self.interfaces
747            .entry(self.interface_name(resolve, Some(name)))
748            .or_default()
749            .extend(data);
750
751        Ok(())
752    }
753
754    fn import_funcs(
755        &mut self,
756        resolve: &Resolve,
757        _world: WorldId,
758        funcs: &[(&str, &Function)],
759        _files: &mut Files,
760    ) {
761        let mut data = InterfaceData::default();
762        for (_, func) in funcs {
763            data.extend(self.import(resolve, func, None));
764        }
765        self.interfaces
766            .entry(self.interface_name(resolve, None))
767            .or_default()
768            .extend(data);
769    }
770
771    fn export_interface(
772        &mut self,
773        resolve: &Resolve,
774        name: &WorldKey,
775        id: InterfaceId,
776        _files: &mut Files,
777    ) -> Result<()> {
778        if let WorldKey::Name(_) = name {
779            self.interface_names.insert(id, name.clone());
780        }
781
782        for (type_name, ty) in &resolve.interfaces[id].types {
783            let exported = matches!(resolve.types[*ty].kind, TypeDefKind::Resource)
784                || self.has_exported_resource(resolve, Type::Id(*ty));
785
786            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), false);
787
788            if exported || !generator.generator.types.contains(ty) {
789                generator.generator.types.insert(*ty);
790                generator.define_type(type_name, *ty);
791            }
792
793            let data = generator.into();
794
795            let name = self.interface_name(resolve, Some(name));
796            if exported {
797                &mut self.export_interfaces
798            } else {
799                &mut self.interfaces
800            }
801            .entry(name)
802            .or_default()
803            .extend(data);
804        }
805
806        for (_, func) in &resolve.interfaces[id].functions {
807            let code = self.export(resolve, func, Some(name));
808            self.src.push_str(&code);
809        }
810
811        Ok(())
812    }
813
814    fn export_funcs(
815        &mut self,
816        resolve: &Resolve,
817        _world: WorldId,
818        funcs: &[(&str, &Function)],
819        _files: &mut Files,
820    ) -> Result<()> {
821        for (_, func) in funcs {
822            let code = self.export(resolve, func, None);
823            self.src.push_str(&code);
824        }
825        Ok(())
826    }
827
828    fn import_types(
829        &mut self,
830        resolve: &Resolve,
831        _world: WorldId,
832        types: &[(&str, TypeId)],
833        _files: &mut Files,
834    ) {
835        let mut generator = InterfaceGenerator::new(self, resolve, None, true);
836        for (name, ty) in types {
837            if !generator.generator.types.contains(ty) {
838                generator.generator.types.insert(*ty);
839                generator.define_type(name, *ty);
840            }
841        }
842        let data = generator.into();
843        self.interfaces
844            .entry(self.interface_name(resolve, None))
845            .or_default()
846            .extend(data);
847    }
848
849    fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
850        _ = (resolve, id);
851
852        let version = env!("CARGO_PKG_VERSION");
853        let packages = resolve
854            .packages
855            .iter()
856            .map(
857                |(
858                    _,
859                    Package {
860                        name:
861                            PackageName {
862                                namespace,
863                                name,
864                                version,
865                            },
866                        ..
867                    },
868                )| {
869                    let version = if let Some(version) = version {
870                        format!("@{version}")
871                    } else {
872                        String::new()
873                    };
874                    format!("//     {namespace}:{name}{version}")
875                },
876            )
877            .collect::<Vec<_>>()
878            .join("\n");
879        let header = &format!(
880            "// Generated by `wit-bindgen` {version}. DO NOT EDIT!
881//
882// This code was generated from the following packages:
883{packages}
884"
885        );
886
887        let src = mem::take(&mut self.src);
888        let align = self.return_area_align.format(POINTER_SIZE_EXPRESSION);
889        let size = self.return_area_size.format(POINTER_SIZE_EXPRESSION);
890        let imports = self
891            .imports
892            .iter()
893            .map(|s| s.as_str())
894            .chain(self.need_math.then_some(r#""math""#))
895            .chain(self.need_unsafe.then_some(r#""unsafe""#))
896            .collect::<Vec<_>>()
897            .join("\n");
898
899        let (exports_file_path, package_name, main_func) = if self.opts.pkg_name.is_some() {
900            if self.opts.print_remote_pkg_version {
901                println!("{}", remote_pkg_version());
902            }
903            // If a module name is specified, the generated files will be used as a library.
904            ("wit_exports/wit_exports.go", "wit_exports", "")
905        } else {
906            files.push(
907                "go.mod",
908                format!(
909                    r#"module wit_component
910
911go 1.25
912
913require (
914    go.bytecodealliance.org/pkg {REMOTE_PKG_VERSION}
915)
916"#,
917                )
918                .as_bytes(),
919            );
920
921            // If a module name is NOT specified, the generated files will be used as a
922            // standalone executable.
923            (
924                "wit_exports.go",
925                "main",
926                r#"// Unused, but present to make the compiler happy
927func main() {}
928"#,
929            )
930        };
931
932        files.push(
933            exports_file_path,
934            &maybe_gofmt(
935                self.opts.format,
936                format!(
937                    r#"{header}
938package {package_name}
939
940import (
941        "runtime"
942        {imports}
943)
944
945var staticPinner = runtime.Pinner{{}}
946var {EXPORT_RETURN_AREA} = uintptr(witRuntime.Allocate(&staticPinner, {size}, {align}))
947var {SYNC_EXPORT_PINNER} = runtime.Pinner{{}}
948
949{src}
950
951{main_func}
952"#
953                )
954                .as_bytes(),
955            ),
956        );
957
958        for (prefix, interfaces) in [("export_", &self.export_interfaces), ("", &self.interfaces)] {
959            for (name, data) in interfaces {
960                let imports = data.imports();
961                let code = &data.code;
962
963                files.push(
964                    &format!("{prefix}{name}/wit_bindings.go"),
965                    &maybe_gofmt(
966                        self.opts.format,
967                        format!(
968                            "{header}
969package {prefix}{name}
970
971import (
972        {imports}
973)
974
975{code}"
976                        )
977                        .as_bytes(),
978                    ),
979                );
980
981                files.push(
982                    &format!("{prefix}{name}/empty.s"),
983                    r#"// This file exists for testing this package without WebAssembly,
984// allowing empty function bodies with a //go:wasmimport directive.
985// See https://pkg.go.dev/cmd/compile for more information."#
986                        .as_bytes(),
987                );
988            }
989        }
990
991        Ok(())
992    }
993}
994
995impl Go {
996    fn import(
997        &mut self,
998        resolve: &Resolve,
999        func: &Function,
1000        interface: Option<&WorldKey>,
1001    ) -> InterfaceData {
1002        self.visit_futures_and_streams(true, resolve, func, interface);
1003
1004        let async_ = self.opts.async_.is_async(resolve, interface, func, true);
1005
1006        let (variant, prefix) = if async_ {
1007            (AbiVariant::GuestImportAsync, "[async-lower]")
1008        } else {
1009            (AbiVariant::GuestImport, "")
1010        };
1011
1012        let sig = resolve.wasm_signature(variant, func);
1013        let import_name = &func.name;
1014        let name = func.name.to_snake_case().replace('.', "_");
1015        let (camel, has_self) = func_declaration(resolve, func);
1016
1017        let module = match interface {
1018            Some(name) => resolve.name_world_key(name),
1019            None => "$root".to_string(),
1020        };
1021
1022        let params = sig
1023            .params
1024            .iter()
1025            .enumerate()
1026            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
1027            .collect::<Vec<_>>()
1028            .join(", ");
1029
1030        let results = match &sig.results[..] {
1031            [] => "",
1032            [result] => wasm_type(*result),
1033            _ => unreachable!(),
1034        };
1035
1036        let mut imports = BTreeSet::new();
1037        let go_params =
1038            self.func_params(resolve, func, interface, true, &mut imports, has_self, "");
1039        let go_results = self.func_results(resolve, func, interface, true, &mut imports);
1040
1041        let raw_name = format!("wasm_import_{name}");
1042
1043        let go_param_names = has_self
1044            .then(|| "self".to_string())
1045            .into_iter()
1046            .chain(
1047                func.params
1048                    .iter()
1049                    .skip(if has_self { 1 } else { 0 })
1050                    .map(|Param { name, .. }| name.to_lower_camel_case()),
1051            )
1052            .collect::<Vec<_>>();
1053
1054        let mut generator = FunctionGenerator::new(
1055            self,
1056            None,
1057            interface,
1058            interface,
1059            &raw_name,
1060            go_param_names.clone(),
1061            false,
1062            true,
1063        );
1064        generator.imports = imports;
1065
1066        let code = if async_ {
1067            generator.imports.insert(remote_pkg("async"));
1068
1069            let (lower, wasm_params) = if sig.indirect_params {
1070                generator.imports.insert(remote_pkg("runtime"));
1071
1072                let params_pointer = generator.locals.tmp("params");
1073                let abi = generator
1074                    .generator
1075                    .sizes
1076                    .record(func.params.iter().map(|Param { ty, .. }| ty));
1077                let size = abi.size.format(POINTER_SIZE_EXPRESSION);
1078                let align = abi.align.format(POINTER_SIZE_EXPRESSION);
1079                let offsets = generator
1080                    .generator
1081                    .sizes
1082                    .field_offsets(func.params.iter().map(|Param { ty, .. }| ty));
1083
1084                for (name, (offset, ty)) in go_param_names.iter().zip(offsets) {
1085                    let offset = offset.format(POINTER_SIZE_EXPRESSION);
1086                    abi::lower_to_memory(
1087                        resolve,
1088                        &mut generator,
1089                        format!("unsafe.Add(unsafe.Pointer({params_pointer}), {offset})"),
1090                        name.clone(),
1091                        ty,
1092                    );
1093                }
1094
1095                let code = mem::take(&mut generator.src);
1096                generator.need_pinner = true;
1097                (
1098                    format!(
1099                        "{params_pointer} := witRuntime.Allocate({PINNER}, {size}, {align})\n{code}"
1100                    ),
1101                    vec![format!("uintptr({params_pointer})")],
1102                )
1103            } else {
1104                let wasm_params = go_param_names
1105                    .iter()
1106                    .zip(&func.params)
1107                    .flat_map(|(name, Param { ty, .. })| {
1108                        abi::lower_flat(resolve, &mut generator, name.clone(), ty)
1109                    })
1110                    .collect();
1111                (mem::take(&mut generator.src), wasm_params)
1112            };
1113
1114            let wasm_params = wasm_params
1115                .iter()
1116                .map(|v| v.as_str())
1117                .chain(func.result.map(|_| IMPORT_RETURN_AREA))
1118                .collect::<Vec<_>>()
1119                .join(", ");
1120
1121            let lift = if let Some(ty) = func.result {
1122                let result = abi::lift_from_memory(
1123                    resolve,
1124                    &mut generator,
1125                    IMPORT_RETURN_AREA.to_string(),
1126                    &ty,
1127                );
1128                let code = mem::take(&mut generator.src);
1129                if let Type::Id(ty) = ty
1130                    && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1131                {
1132                    let count = tuple.types.len();
1133                    let tuple = generator.locals.tmp("tuple");
1134
1135                    let results = (0..count)
1136                        .map(|index| format!("{tuple}.F{index}"))
1137                        .collect::<Vec<_>>()
1138                        .join(", ");
1139
1140                    format!(
1141                        "{code}
1142{tuple} := {result}
1143return {results}"
1144                    )
1145                } else {
1146                    format!("{code}\nreturn {result}")
1147                }
1148            } else {
1149                String::new()
1150            };
1151
1152            format!(
1153                "{lower}
1154witAsync.SubtaskWait(uint32({raw_name}({wasm_params})))
1155{lift}
1156"
1157            )
1158        } else {
1159            abi::call(
1160                resolve,
1161                variant,
1162                LiftLower::LowerArgsLiftResults,
1163                func,
1164                &mut generator,
1165                false,
1166            );
1167            mem::take(&mut generator.src)
1168        };
1169
1170        let return_area = |generator: &mut FunctionGenerator<'_>,
1171                           size: ArchitectureSize,
1172                           align: Alignment| {
1173            generator.imports.insert(remote_pkg("runtime"));
1174            generator.need_pinner = true;
1175            let size = size.format(POINTER_SIZE_EXPRESSION);
1176            let align = align.format(POINTER_SIZE_EXPRESSION);
1177            format!(
1178                "{IMPORT_RETURN_AREA} := uintptr(witRuntime.Allocate({PINNER}, {size}, {align}))"
1179            )
1180        };
1181
1182        let return_area = if async_ && func.result.is_some() {
1183            let abi = generator.generator.sizes.record(func.result.as_ref());
1184            return_area(&mut generator, abi.size, abi.align)
1185        } else if !(async_ || generator.return_area_size.is_empty()) {
1186            let size = generator.return_area_size;
1187            let align = generator.return_area_align;
1188            return_area(&mut generator, size, align)
1189        } else {
1190            String::new()
1191        };
1192
1193        let pinner = if generator.need_pinner {
1194            format!(
1195                "{PINNER} := &runtime.Pinner{{}}
1196defer {PINNER}.Unpin()
1197"
1198            )
1199        } else {
1200            String::new()
1201        };
1202
1203        InterfaceData::from_generator_and_code(
1204            generator,
1205            format!(
1206                "
1207//go:wasmimport {module} {prefix}{import_name}
1208func {raw_name}({params}) {results}
1209
1210func {camel}({go_params}) {go_results} {{
1211        {pinner}
1212        {return_area}
1213        {code}
1214}}
1215"
1216            ),
1217        )
1218    }
1219
1220    fn export(
1221        &mut self,
1222        resolve: &Resolve,
1223        func: &Function,
1224        interface: Option<&WorldKey>,
1225    ) -> String {
1226        self.visit_futures_and_streams(false, resolve, func, interface);
1227
1228        let async_ = self.opts.async_.is_async(resolve, interface, func, false);
1229
1230        let (variant, prefix) = if async_ {
1231            (AbiVariant::GuestExportAsync, "[async-lift]")
1232        } else {
1233            (AbiVariant::GuestExport, "")
1234        };
1235
1236        let sig = resolve.wasm_signature(variant, func);
1237        let core_module_name = interface.map(|v| resolve.name_world_key(v));
1238        let export_name = func.legacy_core_export_name(core_module_name.as_deref());
1239        let name = self.func_name(resolve, interface, func);
1240
1241        let params = sig
1242            .params
1243            .iter()
1244            .enumerate()
1245            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
1246            .collect::<Vec<_>>()
1247            .join(", ");
1248
1249        let results = match &sig.results[..] {
1250            [] => "",
1251            [result] => wasm_type(*result),
1252            _ => unreachable!(),
1253        };
1254
1255        let unpin_params =
1256            sig.indirect_params || abi::guest_export_params_have_allocations(resolve, func);
1257
1258        let param_names = (0..sig.params.len()).map(|i| format!("arg{i}")).collect();
1259        let mut generator = FunctionGenerator::new(
1260            self,
1261            Some(&name),
1262            interface,
1263            None,
1264            "INVALID",
1265            param_names,
1266            unpin_params,
1267            false,
1268        );
1269        abi::call(
1270            resolve,
1271            variant,
1272            LiftLower::LiftArgsLowerResults,
1273            func,
1274            &mut generator,
1275            async_,
1276        );
1277        let code = generator.src;
1278        let imports = generator.imports;
1279        let need_unsafe = generator.need_unsafe;
1280        self.need_math |= generator.need_math;
1281        self.need_unsafe |= need_unsafe;
1282        self.imports.extend(imports);
1283
1284        let (pinner, other, start, end) = if async_ {
1285            self.imports.insert(remote_pkg("async"));
1286
1287            let module = match interface {
1288                Some(name) => resolve.name_world_key(name),
1289                None => "$root".to_string(),
1290            };
1291
1292            let function = &func.name;
1293
1294            let task_return_params = func
1295                .result
1296                .map(|ty| {
1297                    let mut storage = vec![WasmType::I32; MAX_FLAT_PARAMS];
1298                    let mut flat = FlatTypes::new(&mut storage);
1299                    if resolve.push_flat(&ty, &mut flat) {
1300                        flat.to_vec()
1301                    } else {
1302                        vec![WasmType::I32]
1303                    }
1304                })
1305                .unwrap_or_default()
1306                .into_iter()
1307                .enumerate()
1308                .map(|(i, ty)| {
1309                    let ty = wasm_type(ty);
1310                    format!("arg{i} {ty}")
1311                })
1312                .collect::<Vec<_>>()
1313                .join(", ");
1314
1315            (
1316                if abi::guest_export_needs_post_return(resolve, func) {
1317                    format!("{PINNER} := &runtime.Pinner{{}}")
1318                } else {
1319                    String::new()
1320                },
1321                format!(
1322                    "
1323
1324//go:wasmexport [callback]{prefix}{export_name}
1325func wasm_export_callback_{name}(event0 uint32, event1 uint32, event2 uint32) uint32 {{
1326        return witAsync.Callback(event0, event1, event2)
1327}}
1328
1329//go:wasmimport [export]{module} [task-return]{function}
1330func wasm_export_task_return_{name}({task_return_params})
1331"
1332                ),
1333                "return int32(witAsync.Run(func() {",
1334                "}))",
1335            )
1336        } else if abi::guest_export_needs_post_return(resolve, func) {
1337            (
1338                format!("{PINNER} := &{SYNC_EXPORT_PINNER}"),
1339                format!(
1340                    "
1341
1342//go:wasmexport cabi_post_{export_name}
1343func wasm_export_post_return_{name}(result {results}) {{
1344        syncExportPinner.Unpin()
1345}}
1346"
1347                ),
1348                "",
1349                "",
1350            )
1351        } else {
1352            (String::new(), String::new(), "", "")
1353        };
1354
1355        if self.opts.generate_stubs {
1356            let (camel, has_self) = func_declaration(resolve, func);
1357
1358            let mut imports = BTreeSet::new();
1359            let params =
1360                self.func_params(resolve, func, interface, false, &mut imports, has_self, "_");
1361            let results = self.func_results(resolve, func, interface, false, &mut imports);
1362
1363            self.export_interfaces
1364                .entry(self.interface_name(resolve, interface))
1365                .or_default()
1366                .extend(InterfaceData {
1367                    code: format!(
1368                        r#"
1369func {camel}({params}) {results} {{
1370        panic("not implemented")
1371}}
1372"#
1373                    ),
1374                    imports,
1375                    ..InterfaceData::default()
1376                });
1377        }
1378
1379        format!(
1380            "
1381//go:wasmexport {prefix}{export_name}
1382func wasm_export_{name}({params}) {results} {{
1383        {start}
1384        {pinner}
1385        {code}
1386        {end}
1387}}{other}
1388"
1389        )
1390    }
1391
1392    #[expect(clippy::too_many_arguments, reason = "required context for codegen")]
1393    fn func_params(
1394        &mut self,
1395        resolve: &Resolve,
1396        func: &Function,
1397        interface: Option<&WorldKey>,
1398        in_import: bool,
1399        imports: &mut BTreeSet<String>,
1400        has_self: bool,
1401        prefix: &str,
1402    ) -> String {
1403        func.params
1404            .iter()
1405            .skip(if has_self { 1 } else { 0 })
1406            .map(|Param { name, ty, .. }| {
1407                let name = name.to_lower_camel_case();
1408                let ty = self.type_name(resolve, *ty, interface, in_import, imports);
1409                format!("{prefix}{name} {ty}")
1410            })
1411            .collect::<Vec<_>>()
1412            .join(", ")
1413    }
1414
1415    fn func_results(
1416        &mut self,
1417        resolve: &Resolve,
1418        func: &Function,
1419        interface: Option<&WorldKey>,
1420        in_import: bool,
1421        imports: &mut BTreeSet<String>,
1422    ) -> String {
1423        if let Some(ty) = &func.result {
1424            if let Type::Id(id) = ty
1425                && let TypeDefKind::Tuple(tuple) = &resolve.types[*id].kind
1426            {
1427                let types = tuple
1428                    .types
1429                    .iter()
1430                    .map(|ty| self.type_name(resolve, *ty, interface, in_import, imports))
1431                    .collect::<Vec<_>>()
1432                    .join(", ");
1433                format!("({types})")
1434            } else {
1435                self.type_name(resolve, *ty, interface, in_import, imports)
1436            }
1437        } else {
1438            String::new()
1439        }
1440    }
1441
1442    fn visit_futures_and_streams(
1443        &mut self,
1444        in_import: bool,
1445        resolve: &Resolve,
1446        func: &Function,
1447        interface: Option<&WorldKey>,
1448    ) {
1449        for (index, ty) in func
1450            .find_futures_and_streams(resolve)
1451            .into_iter()
1452            .enumerate()
1453        {
1454            let payload_type = match &resolve.types[ty].kind {
1455                TypeDefKind::Future(ty) => {
1456                    self.need_future = true;
1457                    ty
1458                }
1459                TypeDefKind::Stream(ty) => {
1460                    self.need_stream = true;
1461                    ty
1462                }
1463                _ => unreachable!(),
1464            };
1465
1466            let exported = payload_type
1467                .map(|ty| self.has_exported_resource(resolve, ty))
1468                .unwrap_or(false);
1469
1470            if let hash_map::Entry::Vacant(e) = self.futures_and_streams.entry((ty, exported)) {
1471                e.insert(interface.cloned());
1472
1473                let data = self.future_or_stream(
1474                    resolve,
1475                    ty,
1476                    index,
1477                    in_import,
1478                    in_import || !exported,
1479                    interface,
1480                    &func.name,
1481                );
1482
1483                let name = self.interface_name(resolve, interface);
1484                if in_import || !exported {
1485                    &mut self.interfaces
1486                } else {
1487                    &mut self.export_interfaces
1488                }
1489                .entry(name)
1490                .or_default()
1491                .extend(data);
1492            }
1493        }
1494    }
1495
1496    fn has_exported_resource(&self, resolve: &Resolve, ty: Type) -> bool {
1497        any(resolve, ty, &|ty| {
1498            if let Type::Id(id) = ty
1499                && let TypeDefKind::Resource = &resolve.types[id].kind
1500                && let Direction::Export = self.resources.get(&id).unwrap()
1501            {
1502                true
1503            } else {
1504                false
1505            }
1506        })
1507    }
1508
1509    fn interface_name(&self, resolve: &Resolve, interface: Option<&WorldKey>) -> String {
1510        match interface {
1511            Some(WorldKey::Name(name)) => name.to_snake_case(),
1512            Some(WorldKey::Interface(id)) => {
1513                let interface = &resolve.interfaces[*id];
1514                let package = &resolve.packages[interface.package.unwrap()];
1515                let package_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
1516                    p.name.namespace == package.name.namespace
1517                        && p.name.name == package.name.name
1518                        && p.name.version != package.name.version
1519                });
1520                let version = if package_has_multiple_versions || self.opts.include_versions {
1521                    if let Some(version) = &package.name.version {
1522                        format!("{}_", version.to_string().replace(['.', '-', '+'], "_"))
1523                    } else {
1524                        String::new()
1525                    }
1526                } else {
1527                    String::new()
1528                };
1529                let namespace = package.name.namespace.to_snake_case();
1530                let package = package.name.name.to_snake_case();
1531                let interface = interface.name.as_ref().unwrap().to_snake_case();
1532                format!("{namespace}_{package}_{version}{interface}")
1533            }
1534            None => "wit_world".into(),
1535        }
1536    }
1537
1538    fn func_name(
1539        &self,
1540        resolve: &Resolve,
1541        interface: Option<&WorldKey>,
1542        func: &Function,
1543    ) -> String {
1544        let prefix = self.interface_name(resolve, interface);
1545        let name = func.name.to_snake_case().replace('.', "_");
1546
1547        format!("{prefix}_{name}")
1548    }
1549}
1550
1551struct FunctionGenerator<'a> {
1552    generator: &'a mut Go,
1553    name: Option<&'a str>,
1554    interface: Option<&'a WorldKey>,
1555    interface_for_types: Option<&'a WorldKey>,
1556    function_to_call: &'a str,
1557    param_names: Vec<String>,
1558    unpin_params: bool,
1559    in_import: bool,
1560    locals: Ns,
1561    src: String,
1562    block_storage: Vec<String>,
1563    blocks: Vec<(String, Vec<String>)>,
1564    need_unsafe: bool,
1565    need_pinner: bool,
1566    need_math: bool,
1567    collect_lifters: bool,
1568    lifter_count: u32,
1569    return_area_size: ArchitectureSize,
1570    return_area_align: Alignment,
1571    imports: BTreeSet<String>,
1572}
1573
1574impl<'a> FunctionGenerator<'a> {
1575    #[expect(clippy::too_many_arguments, reason = "required context for codegen")]
1576    fn new(
1577        generator: &'a mut Go,
1578        name: Option<&'a str>,
1579        interface: Option<&'a WorldKey>,
1580        interface_for_types: Option<&'a WorldKey>,
1581        function_to_call: &'a str,
1582        param_names: Vec<String>,
1583        unpin_params: bool,
1584        in_import: bool,
1585    ) -> Self {
1586        let mut locals = Ns::default();
1587        for name in &param_names {
1588            locals.insert(name).unwrap();
1589        }
1590
1591        Self {
1592            generator,
1593            name,
1594            interface,
1595            interface_for_types,
1596            function_to_call,
1597            param_names,
1598            unpin_params,
1599            in_import,
1600            locals,
1601            src: String::new(),
1602            block_storage: Vec::new(),
1603            blocks: Vec::new(),
1604            need_unsafe: false,
1605            need_pinner: false,
1606            need_math: false,
1607            collect_lifters: false,
1608            lifter_count: 0,
1609            return_area_size: ArchitectureSize::default(),
1610            return_area_align: Alignment::default(),
1611            imports: BTreeSet::new(),
1612        }
1613    }
1614
1615    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
1616        self.generator.type_name(
1617            resolve,
1618            ty,
1619            self.interface_for_types,
1620            self.in_import,
1621            &mut self.imports,
1622        )
1623    }
1624
1625    fn package_for_owner(
1626        &mut self,
1627        resolve: &Resolve,
1628        owner: Option<&WorldKey>,
1629        ty: TypeId,
1630    ) -> String {
1631        self.generator.package_for_owner(
1632            resolve,
1633            owner,
1634            ty,
1635            self.interface_for_types,
1636            self.in_import,
1637            &mut self.imports,
1638        )
1639    }
1640}
1641
1642impl Bindgen for FunctionGenerator<'_> {
1643    type Operand = String;
1644
1645    fn sizes(&self) -> &SizeAlign {
1646        &self.generator.sizes
1647    }
1648
1649    fn push_block(&mut self) {
1650        let prev = mem::take(&mut self.src);
1651        self.block_storage.push(prev);
1652    }
1653
1654    fn finish_block(&mut self, operands: &mut Vec<String>) {
1655        let to_restore = self.block_storage.pop().unwrap();
1656        let src = mem::replace(&mut self.src, to_restore);
1657        self.blocks.push((src, mem::take(operands)));
1658    }
1659
1660    fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
1661        if self.in_import {
1662            self.return_area_size = self.return_area_size.max(size);
1663            self.return_area_align = self.return_area_align.max(align);
1664
1665            if !self.return_area_size.is_empty() {
1666                self.need_pinner = true;
1667                self.imports.insert(remote_pkg("runtime"));
1668            }
1669
1670            IMPORT_RETURN_AREA.into()
1671        } else {
1672            self.generator.return_area_size = self.generator.return_area_size.max(size);
1673            self.generator.return_area_align = self.generator.return_area_align.max(align);
1674            EXPORT_RETURN_AREA.into()
1675        }
1676    }
1677
1678    fn is_list_canonical(&self, _: &Resolve, ty: &Type) -> bool {
1679        matches!(
1680            ty,
1681            Type::U8
1682                | Type::S8
1683                | Type::U16
1684                | Type::S16
1685                | Type::U32
1686                | Type::S32
1687                | Type::U64
1688                | Type::S64
1689                | Type::F32
1690                | Type::F64
1691        )
1692    }
1693
1694    fn emit(
1695        &mut self,
1696        resolve: &Resolve,
1697        instruction: &Instruction<'_>,
1698        operands: &mut Vec<String>,
1699        results: &mut Vec<String>,
1700    ) {
1701        let store = |me: &mut Self, src, pointer, offset: &ArchitectureSize, ty| {
1702            me.need_unsafe = true;
1703            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1704            uwriteln!(
1705                me.src,
1706                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset})) = {src}"
1707            );
1708        };
1709        let load = |me: &mut Self,
1710                    results: &mut Vec<String>,
1711                    pointer,
1712                    offset: &ArchitectureSize,
1713                    ty,
1714                    cast: &dyn Fn(String) -> String| {
1715            me.need_unsafe = true;
1716            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1717            results.push(cast(format!(
1718                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset}))"
1719            )));
1720        };
1721
1722        match instruction {
1723            Instruction::GetArg { nth } => results.push(self.param_names[*nth].clone()),
1724            Instruction::StringLower { .. } => {
1725                self.need_pinner = true;
1726                self.need_unsafe = true;
1727                let string = &operands[0];
1728                let utf8 = self.locals.tmp("utf8");
1729                uwriteln!(
1730                    self.src,
1731                    "{utf8} := unsafe.Pointer(unsafe.StringData({string}))\n\
1732                     {PINNER}.Pin({utf8})"
1733                );
1734                results.push(format!("uintptr({utf8})"));
1735                results.push(format!("uint32(len({string}))"));
1736            }
1737            Instruction::StringLift { .. } => {
1738                self.need_unsafe = true;
1739                let pointer = &operands[0];
1740                let length = &operands[1];
1741                let value = self.locals.tmp("value");
1742                uwriteln!(
1743                    self.src,
1744                    "{value} := unsafe.String((*uint8)(unsafe.Pointer({pointer})), {length})"
1745                );
1746                results.push(value)
1747            }
1748            Instruction::ListCanonLower { .. } => {
1749                self.need_pinner = true;
1750                self.need_unsafe = true;
1751                let slice = &operands[0];
1752                let data = self.locals.tmp("data");
1753                uwriteln!(
1754                    self.src,
1755                    "{data} := unsafe.Pointer(unsafe.SliceData({slice}))\n\
1756                     {PINNER}.Pin({data})"
1757                );
1758                results.push(format!("uintptr({data})"));
1759                results.push(format!("uint32(len({slice}))"));
1760            }
1761            Instruction::ListCanonLift { element, .. } => {
1762                self.need_unsafe = true;
1763                let pointer = &operands[0];
1764                let length = &operands[1];
1765                let ty = self.type_name(resolve, **element);
1766                let value = self.locals.tmp("value");
1767                uwriteln!(
1768                    self.src,
1769                    "{value} := unsafe.Slice((*{ty})(unsafe.Pointer({pointer})), {length})"
1770                );
1771                results.push(value)
1772            }
1773            Instruction::ListLower { element, .. } => {
1774                self.need_unsafe = true;
1775                self.need_pinner = true;
1776                self.imports.insert(remote_pkg("runtime"));
1777                let (body, _) = self.blocks.pop().unwrap();
1778                let value = &operands[0];
1779                let slice = self.locals.tmp("slice");
1780                let result = self.locals.tmp("result");
1781                let length = self.locals.tmp("length");
1782                let size = self
1783                    .generator
1784                    .sizes
1785                    .size(element)
1786                    .format(POINTER_SIZE_EXPRESSION);
1787                let align = self
1788                    .generator
1789                    .sizes
1790                    .align(element)
1791                    .format(POINTER_SIZE_EXPRESSION);
1792                uwriteln!(
1793                    self.src,
1794                    "{slice} := {value}
1795{length} := uint32(len({slice}))
1796{result} := witRuntime.Allocate({PINNER}, uintptr({length} * {size}), {align})
1797for index, {ITER_ELEMENT} := range {slice} {{
1798        {ITER_BASE_POINTER} := unsafe.Add({result}, index * {size})
1799        {body}
1800}}
1801"
1802                );
1803                results.push(format!("uintptr({result})"));
1804                results.push(length);
1805            }
1806            Instruction::ListLift { element, .. } => {
1807                self.need_unsafe = true;
1808                let (body, body_results) = self.blocks.pop().unwrap();
1809                let value = &operands[0];
1810                let length = &operands[1];
1811                let result = self.locals.tmp("result");
1812                let size = self
1813                    .generator
1814                    .sizes
1815                    .size(element)
1816                    .format(POINTER_SIZE_EXPRESSION);
1817                let element_type = self.type_name(resolve, **element);
1818                let body_result = &body_results[0];
1819                uwriteln!(
1820                    self.src,
1821                    "{result} := make([]{element_type}, 0, {length})
1822for index := 0; index < int({length}); index++ {{
1823        {ITER_BASE_POINTER} := unsafe.Add(unsafe.Pointer({value}), index * {size})
1824        {body}
1825        {result} = append({result}, {body_result})
1826}}
1827"
1828                );
1829                results.push(result);
1830            }
1831            Instruction::CallInterface { func, .. } => {
1832                if self.unpin_params {
1833                    self.imports.insert(remote_pkg("runtime"));
1834                    uwriteln!(self.src, "witRuntime.Unpin()");
1835                }
1836
1837                let name = func.item_name().to_upper_camel_case();
1838                let package = format!(
1839                    "export_{}",
1840                    self.generator.interface_name(resolve, self.interface)
1841                );
1842
1843                let call = match &func.kind {
1844                    FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1845                        let args = operands.join(", ");
1846                        let call = format!("{package}.{name}({args})");
1847                        self.imports.insert(self.generator.mod_pkg(true, &package));
1848                        call
1849                    }
1850                    FunctionKind::Constructor(ty) => {
1851                        let args = operands.join(", ");
1852                        let ty = resolve.types[*ty]
1853                            .name
1854                            .as_ref()
1855                            .unwrap()
1856                            .to_upper_camel_case();
1857                        let call = format!("{package}.Make{ty}({args})");
1858                        self.imports.insert(self.generator.mod_pkg(true, &package));
1859                        call
1860                    }
1861                    FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
1862                        let target = &operands[0];
1863                        let args = operands[1..].join(", ");
1864                        format!("({target}).{name}({args})")
1865                    }
1866                    FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
1867                        let args = operands.join(", ");
1868                        let ty = self.type_name(resolve, Type::Id(*ty));
1869                        format!("{ty}{name}({args})")
1870                    }
1871                };
1872
1873                if let Some(ty) = func.result {
1874                    let result = self.locals.tmp("result");
1875                    if let Type::Id(ty) = ty
1876                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1877                    {
1878                        let count = tuple.types.len();
1879                        self.generator.tuples.insert(count);
1880                        self.imports.insert(remote_pkg("types"));
1881
1882                        let results = (0..count)
1883                            .map(|_| self.locals.tmp("result"))
1884                            .collect::<Vec<_>>()
1885                            .join(", ");
1886
1887                        let types = tuple
1888                            .types
1889                            .iter()
1890                            .map(|&ty| self.type_name(resolve, ty))
1891                            .collect::<Vec<_>>()
1892                            .join(", ");
1893
1894                        uwriteln!(
1895                            self.src,
1896                            "{results} := {call}
1897{result} := witTypes.Tuple{count}[{types}]{{{results}}}"
1898                        );
1899                    } else {
1900                        uwriteln!(self.src, "{result} := {call}");
1901                    }
1902                    results.push(result);
1903                } else {
1904                    uwriteln!(self.src, "{call}");
1905                }
1906            }
1907            Instruction::Return { func, .. } => {
1908                if let Some(ty) = func.result {
1909                    let result = &operands[0];
1910                    if self.in_import
1911                        && let Type::Id(ty) = ty
1912                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1913                    {
1914                        let count = tuple.types.len();
1915                        let tuple = self.locals.tmp("tuple");
1916
1917                        let results = (0..count)
1918                            .map(|index| format!("{tuple}.F{index}"))
1919                            .collect::<Vec<_>>()
1920                            .join(", ");
1921
1922                        uwriteln!(
1923                            self.src,
1924                            "{tuple} := {result}
1925return {results}"
1926                        );
1927                    } else {
1928                        uwriteln!(self.src, "return {result}");
1929                    }
1930                }
1931            }
1932            Instruction::AsyncTaskReturn { .. } => {
1933                let name = self.name.unwrap();
1934                let args = operands.join(", ");
1935                uwriteln!(self.src, "wasm_export_task_return_{name}({args})");
1936            }
1937            Instruction::LengthStore { offset } => store(
1938                self,
1939                &format!("uint32({})", operands[0]),
1940                &operands[1],
1941                offset,
1942                "uint32",
1943            ),
1944            Instruction::PointerStore { offset } => store(
1945                self,
1946                &format!("uint32(uintptr({}))", operands[0]),
1947                &operands[1],
1948                offset,
1949                "uint32",
1950            ),
1951            Instruction::I32Store8 { offset } => store(
1952                self,
1953                &format!("int8({})", operands[0]),
1954                &operands[1],
1955                offset,
1956                "int8",
1957            ),
1958            Instruction::I32Store16 { offset } => store(
1959                self,
1960                &format!("int16({})", operands[0]),
1961                &operands[1],
1962                offset,
1963                "int16",
1964            ),
1965            Instruction::I32Store { offset } => {
1966                store(self, &operands[0], &operands[1], offset, "int32")
1967            }
1968            Instruction::I64Store { offset } => {
1969                store(self, &operands[0], &operands[1], offset, "int64")
1970            }
1971            Instruction::F32Store { offset } => {
1972                store(self, &operands[0], &operands[1], offset, "float32")
1973            }
1974            Instruction::F64Store { offset } => {
1975                store(self, &operands[0], &operands[1], offset, "float64")
1976            }
1977            Instruction::LengthLoad { offset } => {
1978                load(self, results, &operands[0], offset, "uint32", &|v| v)
1979            }
1980            Instruction::PointerLoad { offset } => {
1981                load(self, results, &operands[0], offset, "uint32", &|v| {
1982                    format!("uintptr({v})")
1983                })
1984            }
1985            Instruction::I32Load8U { offset } => {
1986                load(self, results, &operands[0], offset, "uint32", &|v| {
1987                    format!("uint8({v})")
1988                })
1989            }
1990            Instruction::I32Load8S { offset } => {
1991                load(self, results, &operands[0], offset, "uint32", &|v| {
1992                    format!("int8({v})")
1993                })
1994            }
1995            Instruction::I32Load16U { offset } => {
1996                load(self, results, &operands[0], offset, "uint32", &|v| {
1997                    format!("uint16({v})")
1998                })
1999            }
2000            Instruction::I32Load16S { offset } => {
2001                load(self, results, &operands[0], offset, "uint32", &|v| {
2002                    format!("int16({v})")
2003                })
2004            }
2005            Instruction::I32Load { offset } => {
2006                load(self, results, &operands[0], offset, "int32", &|v| v)
2007            }
2008            Instruction::I64Load { offset } => {
2009                load(self, results, &operands[0], offset, "int64", &|v| v)
2010            }
2011            Instruction::F32Load { offset } => {
2012                load(self, results, &operands[0], offset, "float32", &|v| v)
2013            }
2014            Instruction::F64Load { offset } => {
2015                load(self, results, &operands[0], offset, "float64", &|v| v)
2016            }
2017            Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
2018            Instruction::U8FromI32 => results.push(format!("uint8({})", operands[0])),
2019            Instruction::S8FromI32 => results.push(format!("int8({})", operands[0])),
2020            Instruction::U16FromI32 => results.push(format!("uint16({})", operands[0])),
2021            Instruction::S16FromI32 => results.push(format!("int16({})", operands[0])),
2022            Instruction::U32FromI32 => results.push(format!("uint32({})", operands[0])),
2023            Instruction::S32FromI32 | Instruction::S64FromI64 => {
2024                results.push(operands.pop().unwrap())
2025            }
2026            Instruction::U64FromI64 => results.push(format!("uint64({})", operands[0])),
2027            Instruction::I32FromBool => {
2028                let value = &operands[0];
2029                let result = self.locals.tmp("result");
2030                uwriteln!(
2031                    self.src,
2032                    "var {result} int32
2033if {value} {{
2034        {result} = 1
2035}} else {{
2036        {result} = 0
2037}}"
2038                );
2039                results.push(result);
2040            }
2041            Instruction::I32FromU8
2042            | Instruction::I32FromS8
2043            | Instruction::I32FromU16
2044            | Instruction::I32FromS16
2045            | Instruction::I32FromU32 => {
2046                results.push(format!("int32({})", operands[0]));
2047            }
2048            Instruction::I32FromS32 | Instruction::I64FromS64 => {
2049                results.push(operands.pop().unwrap())
2050            }
2051            Instruction::I64FromU64 => results.push(format!("int64({})", operands[0])),
2052            Instruction::CoreF32FromF32
2053            | Instruction::CoreF64FromF64
2054            | Instruction::F32FromCoreF32
2055            | Instruction::F64FromCoreF64 => results.push(operands.pop().unwrap()),
2056            Instruction::CharFromI32 => results.push(format!("rune({})", operands[0])),
2057            Instruction::I32FromChar => results.push(format!("int32({})", operands[0])),
2058            Instruction::TupleLower { tuple, .. } => {
2059                let op = &operands[0];
2060                for index in 0..tuple.types.len() {
2061                    results.push(format!("({op}).F{index}"));
2062                }
2063            }
2064            Instruction::TupleLift { tuple, .. } => {
2065                let count = tuple.types.len();
2066                self.generator.tuples.insert(count);
2067                let types = tuple
2068                    .types
2069                    .iter()
2070                    .map(|&ty| self.type_name(resolve, ty))
2071                    .collect::<Vec<_>>()
2072                    .join(", ");
2073                let fields = operands.join(", ");
2074                self.imports.insert(remote_pkg("types"));
2075                results.push(format!("witTypes.Tuple{count}[{types}]{{{fields}}}"));
2076            }
2077            Instruction::FlagsLower { .. } => {
2078                let value = operands.pop().unwrap();
2079                results.push(format!("int32({value})"))
2080            }
2081            Instruction::FlagsLift { flags, .. } => {
2082                let value = operands.pop().unwrap();
2083                let repr = flags_repr(flags);
2084                results.push(format!("{repr}({value})"))
2085            }
2086            Instruction::RecordLower { record, .. } => {
2087                let op = &operands[0];
2088                for field in &record.fields {
2089                    let field = field.name.to_upper_camel_case();
2090                    results.push(format!("({op}).{field}"));
2091                }
2092            }
2093            Instruction::RecordLift { ty, .. } => {
2094                let name = self.type_name(resolve, Type::Id(*ty));
2095                let fields = operands.join(", ");
2096                results.push(format!("{name}{{{fields}}}"));
2097            }
2098            Instruction::OptionLower {
2099                results: result_types,
2100                ..
2101            } => {
2102                self.generator.need_option = true;
2103                self.imports.insert(remote_pkg("types"));
2104                let (some, some_results) = self.blocks.pop().unwrap();
2105                let (none, none_results) = self.blocks.pop().unwrap();
2106                let value = &operands[0];
2107
2108                let result_names = (0..result_types.len())
2109                    .map(|_| self.locals.tmp("option"))
2110                    .collect::<Vec<_>>();
2111
2112                let declarations = result_types
2113                    .iter()
2114                    .zip(&result_names)
2115                    .map(|(ty, name)| {
2116                        let ty = wasm_type(*ty);
2117                        format!("var {name} {ty}")
2118                    })
2119                    .collect::<Vec<_>>()
2120                    .join("\n");
2121
2122                let some_result_assignments = some_results
2123                    .iter()
2124                    .zip(&result_names)
2125                    .map(|(result, name)| format!("{name} = {result}"))
2126                    .collect::<Vec<_>>()
2127                    .join("\n");
2128
2129                let none_result_assignments = none_results
2130                    .iter()
2131                    .zip(&result_names)
2132                    .map(|(result, name)| format!("{name} = {result}"))
2133                    .collect::<Vec<_>>()
2134                    .join("\n");
2135
2136                results.extend(result_names);
2137
2138                uwriteln!(
2139                    self.src,
2140                    r#"{declarations}
2141switch {value}.Tag() {{
2142case witTypes.OptionNone:
2143        {none}
2144        {none_result_assignments}
2145case witTypes.OptionSome:
2146        {VARIANT_PAYLOAD_NAME} := {value}.Some()
2147        {some}
2148        {some_result_assignments}
2149default:
2150        panic("unreachable")
2151}}"#
2152                );
2153            }
2154            Instruction::OptionLift { ty, payload } => {
2155                self.generator.need_option = true;
2156                self.imports.insert(remote_pkg("types"));
2157                let (some, some_results) = self.blocks.pop().unwrap();
2158                let (none, none_results) = self.blocks.pop().unwrap();
2159                assert!(none_results.is_empty());
2160                assert!(some_results.len() == 1);
2161                let some_result = &some_results[0];
2162                let ty = self.type_name(resolve, Type::Id(*ty));
2163                let some_type = self.type_name(resolve, **payload);
2164                let result = self.locals.tmp("option");
2165                let tag = &operands[0];
2166                uwriteln!(
2167                    self.src,
2168                    r#"var {result} {ty}
2169switch {tag} {{
2170case 0:
2171        {none}
2172        {result} = witTypes.None[{some_type}]()
2173case 1:
2174        {some}
2175        {result} = witTypes.Some[{some_type}]({some_result})
2176default:
2177        panic("unreachable")
2178}}"#
2179                );
2180                results.push(result);
2181            }
2182            Instruction::ResultLower {
2183                result,
2184                results: result_types,
2185                ..
2186            } => {
2187                self.generator.need_result = true;
2188                self.imports.insert(remote_pkg("types"));
2189                let (err, err_results) = self.blocks.pop().unwrap();
2190                let (ok, ok_results) = self.blocks.pop().unwrap();
2191                let value = &operands[0];
2192
2193                let result_names = (0..result_types.len())
2194                    .map(|_| self.locals.tmp("option"))
2195                    .collect::<Vec<_>>();
2196
2197                let declarations = result_types
2198                    .iter()
2199                    .zip(&result_names)
2200                    .map(|(ty, name)| {
2201                        let ty = wasm_type(*ty);
2202                        format!("var {name} {ty}")
2203                    })
2204                    .collect::<Vec<_>>()
2205                    .join("\n");
2206
2207                let ok_result_assignments = ok_results
2208                    .iter()
2209                    .zip(&result_names)
2210                    .map(|(result, name)| format!("{name} = {result}"))
2211                    .collect::<Vec<_>>()
2212                    .join("\n");
2213
2214                let err_result_assignments = err_results
2215                    .iter()
2216                    .zip(&result_names)
2217                    .map(|(result, name)| format!("{name} = {result}"))
2218                    .collect::<Vec<_>>()
2219                    .join("\n");
2220
2221                results.extend(result_names);
2222
2223                let ok_set_payload = if result.ok.is_some() {
2224                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Ok()")
2225                } else {
2226                    self.generator.need_unit = true;
2227                    String::new()
2228                };
2229
2230                let err_set_payload = if result.err.is_some() {
2231                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Err()")
2232                } else {
2233                    self.generator.need_unit = true;
2234                    String::new()
2235                };
2236
2237                uwriteln!(
2238                    self.src,
2239                    r#"{declarations}
2240switch {value}.Tag() {{
2241case witTypes.ResultOk:
2242        {ok_set_payload}
2243        {ok}
2244        {ok_result_assignments}
2245case witTypes.ResultErr:
2246        {err_set_payload}
2247        {err}
2248        {err_result_assignments}
2249default:
2250        panic("unreachable")
2251}}"#
2252                );
2253            }
2254            Instruction::ResultLift { ty, result, .. } => {
2255                self.generator.need_result = true;
2256                self.imports.insert(remote_pkg("types"));
2257                let (err, err_results) = self.blocks.pop().unwrap();
2258                let (ok, ok_results) = self.blocks.pop().unwrap();
2259                assert_eq!(ok_results.is_empty(), result.ok.is_none());
2260                assert_eq!(err_results.is_empty(), result.err.is_none());
2261                let ok_result = if result.ok.is_some() {
2262                    &ok_results[0]
2263                } else {
2264                    self.generator.need_unit = true;
2265                    "witTypes.Unit{}"
2266                };
2267                let err_result = if result.err.is_some() {
2268                    &err_results[0]
2269                } else {
2270                    self.generator.need_unit = true;
2271                    "witTypes.Unit{}"
2272                };
2273                let ty = self.type_name(resolve, Type::Id(*ty));
2274                let ok_type = result
2275                    .ok
2276                    .map(|ty| self.type_name(resolve, ty))
2277                    .unwrap_or_else(|| {
2278                        self.generator.need_unit = true;
2279                        "witTypes.Unit".into()
2280                    });
2281                let err_type = result
2282                    .err
2283                    .map(|ty| self.type_name(resolve, ty))
2284                    .unwrap_or_else(|| {
2285                        self.generator.need_unit = true;
2286                        "witTypes.Unit".into()
2287                    });
2288                let result = self.locals.tmp("result");
2289                let tag = &operands[0];
2290                uwriteln!(
2291                    self.src,
2292                    r#"var {result} {ty}
2293switch {tag} {{
2294case 0:
2295        {ok}
2296        {result} = witTypes.Ok[{ok_type}, {err_type}]({ok_result})
2297case 1:
2298        {err}
2299        {result} = witTypes.Err[{ok_type}, {err_type}]({err_result})
2300default:
2301        panic("unreachable")
2302}}"#
2303                );
2304                results.push(result);
2305            }
2306            Instruction::EnumLower { .. } => results.push(format!("int32({})", operands[0])),
2307            Instruction::EnumLift { enum_, .. } => {
2308                results.push(format!("{}({})", int_repr(enum_.tag()), operands[0]))
2309            }
2310            Instruction::VariantLower {
2311                ty,
2312                variant,
2313                results: result_types,
2314                ..
2315            } => {
2316                let blocks = self
2317                    .blocks
2318                    .drain(self.blocks.len() - variant.cases.len()..)
2319                    .collect::<Vec<_>>();
2320
2321                let ty = self.type_name(resolve, Type::Id(*ty));
2322                let value = &operands[0];
2323
2324                let result_names = (0..result_types.len())
2325                    .map(|_| self.locals.tmp("variant"))
2326                    .collect::<Vec<_>>();
2327
2328                let declarations = result_types
2329                    .iter()
2330                    .zip(&result_names)
2331                    .map(|(ty, name)| {
2332                        let ty = wasm_type(*ty);
2333                        format!("var {name} {ty}")
2334                    })
2335                    .collect::<Vec<_>>()
2336                    .join("\n");
2337
2338                let cases = variant
2339                    .cases
2340                    .iter()
2341                    .zip(blocks)
2342                    .map(|(case, (block, block_results))| {
2343                        let assignments = result_names
2344                            .iter()
2345                            .zip(&block_results)
2346                            .map(|(name, result)| format!("{name} = {result}"))
2347                            .collect::<Vec<_>>()
2348                            .join("\n");
2349
2350                        let name = case.name.to_upper_camel_case();
2351
2352                        let set_payload = if case.ty.is_some() {
2353                            format!("{VARIANT_PAYLOAD_NAME} := {value}.{name}()")
2354                        } else {
2355                            String::new()
2356                        };
2357
2358                        format!(
2359                            "case {ty}{name}:
2360        {set_payload}
2361        {block}
2362        {assignments}
2363"
2364                        )
2365                    })
2366                    .collect::<Vec<_>>()
2367                    .join("\n");
2368
2369                results.extend(result_names);
2370
2371                uwriteln!(
2372                    self.src,
2373                    r#"{declarations}
2374switch {value}.Tag() {{
2375{cases}
2376default:
2377        panic("unreachable")
2378}}"#
2379                );
2380            }
2381            Instruction::VariantLift { ty, variant, .. } => {
2382                let blocks = self
2383                    .blocks
2384                    .drain(self.blocks.len() - variant.cases.len()..)
2385                    .collect::<Vec<_>>();
2386
2387                let ty = self.type_name(resolve, Type::Id(*ty));
2388                let result = self.locals.tmp("variant");
2389                let tag = &operands[0];
2390
2391                let (package, name) = if let Some(index) = ty.find('.') {
2392                    (&ty[..index + 1], &ty[index + 1..])
2393                } else {
2394                    ("", ty.as_str())
2395                };
2396
2397                let cases = variant
2398                    .cases
2399                    .iter()
2400                    .zip(blocks)
2401                    .enumerate()
2402                    .map(|(index, (case, (block, block_results)))| {
2403                        assert_eq!(block_results.is_empty(), case.ty.is_none());
2404                        let payload = if case.ty.is_some() {
2405                            &block_results[0]
2406                        } else {
2407                            ""
2408                        };
2409                        let case = case.name.to_upper_camel_case();
2410                        format!(
2411                            "case {index}:
2412        {block}
2413        {result} = {package}Make{name}{case}({payload})
2414"
2415                        )
2416                    })
2417                    .collect::<Vec<_>>()
2418                    .join("\n");
2419
2420                uwriteln!(
2421                    self.src,
2422                    r#"var {result} {ty}
2423switch {tag} {{
2424{cases}
2425default:
2426        panic("unreachable")
2427}}"#
2428                );
2429                results.push(result);
2430            }
2431            Instruction::VariantPayloadName => results.push(VARIANT_PAYLOAD_NAME.into()),
2432            Instruction::IterElem { .. } => results.push(ITER_ELEMENT.into()),
2433            Instruction::IterBasePointer => results.push(ITER_BASE_POINTER.into()),
2434            Instruction::I32Const { val } => results.push(format!("int32({val})")),
2435            Instruction::ConstZero { tys } => {
2436                results.extend(iter::repeat_with(|| "0".into()).take(tys.len()));
2437            }
2438            Instruction::Bitcasts { casts } => {
2439                results.extend(
2440                    casts
2441                        .iter()
2442                        .zip(operands)
2443                        .map(|(which, op)| cast(op, which, &mut self.need_math)),
2444                );
2445            }
2446            Instruction::FutureLower { .. }
2447            | Instruction::StreamLower { .. }
2448            | Instruction::HandleLower {
2449                handle: Handle::Own(_),
2450                ..
2451            } => {
2452                let op = &operands[0];
2453                if self.collect_lifters {
2454                    self.lifter_count += 1;
2455                    let resource = self.locals.tmp("resource");
2456                    let handle = self.locals.tmp("handle");
2457                    uwriteln!(
2458                        self.src,
2459                        "{resource} := {op}
2460{handle} := {resource}.TakeHandle()
2461lifters = append(lifters, func() {{
2462        {resource}.SetHandle({handle})
2463}})"
2464                    );
2465                    results.push(handle)
2466                } else {
2467                    results.push(format!("({op}).TakeHandle()"))
2468                }
2469            }
2470            Instruction::HandleLower {
2471                handle: Handle::Borrow(_),
2472                ..
2473            } => results.push(format!("({}).Handle()", operands[0])),
2474            Instruction::HandleLift { handle, .. } => {
2475                let (which, resource) = match handle {
2476                    Handle::Borrow(resource) => ("Borrow", resource),
2477                    Handle::Own(resource) => ("Own", resource),
2478                };
2479                let handle = &operands[0];
2480                let ty = self.type_name(resolve, Type::Id(*resource));
2481                results.push(format!("{ty}From{which}Handle(int32(uintptr({handle})))"))
2482            }
2483            Instruction::CallWasm { sig, .. } => {
2484                let assignment = match &sig.results[..] {
2485                    [] => String::new(),
2486                    [_] => {
2487                        let result = self.locals.tmp("result");
2488                        let assignment = format!("{result} := ");
2489                        results.push(result);
2490                        assignment
2491                    }
2492                    _ => unreachable!(),
2493                };
2494                let name = &self.function_to_call;
2495                let params = operands.join(", ");
2496                uwriteln!(self.src, "{assignment}{name}({params})")
2497            }
2498            Instruction::Flush { amt } => {
2499                for op in operands.iter().take(*amt) {
2500                    let result = self.locals.tmp("result");
2501                    uwriteln!(self.src, "{result} := {op};");
2502                    results.push(result);
2503                }
2504            }
2505            Instruction::FutureLift { ty, .. } => {
2506                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2507                let owner = self
2508                    .generator
2509                    .futures_and_streams
2510                    .get(&(*ty, exported))
2511                    .unwrap()
2512                    .clone();
2513                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2514                let TypeDefKind::Future(payload_ty) = &resolve.types[*ty].kind else {
2515                    unreachable!()
2516                };
2517                let camel = if let Some(ty) = payload_ty {
2518                    self.generator
2519                        .mangle_name(resolve, *ty, owner.as_ref())
2520                        .to_upper_camel_case()
2521                } else {
2522                    "Unit".into()
2523                };
2524                let handle = &operands[0];
2525                results.push(format!("{package}LiftFuture{camel}({handle})"));
2526            }
2527            Instruction::StreamLift { ty, .. } => {
2528                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2529                let owner = self
2530                    .generator
2531                    .futures_and_streams
2532                    .get(&(*ty, exported))
2533                    .unwrap()
2534                    .clone();
2535                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2536                let TypeDefKind::Stream(payload_ty) = &resolve.types[*ty].kind else {
2537                    unreachable!()
2538                };
2539                let camel = if let Some(ty) = payload_ty {
2540                    self.generator
2541                        .mangle_name(resolve, *ty, owner.as_ref())
2542                        .to_upper_camel_case()
2543                } else {
2544                    "Unit".into()
2545                };
2546                let handle = &operands[0];
2547                results.push(format!("{package}LiftStream{camel}({handle})"));
2548            }
2549            Instruction::GuestDeallocate { .. } => {
2550                // Nothing to do here; should be handled when calling `pinner.Unpin()`
2551            }
2552            _ => unimplemented!("{instruction:?}"),
2553        }
2554    }
2555}
2556
2557struct InterfaceGenerator<'a> {
2558    generator: &'a mut Go,
2559    resolve: &'a Resolve,
2560    interface: Option<(InterfaceId, &'a WorldKey)>,
2561    in_import: bool,
2562    src: String,
2563    imports: BTreeSet<String>,
2564    need_unsafe: bool,
2565    need_runtime: bool,
2566}
2567
2568impl<'a> InterfaceGenerator<'a> {
2569    fn new(
2570        generator: &'a mut Go,
2571        resolve: &'a Resolve,
2572        interface: Option<(InterfaceId, &'a WorldKey)>,
2573        in_import: bool,
2574    ) -> Self {
2575        Self {
2576            generator,
2577            resolve,
2578            interface,
2579            in_import,
2580            src: String::new(),
2581            imports: BTreeSet::new(),
2582            need_unsafe: false,
2583            need_runtime: false,
2584        }
2585    }
2586
2587    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
2588        self.generator.type_name(
2589            resolve,
2590            ty,
2591            self.interface.map(|(_, key)| key),
2592            self.in_import || !self.generator.has_exported_resource(resolve, ty),
2593            &mut self.imports,
2594        )
2595    }
2596}
2597
2598impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
2599    fn resolve(&self) -> &'a Resolve {
2600        self.resolve
2601    }
2602
2603    fn type_record(&mut self, _: TypeId, name: &str, record: &Record, docs: &Docs) {
2604        let name = name.to_upper_camel_case();
2605
2606        let fields = record
2607            .fields
2608            .iter()
2609            .map(|field| {
2610                let ty = self.type_name(self.resolve, field.ty);
2611                let docs = format_docs(&field.docs);
2612                let field = field.name.to_upper_camel_case();
2613                format!("{docs}{field} {ty}")
2614            })
2615            .collect::<Vec<_>>()
2616            .join("\n");
2617
2618        let docs = format_docs(docs);
2619
2620        uwriteln!(
2621            self.src,
2622            "
2623{docs}type {name} struct {{
2624        {fields}
2625}}"
2626        )
2627    }
2628
2629    fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs) {
2630        self.generator.resources.insert(
2631            id,
2632            if self.in_import {
2633                Direction::Import
2634            } else {
2635                Direction::Export
2636            },
2637        );
2638
2639        let camel = name.to_upper_camel_case();
2640        let module = self
2641            .interface
2642            .map(|(_, key)| self.resolve.name_world_key(key))
2643            .unwrap_or_else(|| "$root".into());
2644
2645        if self.in_import {
2646            self.imports.insert(remote_pkg("runtime"));
2647            self.need_runtime = true;
2648            let docs = format_docs(docs);
2649            uwriteln!(
2650                self.src,
2651                r#"
2652//go:wasmimport {module} [resource-drop]{name}
2653func resourceDrop{camel}(handle int32)
2654
2655{docs}type {camel} struct {{
2656        handle *witRuntime.Handle
2657}}
2658
2659func (self *{camel}) TakeHandle() int32 {{
2660        return self.handle.Take()
2661}}
2662
2663func (self *{camel}) SetHandle(handle int32) {{
2664        self.handle.Set(handle)
2665}}
2666
2667func (self *{camel}) Handle() int32 {{
2668        return self.handle.Use()
2669}}
2670
2671func (self *{camel}) Drop() {{
2672	handle := self.handle.TakeOrNil()
2673	if handle != 0 {{
2674		resourceDrop{camel}(handle)
2675	}}
2676}}
2677
2678func {camel}FromOwnHandle(handleValue int32) *{camel} {{
2679        handle := witRuntime.MakeHandle(handleValue)
2680        value := &{camel}{{handle}}
2681        runtime.AddCleanup(value, func(_ int) {{
2682                handleValue := handle.TakeOrNil()
2683                if handleValue != 0 {{
2684                        resourceDrop{camel}(handleValue)
2685                }}
2686        }}, 0)
2687        return value
2688}}
2689
2690func {camel}FromBorrowHandle(handleValue int32) *{camel} {{
2691	handle := witRuntime.MakeHandle(handleValue)
2692	return &{camel}{{handle}}
2693}}
2694"#
2695            );
2696        } else {
2697            self.need_unsafe = true;
2698            uwriteln!(
2699                self.src,
2700                r#"
2701//go:wasmimport [export]{module} [resource-new]{name}
2702func resourceNew{camel}(pointer unsafe.Pointer) int32
2703
2704//go:wasmimport [export]{module} [resource-rep]{name}
2705func resourceRep{camel}(handle int32) unsafe.Pointer
2706
2707//go:wasmimport [export]{module} [resource-drop]{name}
2708func resourceDrop{camel}(handle int32)
2709
2710//go:wasmexport {module}#[dtor]{name}
2711func resourceDtor{camel}(rep int32) {{
2712        val := (*{camel})(unsafe.Pointer(uintptr(rep)))
2713        val.handle = 0
2714        val.pinner.Unpin()
2715        val.OnDrop()
2716}}
2717
2718func (self *{camel}) TakeHandle() int32 {{
2719	self.pinner.Pin(self)
2720	self.handle = resourceNew{camel}(unsafe.Pointer(self))
2721	return self.handle
2722}}
2723
2724func (self *{camel}) SetHandle(handle int32) {{
2725        if self.handle != handle {{
2726                panic("invalid handle")
2727        }}
2728}}
2729
2730func (self *{camel}) Drop() {{
2731	handle := self.handle
2732	if self.handle != 0 {{
2733		self.handle = 0
2734		resourceDrop{camel}(handle)
2735		self.pinner.Unpin()
2736                self.OnDrop()
2737	}}
2738}}
2739
2740func {camel}FromOwnHandle(handle int32) *{camel} {{
2741	return (*{camel})(unsafe.Pointer(resourceRep{camel}(handle)))
2742}}
2743
2744func {camel}FromBorrowHandle(rep int32) *{camel} {{
2745	return (*{camel})(unsafe.Pointer(uintptr(rep)))
2746}}
2747"#
2748            );
2749
2750            if self.generator.opts.generate_stubs {
2751                self.need_runtime = true;
2752                uwriteln!(
2753                    self.src,
2754                    r#"
2755type {camel} struct {{
2756        pinner runtime.Pinner
2757        handle int32
2758}}
2759
2760func (self *{camel}) OnDrop() {{}}
2761"#
2762                );
2763            }
2764        }
2765    }
2766
2767    fn type_flags(&mut self, _: TypeId, name: &str, flags: &Flags, docs: &Docs) {
2768        let repr = flags_repr(flags);
2769
2770        let name = name.to_upper_camel_case();
2771
2772        let constants = flags
2773            .flags
2774            .iter()
2775            .enumerate()
2776            .map(|(i, flag)| {
2777                let docs = format_docs(&flag.docs);
2778                let flag = flag.name.to_upper_camel_case();
2779                format!("{docs}{name}{flag} {repr} = 1 << {i}")
2780            })
2781            .collect::<Vec<_>>()
2782            .join("\n");
2783
2784        let docs = format_docs(docs);
2785
2786        uwriteln!(
2787            self.src,
2788            "
2789const (
2790{constants}
2791)
2792
2793{docs}type {name} = {repr}"
2794        )
2795    }
2796
2797    fn type_tuple(&mut self, _: TypeId, name: &str, tuple: &Tuple, docs: &Docs) {
2798        self.imports.insert(remote_pkg("types"));
2799        let count = tuple.types.len();
2800        self.generator.tuples.insert(count);
2801        let name = name.to_upper_camel_case();
2802        let docs = format_docs(docs);
2803        let types = tuple
2804            .types
2805            .iter()
2806            .map(|ty| self.type_name(self.resolve, *ty))
2807            .collect::<Vec<_>>()
2808            .join(", ");
2809
2810        uwriteln!(
2811            self.src,
2812            "{docs}type {name} = witTypes.Tuple{count}[{types}]"
2813        );
2814    }
2815
2816    fn type_variant(&mut self, _: TypeId, name: &str, variant: &Variant, docs: &Docs) {
2817        let repr = int_repr(variant.tag());
2818
2819        let name = name.to_upper_camel_case();
2820
2821        let constants = variant
2822            .cases
2823            .iter()
2824            .enumerate()
2825            .map(|(i, case)| {
2826                let docs = format_docs(&case.docs);
2827                let case = case.name.to_upper_camel_case();
2828                format!("{docs}{name}{case} {repr} = {i}")
2829            })
2830            .collect::<Vec<_>>()
2831            .join("\n");
2832
2833        let getters = variant
2834            .cases
2835            .iter()
2836            .filter_map(|case| {
2837                case.ty.map(|ty| {
2838                    let case = case.name.to_upper_camel_case();
2839                    let ty = self.type_name(self.resolve, ty);
2840                    format!(
2841                        r#"func (self {name}) {case}() {ty} {{
2842        if self.tag != {name}{case} {{
2843                panic("tag mismatch")
2844        }}
2845        return self.value.({ty})
2846}}
2847"#
2848                    )
2849                })
2850            })
2851            .collect::<Vec<_>>()
2852            .concat();
2853
2854        let constructors = variant
2855            .cases
2856            .iter()
2857            .map(|case| {
2858                let (param, value) = if let Some(ty) = case.ty {
2859                    let ty = self.type_name(self.resolve, ty);
2860                    (format!("value {ty}"), "value")
2861                } else {
2862                    (String::new(), "nil")
2863                };
2864                let case = case.name.to_upper_camel_case();
2865                format!(
2866                    r#"func Make{name}{case}({param}) {name} {{
2867        return {name}{{{name}{case}, {value}}}
2868}}
2869"#
2870                )
2871            })
2872            .collect::<Vec<_>>()
2873            .concat();
2874
2875        let docs = format_docs(docs);
2876
2877        uwriteln!(
2878            self.src,
2879            "
2880const (
2881{constants}
2882)
2883
2884{docs}type {name} struct {{
2885        tag {repr}
2886        value any
2887}}
2888
2889func (self {name}) Tag() {repr} {{
2890        return self.tag
2891}}
2892
2893{getters}
2894{constructors}
2895"
2896        )
2897    }
2898
2899    fn type_option(&mut self, _: TypeId, name: &str, payload: &Type, docs: &Docs) {
2900        self.generator.need_option = true;
2901        self.imports.insert(remote_pkg("types"));
2902        let name = name.to_upper_camel_case();
2903        let ty = self.type_name(self.resolve, *payload);
2904        let docs = format_docs(docs);
2905        uwriteln!(self.src, "{docs}type {name} = witTypes.Option[{ty}]");
2906    }
2907
2908    fn type_result(&mut self, _: TypeId, name: &str, result: &Result_, docs: &Docs) {
2909        self.generator.need_result = true;
2910        self.imports.insert(remote_pkg("types"));
2911        let name = name.to_upper_camel_case();
2912        let ok_type = result
2913            .ok
2914            .map(|ty| self.type_name(self.resolve, ty))
2915            .unwrap_or_else(|| {
2916                self.generator.need_unit = true;
2917                "witTypes.Unit".into()
2918            });
2919        let err_type = result
2920            .err
2921            .map(|ty| self.type_name(self.resolve, ty))
2922            .unwrap_or_else(|| {
2923                self.generator.need_unit = true;
2924                "witTypes.Unit".into()
2925            });
2926        let docs = format_docs(docs);
2927        uwriteln!(
2928            self.src,
2929            "{docs}type {name} = witTypes.Result[{ok_type}, {err_type}]"
2930        );
2931    }
2932
2933    fn type_enum(&mut self, _: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
2934        let repr = int_repr(enum_.tag());
2935
2936        let name = name.to_upper_camel_case();
2937
2938        let constants = enum_
2939            .cases
2940            .iter()
2941            .enumerate()
2942            .map(|(i, case)| {
2943                let docs = format_docs(&case.docs);
2944                let case = case.name.to_upper_camel_case();
2945                format!("{docs}{name}{case} {repr} = {i}")
2946            })
2947            .collect::<Vec<_>>()
2948            .join("\n");
2949
2950        let docs = format_docs(docs);
2951
2952        uwriteln!(
2953            self.src,
2954            "
2955const (
2956        {constants}
2957)
2958{docs}type {name} = {repr}"
2959        )
2960    }
2961
2962    fn type_alias(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2963        let name = name.to_upper_camel_case();
2964        let ty = self.type_name(self.resolve, *ty);
2965        let docs = format_docs(docs);
2966        uwriteln!(self.src, "{docs}type {name} = {ty}");
2967    }
2968
2969    fn type_list(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2970        let name = name.to_upper_camel_case();
2971        let ty = self.type_name(self.resolve, *ty);
2972        let docs = format_docs(docs);
2973        uwriteln!(self.src, "{docs}type {name} = []{ty}");
2974    }
2975
2976    fn type_fixed_length_list(&mut self, _: TypeId, name: &str, ty: &Type, size: u32, docs: &Docs) {
2977        let name = name.to_upper_camel_case();
2978        let ty = self.type_name(self.resolve, *ty);
2979        let docs = format_docs(docs);
2980        uwriteln!(self.src, "{docs}type {name} = [{size}]{ty}");
2981    }
2982
2983    fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
2984        _ = (id, name, ty, docs);
2985        todo!()
2986    }
2987
2988    fn type_future(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2989        let name = name.to_upper_camel_case();
2990        let ty = self.type_name(self.resolve, Type::Id(id));
2991        let docs = format_docs(docs);
2992        uwriteln!(self.src, "{docs}type {name} = {ty}");
2993    }
2994
2995    fn type_stream(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2996        let name = name.to_upper_camel_case();
2997        let ty = self.type_name(self.resolve, Type::Id(id));
2998        let docs = format_docs(docs);
2999        uwriteln!(self.src, "{docs}type {name} = {ty}");
3000    }
3001}
3002
3003fn wasm_type(ty: WasmType) -> &'static str {
3004    match ty {
3005        WasmType::I32 => "int32",
3006        WasmType::I64 => "int64",
3007        WasmType::F32 => "float32",
3008        WasmType::F64 => "float64",
3009        WasmType::Pointer => "uintptr",
3010        WasmType::PointerOrI64 => "int64",
3011        WasmType::Length => "uint32",
3012    }
3013}
3014
3015fn format_docs(docs: &Docs) -> String {
3016    docs.contents
3017        .as_ref()
3018        .map(|v| {
3019            v.trim()
3020                .lines()
3021                .map(|line| format!("// {line}\n"))
3022                .collect::<Vec<_>>()
3023                .concat()
3024        })
3025        .unwrap_or_default()
3026}
3027
3028fn flags_repr(flags: &Flags) -> &'static str {
3029    match flags.repr() {
3030        FlagsRepr::U8 => "uint8",
3031        FlagsRepr::U16 => "uint16",
3032        FlagsRepr::U32(1) => "uint32",
3033        _ => unreachable!(),
3034    }
3035}
3036
3037fn int_repr(int: Int) -> &'static str {
3038    match int {
3039        Int::U8 => "uint8",
3040        Int::U16 => "uint16",
3041        Int::U32 => "uint32",
3042        Int::U64 => unreachable!(),
3043    }
3044}
3045
3046fn cast(op: &str, which: &Bitcast, need_math: &mut bool) -> String {
3047    match which {
3048        Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
3049            *need_math = true;
3050            format!("math.Float32frombits(uint32({op}))")
3051        }
3052        Bitcast::F32ToI32 => {
3053            *need_math = true;
3054            format!("int32(math.Float32bits({op}))")
3055        }
3056        Bitcast::F32ToI64 => {
3057            *need_math = true;
3058            format!("int64(math.Float32bits({op}))")
3059        }
3060        Bitcast::I64ToF64 => {
3061            *need_math = true;
3062            format!("math.Float64frombits(uint64({op}))")
3063        }
3064        Bitcast::F64ToI64 => {
3065            *need_math = true;
3066            format!("int64(math.Float64bits({op}))")
3067        }
3068        Bitcast::I32ToI64 | Bitcast::LToI64 => {
3069            format!("int64({op})")
3070        }
3071        Bitcast::PToP64 => {
3072            format!("int64({op})")
3073        }
3074        Bitcast::I64ToI32 | Bitcast::I64ToL | Bitcast::PToI32 => {
3075            format!("int32({op})")
3076        }
3077        Bitcast::I64ToP64 | Bitcast::P64ToI64 => op.into(),
3078        Bitcast::P64ToP | Bitcast::LToP | Bitcast::I32ToP => {
3079            format!("uintptr({op})")
3080        }
3081        Bitcast::PToL => {
3082            format!("uint32({op})")
3083        }
3084        Bitcast::I32ToL => {
3085            format!("uint32({op})")
3086        }
3087        Bitcast::LToI32 => {
3088            format!("uint32({op})")
3089        }
3090        Bitcast::None => op.to_string(),
3091        Bitcast::Sequence(sequence) => {
3092            let [first, second] = &**sequence;
3093            let inner = cast(op, first, need_math);
3094            cast(&inner, second, need_math)
3095        }
3096    }
3097}
3098
3099fn any(resolve: &Resolve, ty: Type, fun: &dyn Fn(Type) -> bool) -> bool {
3100    if fun(ty) {
3101        return true;
3102    }
3103
3104    match ty {
3105        Type::Bool
3106        | Type::U8
3107        | Type::S8
3108        | Type::U16
3109        | Type::S16
3110        | Type::U32
3111        | Type::S32
3112        | Type::U64
3113        | Type::S64
3114        | Type::F32
3115        | Type::F64
3116        | Type::Char
3117        | Type::String => false,
3118        Type::Id(id) => {
3119            let ty = &resolve.types[id];
3120            match &ty.kind {
3121                TypeDefKind::Flags(_) | TypeDefKind::Enum(_) | TypeDefKind::Resource => false,
3122                TypeDefKind::Handle(Handle::Own(resource) | Handle::Borrow(resource)) => {
3123                    any(resolve, Type::Id(*resource), fun)
3124                }
3125                TypeDefKind::Record(record) => record
3126                    .fields
3127                    .iter()
3128                    .any(|field| any(resolve, field.ty, fun)),
3129                TypeDefKind::Variant(variant) => variant
3130                    .cases
3131                    .iter()
3132                    .any(|case| case.ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)),
3133                TypeDefKind::Option(ty) | TypeDefKind::List(ty) | TypeDefKind::Type(ty) => {
3134                    any(resolve, *ty, fun)
3135                }
3136                TypeDefKind::Result(result) => result
3137                    .ok
3138                    .map(|ty| any(resolve, ty, fun))
3139                    .or_else(|| result.err.map(|ty| any(resolve, ty, fun)))
3140                    .unwrap_or(false),
3141                TypeDefKind::Tuple(tuple) => tuple.types.iter().any(|ty| any(resolve, *ty, fun)),
3142                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
3143                    ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)
3144                }
3145                _ => todo!("{:?}", ty.kind),
3146            }
3147        }
3148        _ => todo!("{ty:?}"),
3149    }
3150}
3151
3152fn func_declaration(resolve: &Resolve, func: &Function) -> (String, bool) {
3153    match &func.kind {
3154        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
3155            (func.item_name().to_upper_camel_case(), false)
3156        }
3157        FunctionKind::Constructor(ty) => {
3158            let ty = resolve.types[*ty]
3159                .name
3160                .as_ref()
3161                .unwrap()
3162                .to_upper_camel_case();
3163            (format!("Make{ty}"), false)
3164        }
3165        FunctionKind::Method(ty) | FunctionKind::AsyncMethod(ty) => {
3166            let ty = resolve.types[*ty]
3167                .name
3168                .as_ref()
3169                .unwrap()
3170                .to_upper_camel_case();
3171            let camel = func.item_name().to_upper_camel_case();
3172            (format!("(self *{ty}) {camel}"), true)
3173        }
3174        FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
3175            let ty = resolve.types[*ty]
3176                .name
3177                .as_ref()
3178                .unwrap()
3179                .to_upper_camel_case();
3180            let camel = func.item_name().to_upper_camel_case();
3181            (format!("{ty}{camel}"), false)
3182        }
3183    }
3184}
3185
3186fn maybe_gofmt<'a>(format: Format, code: &'a [u8]) -> Cow<'a, [u8]> {
3187    thread::scope(|s| {
3188        if let Format::True = format
3189            && let Ok((reader, mut writer)) = io::pipe()
3190        {
3191            s.spawn(move || {
3192                _ = writer.write_all(code);
3193            });
3194
3195            if let Ok(output) = Command::new("gofmt").stdin(reader).output()
3196                && output.status.success()
3197            {
3198                return Cow::Owned(output.stdout);
3199            }
3200        }
3201
3202        Cow::Borrowed(code)
3203    })
3204}