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