Skip to main content

wit_bindgen_go/
lib.rs

1use anyhow::Result;
2use heck::{ToLowerCamelCase as _, ToSnakeCase as _, ToUpperCamelCase as _};
3use std::borrow::Cow;
4use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, hash_map};
5use std::fmt;
6use std::fmt::Write as _;
7use std::io::{self, Write as _};
8use std::iter;
9use std::mem;
10use std::process::Command;
11use std::str::FromStr;
12use std::thread;
13use wit_bindgen_core::abi::{
14    self, AbiVariant, Bindgen, Bitcast, FlatTypes, Instruction, LiftLower, WasmType,
15};
16use wit_bindgen_core::wit_parser::{
17    Alignment, ArchitectureSize, Docs, Enum, Flags, FlagsRepr, Function, FunctionKind, Handle, Int,
18    InterfaceId, Package, PackageName, Param, Record, Resolve, Result_, SizeAlign, Tuple, Type,
19    TypeDefKind, TypeId, TypeOwner, Variant, WorldId, WorldKey,
20};
21use wit_bindgen_core::{
22    AsyncFilterSet, Direction, Files, InterfaceGenerator as _, Ns, WorldGenerator, uwriteln,
23};
24
25const MAX_FLAT_PARAMS: usize = 16;
26
27const POINTER_SIZE_EXPRESSION: &str = "4";
28const VARIANT_PAYLOAD_NAME: &str = "payload";
29const ITER_BASE_POINTER: &str = "base";
30const ITER_ELEMENT: &str = "element";
31const IMPORT_RETURN_AREA: &str = "returnArea";
32const EXPORT_RETURN_AREA: &str = "exportReturnArea";
33const SYNC_EXPORT_PINNER: &str = "syncExportPinner";
34const PINNER: &str = "pinner";
35
36/// Adds the 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    // FIXME(#1527): this caused failures in CI at
665    // https://github.com/bytecodealliance/wit-bindgen/actions/runs/21880247244/job/63160400774?pr=1526
666    // and should be fixed at some point by deleting this method and getting
667    // tests passing again.
668    fn uses_nominal_type_ids(&self) -> bool {
669        false
670    }
671
672    fn preprocess(&mut self, resolve: &Resolve, world: WorldId) {
673        _ = world;
674        self.sizes.fill(resolve);
675        self.imports.insert(remote_pkg("wit_runtime"));
676    }
677
678    fn import_interface(
679        &mut self,
680        resolve: &Resolve,
681        name: &WorldKey,
682        id: InterfaceId,
683        _files: &mut Files,
684    ) -> Result<()> {
685        if let WorldKey::Name(_) = name {
686            self.interface_names.insert(id, name.clone());
687        }
688
689        let mut data = {
690            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), true);
691            for (name, ty) in resolve.interfaces[id].types.iter() {
692                if !generator.generator.types.contains(ty) {
693                    generator.generator.types.insert(*ty);
694                    generator.define_type(name, *ty);
695                }
696            }
697            InterfaceData::from(generator)
698        };
699
700        for (_, func) in &resolve.interfaces[id].functions {
701            data.extend(self.import(resolve, func, Some(name)));
702        }
703        self.interfaces
704            .entry(interface_name(resolve, Some(name)))
705            .or_default()
706            .extend(data);
707
708        Ok(())
709    }
710
711    fn import_funcs(
712        &mut self,
713        resolve: &Resolve,
714        _world: WorldId,
715        funcs: &[(&str, &Function)],
716        _files: &mut Files,
717    ) {
718        let mut data = InterfaceData::default();
719        for (_, func) in funcs {
720            data.extend(self.import(resolve, func, None));
721        }
722        self.interfaces
723            .entry(interface_name(resolve, None))
724            .or_default()
725            .extend(data);
726    }
727
728    fn export_interface(
729        &mut self,
730        resolve: &Resolve,
731        name: &WorldKey,
732        id: InterfaceId,
733        _files: &mut Files,
734    ) -> Result<()> {
735        if let WorldKey::Name(_) = name {
736            self.interface_names.insert(id, name.clone());
737        }
738
739        for (type_name, ty) in &resolve.interfaces[id].types {
740            let exported = matches!(resolve.types[*ty].kind, TypeDefKind::Resource)
741                || self.has_exported_resource(resolve, Type::Id(*ty));
742
743            let mut generator = InterfaceGenerator::new(self, resolve, Some((id, name)), false);
744
745            if exported || !generator.generator.types.contains(ty) {
746                generator.generator.types.insert(*ty);
747                generator.define_type(type_name, *ty);
748            }
749
750            let data = generator.into();
751
752            if exported {
753                &mut self.export_interfaces
754            } else {
755                &mut self.interfaces
756            }
757            .entry(interface_name(resolve, Some(name)))
758            .or_default()
759            .extend(data);
760        }
761
762        for (_, func) in &resolve.interfaces[id].functions {
763            let code = self.export(resolve, func, Some(name));
764            self.src.push_str(&code);
765        }
766
767        Ok(())
768    }
769
770    fn export_funcs(
771        &mut self,
772        resolve: &Resolve,
773        _world: WorldId,
774        funcs: &[(&str, &Function)],
775        _files: &mut Files,
776    ) -> Result<()> {
777        for (_, func) in funcs {
778            let code = self.export(resolve, func, None);
779            self.src.push_str(&code);
780        }
781        Ok(())
782    }
783
784    fn import_types(
785        &mut self,
786        resolve: &Resolve,
787        _world: WorldId,
788        types: &[(&str, TypeId)],
789        _files: &mut Files,
790    ) {
791        let mut generator = InterfaceGenerator::new(self, resolve, None, true);
792        for (name, ty) in types {
793            if !generator.generator.types.contains(ty) {
794                generator.generator.types.insert(*ty);
795                generator.define_type(name, *ty);
796            }
797        }
798        let data = generator.into();
799        self.interfaces
800            .entry(interface_name(resolve, None))
801            .or_default()
802            .extend(data);
803    }
804
805    fn finish(&mut self, resolve: &Resolve, id: WorldId, files: &mut Files) -> Result<()> {
806        _ = (resolve, id);
807
808        let version = env!("CARGO_PKG_VERSION");
809        let packages = resolve
810            .packages
811            .iter()
812            .map(
813                |(
814                    _,
815                    Package {
816                        name:
817                            PackageName {
818                                namespace,
819                                name,
820                                version,
821                            },
822                        ..
823                    },
824                )| {
825                    let version = if let Some(version) = version {
826                        format!("@{version}")
827                    } else {
828                        String::new()
829                    };
830                    format!("//     {namespace}:{name}{version}")
831                },
832            )
833            .collect::<Vec<_>>()
834            .join("\n");
835        let header = &format!(
836            "// Generated by `wit-bindgen` {version}. DO NOT EDIT!
837//
838// This code was generated from the following packages:
839{packages}
840"
841        );
842
843        let src = mem::take(&mut self.src);
844        let align = self.return_area_align.format(POINTER_SIZE_EXPRESSION);
845        let size = self.return_area_size.format(POINTER_SIZE_EXPRESSION);
846        let imports = self
847            .imports
848            .iter()
849            .map(|s| s.as_str())
850            .chain(self.need_math.then_some(r#""math""#))
851            .chain(self.need_unsafe.then_some(r#""unsafe""#))
852            .collect::<Vec<_>>()
853            .join("\n");
854
855        let (exports_file_path, package_name, main_func) = if self.opts.pkg_name.is_some() {
856            // If a module name is specified, the generated files will be used as a library.
857            ("wit_exports/wit_exports.go", "wit_exports", "")
858        } else {
859            // This is the literal location of the Go package.
860            let replacement_pkg = concat!(
861                "github.com/bytecodealliance/wit-bindgen/crates/go/src/package v",
862                env!("CARGO_PKG_VERSION")
863            );
864
865            files.push(
866                "go.mod",
867                format!(
868                    "module {}\n\ngo 1.25\n\nreplace github.com/bytecodealliance/wit-bindgen => {}",
869                    self.opts.pkg_name.as_deref().unwrap_or("wit_component"),
870                    replacement_pkg
871                )
872                .as_bytes(),
873            );
874
875            // If a module name is NOT specified, the generated files will be used as a
876            // standalone executable.
877            (
878                "wit_exports.go",
879                "main",
880                r#"// Unused, but present to make the compiler happy
881func main() {}
882"#,
883            )
884        };
885
886        files.push(
887            exports_file_path,
888            &maybe_gofmt(
889                self.opts.format,
890                format!(
891                    r#"{header}
892package {package_name}
893
894import (
895        "runtime"
896        {imports}
897)
898
899var staticPinner = runtime.Pinner{{}}
900var {EXPORT_RETURN_AREA} = uintptr(wit_runtime.Allocate(&staticPinner, {size}, {align}))
901var {SYNC_EXPORT_PINNER} = runtime.Pinner{{}}
902
903{src}
904
905{main_func}
906"#
907                )
908                .as_bytes(),
909            ),
910        );
911
912        for (prefix, interfaces) in [("export_", &self.export_interfaces), ("", &self.interfaces)] {
913            for (name, data) in interfaces {
914                let imports = data.imports();
915                let code = &data.code;
916
917                files.push(
918                    &format!("{prefix}{name}/wit_bindings.go"),
919                    &maybe_gofmt(
920                        self.opts.format,
921                        format!(
922                            "{header}
923package {prefix}{name}
924
925import (
926        {imports}
927)
928
929{code}"
930                        )
931                        .as_bytes(),
932                    ),
933                );
934            }
935        }
936
937        Ok(())
938    }
939}
940
941impl Go {
942    fn import(
943        &mut self,
944        resolve: &Resolve,
945        func: &Function,
946        interface: Option<&WorldKey>,
947    ) -> InterfaceData {
948        self.visit_futures_and_streams(true, resolve, func, interface);
949
950        let async_ = self.opts.async_.is_async(resolve, interface, func, true);
951
952        let (variant, prefix) = if async_ {
953            (AbiVariant::GuestImportAsync, "[async-lower]")
954        } else {
955            (AbiVariant::GuestImport, "")
956        };
957
958        let sig = resolve.wasm_signature(variant, func);
959        let import_name = &func.name;
960        let name = func.name.to_snake_case().replace('.', "_");
961        let (camel, has_self) = func_declaration(resolve, func);
962
963        let module = match interface {
964            Some(name) => resolve.name_world_key(name),
965            None => "$root".to_string(),
966        };
967
968        let params = sig
969            .params
970            .iter()
971            .enumerate()
972            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
973            .collect::<Vec<_>>()
974            .join(", ");
975
976        let results = match &sig.results[..] {
977            [] => "",
978            [result] => wasm_type(*result),
979            _ => unreachable!(),
980        };
981
982        let mut imports = BTreeSet::new();
983        let go_params =
984            self.func_params(resolve, func, interface, true, &mut imports, has_self, "");
985        let go_results = self.func_results(resolve, func, interface, true, &mut imports);
986
987        let raw_name = format!("wasm_import_{name}");
988
989        let go_param_names = has_self
990            .then(|| "self".to_string())
991            .into_iter()
992            .chain(
993                func.params
994                    .iter()
995                    .skip(if has_self { 1 } else { 0 })
996                    .map(|Param { name, .. }| name.to_lower_camel_case()),
997            )
998            .collect::<Vec<_>>();
999
1000        let mut generator = FunctionGenerator::new(
1001            self,
1002            None,
1003            interface,
1004            interface,
1005            &raw_name,
1006            go_param_names.clone(),
1007            false,
1008            true,
1009        );
1010        generator.imports = imports;
1011
1012        let code = if async_ {
1013            generator.imports.insert(remote_pkg("wit_async"));
1014
1015            let (lower, wasm_params) = if sig.indirect_params {
1016                generator.imports.insert(remote_pkg("wit_runtime"));
1017
1018                let params_pointer = generator.locals.tmp("params");
1019                let abi = generator
1020                    .generator
1021                    .sizes
1022                    .record(func.params.iter().map(|Param { ty, .. }| ty));
1023                let size = abi.size.format(POINTER_SIZE_EXPRESSION);
1024                let align = abi.align.format(POINTER_SIZE_EXPRESSION);
1025                let offsets = generator
1026                    .generator
1027                    .sizes
1028                    .field_offsets(func.params.iter().map(|Param { ty, .. }| ty));
1029
1030                for (name, (offset, ty)) in go_param_names.iter().zip(offsets) {
1031                    let offset = offset.format(POINTER_SIZE_EXPRESSION);
1032                    abi::lower_to_memory(
1033                        resolve,
1034                        &mut generator,
1035                        format!("unsafe.Add(unsafe.Pointer({params_pointer}), {offset})"),
1036                        name.clone(),
1037                        ty,
1038                    );
1039                }
1040
1041                let code = mem::take(&mut generator.src);
1042                generator.need_pinner = true;
1043                (
1044                    format!(
1045                        "{params_pointer} := wit_runtime.Allocate({PINNER}, {size}, {align})\n{code}"
1046                    ),
1047                    vec![format!("uintptr({params_pointer})")],
1048                )
1049            } else {
1050                let wasm_params = go_param_names
1051                    .iter()
1052                    .zip(&func.params)
1053                    .flat_map(|(name, Param { ty, .. })| {
1054                        abi::lower_flat(resolve, &mut generator, name.clone(), ty)
1055                    })
1056                    .collect();
1057                (mem::take(&mut generator.src), wasm_params)
1058            };
1059
1060            let wasm_params = wasm_params
1061                .iter()
1062                .map(|v| v.as_str())
1063                .chain(func.result.map(|_| IMPORT_RETURN_AREA))
1064                .collect::<Vec<_>>()
1065                .join(", ");
1066
1067            let lift = if let Some(ty) = func.result {
1068                let result = abi::lift_from_memory(
1069                    resolve,
1070                    &mut generator,
1071                    IMPORT_RETURN_AREA.to_string(),
1072                    &ty,
1073                );
1074                let code = mem::take(&mut generator.src);
1075                if let Type::Id(ty) = ty
1076                    && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1077                {
1078                    let count = tuple.types.len();
1079                    let tuple = generator.locals.tmp("tuple");
1080
1081                    let results = (0..count)
1082                        .map(|index| format!("{tuple}.F{index}"))
1083                        .collect::<Vec<_>>()
1084                        .join(", ");
1085
1086                    format!(
1087                        "{code}
1088{tuple} := {result}
1089return {results}"
1090                    )
1091                } else {
1092                    format!("{code}\nreturn {result}")
1093                }
1094            } else {
1095                String::new()
1096            };
1097
1098            format!(
1099                "{lower}
1100wit_async.SubtaskWait(uint32({raw_name}({wasm_params})))
1101{lift}
1102"
1103            )
1104        } else {
1105            abi::call(
1106                resolve,
1107                variant,
1108                LiftLower::LowerArgsLiftResults,
1109                func,
1110                &mut generator,
1111                false,
1112            );
1113            mem::take(&mut generator.src)
1114        };
1115
1116        let return_area = |generator: &mut FunctionGenerator<'_>,
1117                           size: ArchitectureSize,
1118                           align: Alignment| {
1119            generator.imports.insert(remote_pkg("wit_runtime"));
1120            generator.need_pinner = true;
1121            let size = size.format(POINTER_SIZE_EXPRESSION);
1122            let align = align.format(POINTER_SIZE_EXPRESSION);
1123            format!(
1124                "{IMPORT_RETURN_AREA} := uintptr(wit_runtime.Allocate({PINNER}, {size}, {align}))"
1125            )
1126        };
1127
1128        let return_area = if async_ && func.result.is_some() {
1129            let abi = generator.generator.sizes.record(func.result.as_ref());
1130            return_area(&mut generator, abi.size, abi.align)
1131        } else if !(async_ || generator.return_area_size.is_empty()) {
1132            let size = generator.return_area_size;
1133            let align = generator.return_area_align;
1134            return_area(&mut generator, size, align)
1135        } else {
1136            String::new()
1137        };
1138
1139        let pinner = if generator.need_pinner {
1140            format!(
1141                "{PINNER} := &runtime.Pinner{{}}
1142defer {PINNER}.Unpin()
1143"
1144            )
1145        } else {
1146            String::new()
1147        };
1148
1149        InterfaceData::from_generator_and_code(
1150            generator,
1151            format!(
1152                "
1153//go:wasmimport {module} {prefix}{import_name}
1154func {raw_name}({params}) {results}
1155
1156func {camel}({go_params}) {go_results} {{
1157        {pinner}
1158        {return_area}
1159        {code}
1160}}
1161"
1162            ),
1163        )
1164    }
1165
1166    fn export(
1167        &mut self,
1168        resolve: &Resolve,
1169        func: &Function,
1170        interface: Option<&WorldKey>,
1171    ) -> String {
1172        self.visit_futures_and_streams(false, resolve, func, interface);
1173
1174        let async_ = self.opts.async_.is_async(resolve, interface, func, false);
1175
1176        let (variant, prefix) = if async_ {
1177            (AbiVariant::GuestExportAsync, "[async-lift]")
1178        } else {
1179            (AbiVariant::GuestExport, "")
1180        };
1181
1182        let sig = resolve.wasm_signature(variant, func);
1183        let core_module_name = interface.map(|v| resolve.name_world_key(v));
1184        let export_name = func.legacy_core_export_name(core_module_name.as_deref());
1185        let name = func_name(resolve, interface, func);
1186
1187        let params = sig
1188            .params
1189            .iter()
1190            .enumerate()
1191            .map(|(i, param)| format!("arg{i} {}", wasm_type(*param)))
1192            .collect::<Vec<_>>()
1193            .join(", ");
1194
1195        let results = match &sig.results[..] {
1196            [] => "",
1197            [result] => wasm_type(*result),
1198            _ => unreachable!(),
1199        };
1200
1201        let unpin_params =
1202            sig.indirect_params || abi::guest_export_params_have_allocations(resolve, func);
1203
1204        let param_names = (0..sig.params.len()).map(|i| format!("arg{i}")).collect();
1205        let mut generator = FunctionGenerator::new(
1206            self,
1207            Some(&name),
1208            interface,
1209            None,
1210            "INVALID",
1211            param_names,
1212            unpin_params,
1213            false,
1214        );
1215        abi::call(
1216            resolve,
1217            variant,
1218            LiftLower::LiftArgsLowerResults,
1219            func,
1220            &mut generator,
1221            async_,
1222        );
1223        let code = generator.src;
1224        let imports = generator.imports;
1225        let need_unsafe = generator.need_unsafe;
1226        self.need_math |= generator.need_math;
1227        self.need_unsafe |= need_unsafe;
1228        self.imports.extend(imports);
1229
1230        let (pinner, other, start, end) = if async_ {
1231            self.imports.insert(remote_pkg("wit_async"));
1232
1233            let module = match interface {
1234                Some(name) => resolve.name_world_key(name),
1235                None => "$root".to_string(),
1236            };
1237
1238            let function = &func.name;
1239
1240            let task_return_params = func
1241                .result
1242                .map(|ty| {
1243                    let mut storage = vec![WasmType::I32; MAX_FLAT_PARAMS];
1244                    let mut flat = FlatTypes::new(&mut storage);
1245                    if resolve.push_flat(&ty, &mut flat) {
1246                        flat.to_vec()
1247                    } else {
1248                        vec![WasmType::I32]
1249                    }
1250                })
1251                .unwrap_or_default()
1252                .into_iter()
1253                .enumerate()
1254                .map(|(i, ty)| {
1255                    let ty = wasm_type(ty);
1256                    format!("arg{i} {ty}")
1257                })
1258                .collect::<Vec<_>>()
1259                .join(", ");
1260
1261            (
1262                if abi::guest_export_needs_post_return(resolve, func) {
1263                    format!("{PINNER} := &runtime.Pinner{{}}")
1264                } else {
1265                    String::new()
1266                },
1267                format!(
1268                    "
1269
1270//go:wasmexport [callback]{prefix}{export_name}
1271func wasm_export_callback_{name}(event0 uint32, event1 uint32, event2 uint32) uint32 {{
1272        return wit_async.Callback(event0, event1, event2)
1273}}
1274
1275//go:wasmimport [export]{module} [task-return]{function}
1276func wasm_export_task_return_{name}({task_return_params})
1277"
1278                ),
1279                "return int32(wit_async.Run(func() {",
1280                "}))",
1281            )
1282        } else if abi::guest_export_needs_post_return(resolve, func) {
1283            (
1284                format!("{PINNER} := &{SYNC_EXPORT_PINNER}"),
1285                format!(
1286                    "
1287
1288//go:wasmexport cabi_post_{export_name}
1289func wasm_export_post_return_{name}(result {results}) {{
1290        syncExportPinner.Unpin()
1291}}
1292"
1293                ),
1294                "",
1295                "",
1296            )
1297        } else {
1298            (String::new(), String::new(), "", "")
1299        };
1300
1301        if self.opts.generate_stubs {
1302            let (camel, has_self) = func_declaration(resolve, func);
1303
1304            let mut imports = BTreeSet::new();
1305            let params =
1306                self.func_params(resolve, func, interface, false, &mut imports, has_self, "_");
1307            let results = self.func_results(resolve, func, interface, false, &mut imports);
1308
1309            self.export_interfaces
1310                .entry(interface_name(resolve, interface))
1311                .or_default()
1312                .extend(InterfaceData {
1313                    code: format!(
1314                        r#"
1315func {camel}({params}) {results} {{
1316        panic("not implemented")
1317}}
1318"#
1319                    ),
1320                    imports,
1321                    ..InterfaceData::default()
1322                });
1323        }
1324
1325        format!(
1326            "
1327//go:wasmexport {prefix}{export_name}
1328func wasm_export_{name}({params}) {results} {{
1329        {start}
1330        {pinner}
1331        {code}
1332        {end}
1333}}{other}
1334"
1335        )
1336    }
1337
1338    #[expect(clippy::too_many_arguments, reason = "required context for codegen")]
1339    fn func_params(
1340        &mut self,
1341        resolve: &Resolve,
1342        func: &Function,
1343        interface: Option<&WorldKey>,
1344        in_import: bool,
1345        imports: &mut BTreeSet<String>,
1346        has_self: bool,
1347        prefix: &str,
1348    ) -> String {
1349        func.params
1350            .iter()
1351            .skip(if has_self { 1 } else { 0 })
1352            .map(|Param { name, ty, .. }| {
1353                let name = name.to_lower_camel_case();
1354                let ty = self.type_name(resolve, *ty, interface, in_import, imports);
1355                format!("{prefix}{name} {ty}")
1356            })
1357            .collect::<Vec<_>>()
1358            .join(", ")
1359    }
1360
1361    fn func_results(
1362        &mut self,
1363        resolve: &Resolve,
1364        func: &Function,
1365        interface: Option<&WorldKey>,
1366        in_import: bool,
1367        imports: &mut BTreeSet<String>,
1368    ) -> String {
1369        if let Some(ty) = &func.result {
1370            if let Type::Id(id) = ty
1371                && let TypeDefKind::Tuple(tuple) = &resolve.types[*id].kind
1372            {
1373                let types = tuple
1374                    .types
1375                    .iter()
1376                    .map(|ty| self.type_name(resolve, *ty, interface, in_import, imports))
1377                    .collect::<Vec<_>>()
1378                    .join(", ");
1379                format!("({types})")
1380            } else {
1381                self.type_name(resolve, *ty, interface, in_import, imports)
1382            }
1383        } else {
1384            String::new()
1385        }
1386    }
1387
1388    fn visit_futures_and_streams(
1389        &mut self,
1390        in_import: bool,
1391        resolve: &Resolve,
1392        func: &Function,
1393        interface: Option<&WorldKey>,
1394    ) {
1395        for (index, ty) in func
1396            .find_futures_and_streams(resolve)
1397            .into_iter()
1398            .enumerate()
1399        {
1400            let payload_type = match &resolve.types[ty].kind {
1401                TypeDefKind::Future(ty) => {
1402                    self.need_future = true;
1403                    ty
1404                }
1405                TypeDefKind::Stream(ty) => {
1406                    self.need_stream = true;
1407                    ty
1408                }
1409                _ => unreachable!(),
1410            };
1411
1412            let exported = payload_type
1413                .map(|ty| self.has_exported_resource(resolve, ty))
1414                .unwrap_or(false);
1415
1416            if let hash_map::Entry::Vacant(e) = self.futures_and_streams.entry((ty, exported)) {
1417                e.insert(interface.cloned());
1418
1419                let data = self.future_or_stream(
1420                    resolve,
1421                    ty,
1422                    index,
1423                    in_import,
1424                    in_import || !exported,
1425                    interface,
1426                    &func.name,
1427                );
1428
1429                if in_import || !exported {
1430                    &mut self.interfaces
1431                } else {
1432                    &mut self.export_interfaces
1433                }
1434                .entry(interface_name(resolve, interface))
1435                .or_default()
1436                .extend(data);
1437            }
1438        }
1439    }
1440
1441    fn has_exported_resource(&self, resolve: &Resolve, ty: Type) -> bool {
1442        any(resolve, ty, &|ty| {
1443            if let Type::Id(id) = ty
1444                && let TypeDefKind::Resource = &resolve.types[id].kind
1445                && let Direction::Export = self.resources.get(&id).unwrap()
1446            {
1447                true
1448            } else {
1449                false
1450            }
1451        })
1452    }
1453}
1454
1455struct FunctionGenerator<'a> {
1456    generator: &'a mut Go,
1457    name: Option<&'a str>,
1458    interface: Option<&'a WorldKey>,
1459    interface_for_types: Option<&'a WorldKey>,
1460    function_to_call: &'a str,
1461    param_names: Vec<String>,
1462    unpin_params: bool,
1463    in_import: bool,
1464    locals: Ns,
1465    src: String,
1466    block_storage: Vec<String>,
1467    blocks: Vec<(String, Vec<String>)>,
1468    need_unsafe: bool,
1469    need_pinner: bool,
1470    need_math: bool,
1471    collect_lifters: bool,
1472    lifter_count: u32,
1473    return_area_size: ArchitectureSize,
1474    return_area_align: Alignment,
1475    imports: BTreeSet<String>,
1476}
1477
1478impl<'a> FunctionGenerator<'a> {
1479    #[expect(clippy::too_many_arguments, reason = "required context for codegen")]
1480    fn new(
1481        generator: &'a mut Go,
1482        name: Option<&'a str>,
1483        interface: Option<&'a WorldKey>,
1484        interface_for_types: Option<&'a WorldKey>,
1485        function_to_call: &'a str,
1486        param_names: Vec<String>,
1487        unpin_params: bool,
1488        in_import: bool,
1489    ) -> Self {
1490        let mut locals = Ns::default();
1491        for name in &param_names {
1492            locals.insert(name).unwrap();
1493        }
1494
1495        Self {
1496            generator,
1497            name,
1498            interface,
1499            interface_for_types,
1500            function_to_call,
1501            param_names,
1502            unpin_params,
1503            in_import,
1504            locals,
1505            src: String::new(),
1506            block_storage: Vec::new(),
1507            blocks: Vec::new(),
1508            need_unsafe: false,
1509            need_pinner: false,
1510            need_math: false,
1511            collect_lifters: false,
1512            lifter_count: 0,
1513            return_area_size: ArchitectureSize::default(),
1514            return_area_align: Alignment::default(),
1515            imports: BTreeSet::new(),
1516        }
1517    }
1518
1519    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
1520        self.generator.type_name(
1521            resolve,
1522            ty,
1523            self.interface_for_types,
1524            self.in_import,
1525            &mut self.imports,
1526        )
1527    }
1528
1529    fn package_for_owner(
1530        &mut self,
1531        resolve: &Resolve,
1532        owner: Option<&WorldKey>,
1533        ty: TypeId,
1534    ) -> String {
1535        self.generator.package_for_owner(
1536            resolve,
1537            owner,
1538            ty,
1539            self.interface_for_types,
1540            self.in_import,
1541            &mut self.imports,
1542        )
1543    }
1544}
1545
1546impl Bindgen for FunctionGenerator<'_> {
1547    type Operand = String;
1548
1549    fn sizes(&self) -> &SizeAlign {
1550        &self.generator.sizes
1551    }
1552
1553    fn push_block(&mut self) {
1554        let prev = mem::take(&mut self.src);
1555        self.block_storage.push(prev);
1556    }
1557
1558    fn finish_block(&mut self, operands: &mut Vec<String>) {
1559        let to_restore = self.block_storage.pop().unwrap();
1560        let src = mem::replace(&mut self.src, to_restore);
1561        self.blocks.push((src, mem::take(operands)));
1562    }
1563
1564    fn return_pointer(&mut self, size: ArchitectureSize, align: Alignment) -> String {
1565        if self.in_import {
1566            self.return_area_size = self.return_area_size.max(size);
1567            self.return_area_align = self.return_area_align.max(align);
1568
1569            if !self.return_area_size.is_empty() {
1570                self.need_pinner = true;
1571                self.imports.insert(remote_pkg("wit_runtime"));
1572            }
1573
1574            IMPORT_RETURN_AREA.into()
1575        } else {
1576            self.generator.return_area_size = self.generator.return_area_size.max(size);
1577            self.generator.return_area_align = self.generator.return_area_align.max(align);
1578            EXPORT_RETURN_AREA.into()
1579        }
1580    }
1581
1582    fn is_list_canonical(&self, _: &Resolve, ty: &Type) -> bool {
1583        matches!(
1584            ty,
1585            Type::U8
1586                | Type::S8
1587                | Type::U16
1588                | Type::S16
1589                | Type::U32
1590                | Type::S32
1591                | Type::U64
1592                | Type::S64
1593                | Type::F32
1594                | Type::F64
1595        )
1596    }
1597
1598    fn emit(
1599        &mut self,
1600        resolve: &Resolve,
1601        instruction: &Instruction<'_>,
1602        operands: &mut Vec<String>,
1603        results: &mut Vec<String>,
1604    ) {
1605        let store = |me: &mut Self, src, pointer, offset: &ArchitectureSize, ty| {
1606            me.need_unsafe = true;
1607            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1608            uwriteln!(
1609                me.src,
1610                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset})) = {src}"
1611            );
1612        };
1613        let load = |me: &mut Self,
1614                    results: &mut Vec<String>,
1615                    pointer,
1616                    offset: &ArchitectureSize,
1617                    ty,
1618                    cast: &dyn Fn(String) -> String| {
1619            me.need_unsafe = true;
1620            let offset = offset.format(POINTER_SIZE_EXPRESSION);
1621            results.push(cast(format!(
1622                "*(*{ty})(unsafe.Add(unsafe.Pointer({pointer}), {offset}))"
1623            )));
1624        };
1625
1626        match instruction {
1627            Instruction::GetArg { nth } => results.push(self.param_names[*nth].clone()),
1628            Instruction::StringLower { .. } => {
1629                self.need_pinner = true;
1630                self.need_unsafe = true;
1631                let string = &operands[0];
1632                let utf8 = self.locals.tmp("utf8");
1633                uwriteln!(
1634                    self.src,
1635                    "{utf8} := unsafe.Pointer(unsafe.StringData({string}))\n\
1636                     {PINNER}.Pin({utf8})"
1637                );
1638                results.push(format!("uintptr({utf8})"));
1639                results.push(format!("uint32(len({string}))"));
1640            }
1641            Instruction::StringLift { .. } => {
1642                self.need_unsafe = true;
1643                let pointer = &operands[0];
1644                let length = &operands[1];
1645                let value = self.locals.tmp("value");
1646                uwriteln!(
1647                    self.src,
1648                    "{value} := unsafe.String((*uint8)(unsafe.Pointer({pointer})), {length})"
1649                );
1650                results.push(value)
1651            }
1652            Instruction::ListCanonLower { .. } => {
1653                self.need_pinner = true;
1654                self.need_unsafe = true;
1655                let slice = &operands[0];
1656                let data = self.locals.tmp("data");
1657                uwriteln!(
1658                    self.src,
1659                    "{data} := unsafe.Pointer(unsafe.SliceData({slice}))\n\
1660                     {PINNER}.Pin({data})"
1661                );
1662                results.push(format!("uintptr({data})"));
1663                results.push(format!("uint32(len({slice}))"));
1664            }
1665            Instruction::ListCanonLift { element, .. } => {
1666                self.need_unsafe = true;
1667                let pointer = &operands[0];
1668                let length = &operands[1];
1669                let ty = self.type_name(resolve, **element);
1670                let value = self.locals.tmp("value");
1671                uwriteln!(
1672                    self.src,
1673                    "{value} := unsafe.Slice((*{ty})(unsafe.Pointer({pointer})), {length})"
1674                );
1675                results.push(value)
1676            }
1677            Instruction::ListLower { element, .. } => {
1678                self.need_unsafe = true;
1679                self.need_pinner = true;
1680                self.imports.insert(remote_pkg("wit_runtime"));
1681                let (body, _) = self.blocks.pop().unwrap();
1682                let value = &operands[0];
1683                let slice = self.locals.tmp("slice");
1684                let result = self.locals.tmp("result");
1685                let length = self.locals.tmp("length");
1686                let size = self
1687                    .generator
1688                    .sizes
1689                    .size(element)
1690                    .format(POINTER_SIZE_EXPRESSION);
1691                let align = self
1692                    .generator
1693                    .sizes
1694                    .align(element)
1695                    .format(POINTER_SIZE_EXPRESSION);
1696                uwriteln!(
1697                    self.src,
1698                    "{slice} := {value}
1699{length} := uint32(len({slice}))
1700{result} := wit_runtime.Allocate({PINNER}, uintptr({length} * {size}), {align})
1701for index, {ITER_ELEMENT} := range {slice} {{
1702        {ITER_BASE_POINTER} := unsafe.Add({result}, index * {size})
1703        {body}
1704}}
1705"
1706                );
1707                results.push(format!("uintptr({result})"));
1708                results.push(length);
1709            }
1710            Instruction::ListLift { element, .. } => {
1711                self.need_unsafe = true;
1712                let (body, body_results) = self.blocks.pop().unwrap();
1713                let value = &operands[0];
1714                let length = &operands[1];
1715                let result = self.locals.tmp("result");
1716                let size = self
1717                    .generator
1718                    .sizes
1719                    .size(element)
1720                    .format(POINTER_SIZE_EXPRESSION);
1721                let element_type = self.type_name(resolve, **element);
1722                let body_result = &body_results[0];
1723                uwriteln!(
1724                    self.src,
1725                    "{result} := make([]{element_type}, 0, {length})
1726for index := 0; index < int({length}); index++ {{
1727        {ITER_BASE_POINTER} := unsafe.Add(unsafe.Pointer({value}), index * {size})
1728        {body}
1729        {result} = append({result}, {body_result})
1730}}
1731"
1732                );
1733                results.push(result);
1734            }
1735            Instruction::CallInterface { func, .. } => {
1736                if self.unpin_params {
1737                    self.imports.insert(remote_pkg("wit_runtime"));
1738                    uwriteln!(self.src, "wit_runtime.Unpin()");
1739                }
1740
1741                let name = func.item_name().to_upper_camel_case();
1742                let package = format!("export_{}", interface_name(resolve, self.interface));
1743
1744                let call = match &func.kind {
1745                    FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
1746                        let args = operands.join(", ");
1747                        let call = format!("{package}.{name}({args})");
1748                        self.imports.insert(self.generator.mod_pkg(&package));
1749                        call
1750                    }
1751                    FunctionKind::Constructor(ty) => {
1752                        let args = operands.join(", ");
1753                        let ty = resolve.types[*ty]
1754                            .name
1755                            .as_ref()
1756                            .unwrap()
1757                            .to_upper_camel_case();
1758                        let call = format!("{package}.Make{ty}({args})");
1759                        self.imports.insert(self.generator.mod_pkg(&package));
1760                        call
1761                    }
1762                    FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
1763                        let target = &operands[0];
1764                        let args = operands[1..].join(", ");
1765                        format!("({target}).{name}({args})")
1766                    }
1767                    FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
1768                        let args = operands.join(", ");
1769                        let ty = self.type_name(resolve, Type::Id(*ty));
1770                        format!("{ty}{name}({args})")
1771                    }
1772                };
1773
1774                if let Some(ty) = func.result {
1775                    let result = self.locals.tmp("result");
1776                    if let Type::Id(ty) = ty
1777                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1778                    {
1779                        let count = tuple.types.len();
1780                        self.generator.tuples.insert(count);
1781                        self.imports.insert(remote_pkg("wit_types"));
1782
1783                        let results = (0..count)
1784                            .map(|_| self.locals.tmp("result"))
1785                            .collect::<Vec<_>>()
1786                            .join(", ");
1787
1788                        let types = tuple
1789                            .types
1790                            .iter()
1791                            .map(|&ty| self.type_name(resolve, ty))
1792                            .collect::<Vec<_>>()
1793                            .join(", ");
1794
1795                        uwriteln!(
1796                            self.src,
1797                            "{results} := {call}
1798{result} := wit_types.Tuple{count}[{types}]{{{results}}}"
1799                        );
1800                    } else {
1801                        uwriteln!(self.src, "{result} := {call}");
1802                    }
1803                    results.push(result);
1804                } else {
1805                    uwriteln!(self.src, "{call}");
1806                }
1807            }
1808            Instruction::Return { func, .. } => {
1809                if let Some(ty) = func.result {
1810                    let result = &operands[0];
1811                    if self.in_import
1812                        && let Type::Id(ty) = ty
1813                        && let TypeDefKind::Tuple(tuple) = &resolve.types[ty].kind
1814                    {
1815                        let count = tuple.types.len();
1816                        let tuple = self.locals.tmp("tuple");
1817
1818                        let results = (0..count)
1819                            .map(|index| format!("{tuple}.F{index}"))
1820                            .collect::<Vec<_>>()
1821                            .join(", ");
1822
1823                        uwriteln!(
1824                            self.src,
1825                            "{tuple} := {result}
1826return {results}"
1827                        );
1828                    } else {
1829                        uwriteln!(self.src, "return {result}");
1830                    }
1831                }
1832            }
1833            Instruction::AsyncTaskReturn { .. } => {
1834                let name = self.name.unwrap();
1835                let args = operands.join(", ");
1836                uwriteln!(self.src, "wasm_export_task_return_{name}({args})");
1837            }
1838            Instruction::LengthStore { offset } => store(
1839                self,
1840                &format!("uint32({})", operands[0]),
1841                &operands[1],
1842                offset,
1843                "uint32",
1844            ),
1845            Instruction::PointerStore { offset } => store(
1846                self,
1847                &format!("uint32(uintptr({}))", operands[0]),
1848                &operands[1],
1849                offset,
1850                "uint32",
1851            ),
1852            Instruction::I32Store8 { offset } => store(
1853                self,
1854                &format!("int8({})", operands[0]),
1855                &operands[1],
1856                offset,
1857                "int8",
1858            ),
1859            Instruction::I32Store16 { offset } => store(
1860                self,
1861                &format!("int16({})", operands[0]),
1862                &operands[1],
1863                offset,
1864                "int16",
1865            ),
1866            Instruction::I32Store { offset } => {
1867                store(self, &operands[0], &operands[1], offset, "int32")
1868            }
1869            Instruction::I64Store { offset } => {
1870                store(self, &operands[0], &operands[1], offset, "int64")
1871            }
1872            Instruction::F32Store { offset } => {
1873                store(self, &operands[0], &operands[1], offset, "float32")
1874            }
1875            Instruction::F64Store { offset } => {
1876                store(self, &operands[0], &operands[1], offset, "float64")
1877            }
1878            Instruction::LengthLoad { offset } => {
1879                load(self, results, &operands[0], offset, "uint32", &|v| v)
1880            }
1881            Instruction::PointerLoad { offset } => {
1882                load(self, results, &operands[0], offset, "uint32", &|v| {
1883                    format!("uintptr({v})")
1884                })
1885            }
1886            Instruction::I32Load8U { offset } => {
1887                load(self, results, &operands[0], offset, "uint32", &|v| {
1888                    format!("uint8({v})")
1889                })
1890            }
1891            Instruction::I32Load8S { offset } => {
1892                load(self, results, &operands[0], offset, "uint32", &|v| {
1893                    format!("int8({v})")
1894                })
1895            }
1896            Instruction::I32Load16U { offset } => {
1897                load(self, results, &operands[0], offset, "uint32", &|v| {
1898                    format!("uint16({v})")
1899                })
1900            }
1901            Instruction::I32Load16S { offset } => {
1902                load(self, results, &operands[0], offset, "uint32", &|v| {
1903                    format!("int16({v})")
1904                })
1905            }
1906            Instruction::I32Load { offset } => {
1907                load(self, results, &operands[0], offset, "int32", &|v| v)
1908            }
1909            Instruction::I64Load { offset } => {
1910                load(self, results, &operands[0], offset, "int64", &|v| v)
1911            }
1912            Instruction::F32Load { offset } => {
1913                load(self, results, &operands[0], offset, "float32", &|v| v)
1914            }
1915            Instruction::F64Load { offset } => {
1916                load(self, results, &operands[0], offset, "float64", &|v| v)
1917            }
1918            Instruction::BoolFromI32 => results.push(format!("({} != 0)", operands[0])),
1919            Instruction::U8FromI32 => results.push(format!("uint8({})", operands[0])),
1920            Instruction::S8FromI32 => results.push(format!("int8({})", operands[0])),
1921            Instruction::U16FromI32 => results.push(format!("uint16({})", operands[0])),
1922            Instruction::S16FromI32 => results.push(format!("int16({})", operands[0])),
1923            Instruction::U32FromI32 => results.push(format!("uint32({})", operands[0])),
1924            Instruction::S32FromI32 | Instruction::S64FromI64 => {
1925                results.push(operands.pop().unwrap())
1926            }
1927            Instruction::U64FromI64 => results.push(format!("uint64({})", operands[0])),
1928            Instruction::I32FromBool => {
1929                let value = &operands[0];
1930                let result = self.locals.tmp("result");
1931                uwriteln!(
1932                    self.src,
1933                    "var {result} int32
1934if {value} {{
1935        {result} = 1
1936}} else {{
1937        {result} = 0
1938}}"
1939                );
1940                results.push(result);
1941            }
1942            Instruction::I32FromU8
1943            | Instruction::I32FromS8
1944            | Instruction::I32FromU16
1945            | Instruction::I32FromS16
1946            | Instruction::I32FromU32 => {
1947                results.push(format!("int32({})", operands[0]));
1948            }
1949            Instruction::I32FromS32 | Instruction::I64FromS64 => {
1950                results.push(operands.pop().unwrap())
1951            }
1952            Instruction::I64FromU64 => results.push(format!("int64({})", operands[0])),
1953            Instruction::CoreF32FromF32
1954            | Instruction::CoreF64FromF64
1955            | Instruction::F32FromCoreF32
1956            | Instruction::F64FromCoreF64 => results.push(operands.pop().unwrap()),
1957            Instruction::CharFromI32 => results.push(format!("rune({})", operands[0])),
1958            Instruction::I32FromChar => results.push(format!("int32({})", operands[0])),
1959            Instruction::TupleLower { tuple, .. } => {
1960                let op = &operands[0];
1961                for index in 0..tuple.types.len() {
1962                    results.push(format!("({op}).F{index}"));
1963                }
1964            }
1965            Instruction::TupleLift { tuple, .. } => {
1966                let count = tuple.types.len();
1967                self.generator.tuples.insert(count);
1968                let types = tuple
1969                    .types
1970                    .iter()
1971                    .map(|&ty| self.type_name(resolve, ty))
1972                    .collect::<Vec<_>>()
1973                    .join(", ");
1974                let fields = operands.join(", ");
1975                self.imports.insert(remote_pkg("wit_types"));
1976                results.push(format!("wit_types.Tuple{count}[{types}]{{{fields}}}"));
1977            }
1978            Instruction::FlagsLower { .. } => {
1979                let value = operands.pop().unwrap();
1980                results.push(format!("int32({value})"))
1981            }
1982            Instruction::FlagsLift { flags, .. } => {
1983                let value = operands.pop().unwrap();
1984                let repr = flags_repr(flags);
1985                results.push(format!("{repr}({value})"))
1986            }
1987            Instruction::RecordLower { record, .. } => {
1988                let op = &operands[0];
1989                for field in &record.fields {
1990                    let field = field.name.to_upper_camel_case();
1991                    results.push(format!("({op}).{field}"));
1992                }
1993            }
1994            Instruction::RecordLift { ty, .. } => {
1995                let name = self.type_name(resolve, Type::Id(*ty));
1996                let fields = operands.join(", ");
1997                results.push(format!("{name}{{{fields}}}"));
1998            }
1999            Instruction::OptionLower {
2000                results: result_types,
2001                ..
2002            } => {
2003                self.generator.need_option = true;
2004                self.imports.insert(remote_pkg("wit_types"));
2005                let (some, some_results) = self.blocks.pop().unwrap();
2006                let (none, none_results) = self.blocks.pop().unwrap();
2007                let value = &operands[0];
2008
2009                let result_names = (0..result_types.len())
2010                    .map(|_| self.locals.tmp("option"))
2011                    .collect::<Vec<_>>();
2012
2013                let declarations = result_types
2014                    .iter()
2015                    .zip(&result_names)
2016                    .map(|(ty, name)| {
2017                        let ty = wasm_type(*ty);
2018                        format!("var {name} {ty}")
2019                    })
2020                    .collect::<Vec<_>>()
2021                    .join("\n");
2022
2023                let some_result_assignments = some_results
2024                    .iter()
2025                    .zip(&result_names)
2026                    .map(|(result, name)| format!("{name} = {result}"))
2027                    .collect::<Vec<_>>()
2028                    .join("\n");
2029
2030                let none_result_assignments = none_results
2031                    .iter()
2032                    .zip(&result_names)
2033                    .map(|(result, name)| format!("{name} = {result}"))
2034                    .collect::<Vec<_>>()
2035                    .join("\n");
2036
2037                results.extend(result_names);
2038
2039                uwriteln!(
2040                    self.src,
2041                    r#"{declarations}
2042switch {value}.Tag() {{
2043case wit_types.OptionNone:
2044        {none}
2045        {none_result_assignments}
2046case wit_types.OptionSome:
2047        {VARIANT_PAYLOAD_NAME} := {value}.Some()
2048        {some}
2049        {some_result_assignments}
2050default:
2051        panic("unreachable")
2052}}"#
2053                );
2054            }
2055            Instruction::OptionLift { ty, payload } => {
2056                self.generator.need_option = true;
2057                self.imports.insert(remote_pkg("wit_types"));
2058                let (some, some_results) = self.blocks.pop().unwrap();
2059                let (none, none_results) = self.blocks.pop().unwrap();
2060                assert!(none_results.is_empty());
2061                assert!(some_results.len() == 1);
2062                let some_result = &some_results[0];
2063                let ty = self.type_name(resolve, Type::Id(*ty));
2064                let some_type = self.type_name(resolve, **payload);
2065                let result = self.locals.tmp("option");
2066                let tag = &operands[0];
2067                uwriteln!(
2068                    self.src,
2069                    r#"var {result} {ty}
2070switch {tag} {{
2071case 0:
2072        {none}
2073        {result} = wit_types.None[{some_type}]()
2074case 1:
2075        {some}
2076        {result} = wit_types.Some[{some_type}]({some_result})
2077default:
2078        panic("unreachable")
2079}}"#
2080                );
2081                results.push(result);
2082            }
2083            Instruction::ResultLower {
2084                result,
2085                results: result_types,
2086                ..
2087            } => {
2088                self.generator.need_result = true;
2089                self.imports.insert(remote_pkg("wit_types"));
2090                let (err, err_results) = self.blocks.pop().unwrap();
2091                let (ok, ok_results) = self.blocks.pop().unwrap();
2092                let value = &operands[0];
2093
2094                let result_names = (0..result_types.len())
2095                    .map(|_| self.locals.tmp("option"))
2096                    .collect::<Vec<_>>();
2097
2098                let declarations = result_types
2099                    .iter()
2100                    .zip(&result_names)
2101                    .map(|(ty, name)| {
2102                        let ty = wasm_type(*ty);
2103                        format!("var {name} {ty}")
2104                    })
2105                    .collect::<Vec<_>>()
2106                    .join("\n");
2107
2108                let ok_result_assignments = ok_results
2109                    .iter()
2110                    .zip(&result_names)
2111                    .map(|(result, name)| format!("{name} = {result}"))
2112                    .collect::<Vec<_>>()
2113                    .join("\n");
2114
2115                let err_result_assignments = err_results
2116                    .iter()
2117                    .zip(&result_names)
2118                    .map(|(result, name)| format!("{name} = {result}"))
2119                    .collect::<Vec<_>>()
2120                    .join("\n");
2121
2122                results.extend(result_names);
2123
2124                let ok_set_payload = if result.ok.is_some() {
2125                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Ok()")
2126                } else {
2127                    self.generator.need_unit = true;
2128                    String::new()
2129                };
2130
2131                let err_set_payload = if result.err.is_some() {
2132                    format!("{VARIANT_PAYLOAD_NAME} := {value}.Err()")
2133                } else {
2134                    self.generator.need_unit = true;
2135                    String::new()
2136                };
2137
2138                uwriteln!(
2139                    self.src,
2140                    r#"{declarations}
2141switch {value}.Tag() {{
2142case wit_types.ResultOk:
2143        {ok_set_payload}
2144        {ok}
2145        {ok_result_assignments}
2146case wit_types.ResultErr:
2147        {err_set_payload}
2148        {err}
2149        {err_result_assignments}
2150default:
2151        panic("unreachable")
2152}}"#
2153                );
2154            }
2155            Instruction::ResultLift { ty, result, .. } => {
2156                self.generator.need_result = true;
2157                self.imports.insert(remote_pkg("wit_types"));
2158                let (err, err_results) = self.blocks.pop().unwrap();
2159                let (ok, ok_results) = self.blocks.pop().unwrap();
2160                assert_eq!(ok_results.is_empty(), result.ok.is_none());
2161                assert_eq!(err_results.is_empty(), result.err.is_none());
2162                let ok_result = if result.ok.is_some() {
2163                    &ok_results[0]
2164                } else {
2165                    self.generator.need_unit = true;
2166                    "wit_types.Unit{}"
2167                };
2168                let err_result = if result.err.is_some() {
2169                    &err_results[0]
2170                } else {
2171                    self.generator.need_unit = true;
2172                    "wit_types.Unit{}"
2173                };
2174                let ty = self.type_name(resolve, Type::Id(*ty));
2175                let ok_type = result
2176                    .ok
2177                    .map(|ty| self.type_name(resolve, ty))
2178                    .unwrap_or_else(|| {
2179                        self.generator.need_unit = true;
2180                        "wit_types.Unit".into()
2181                    });
2182                let err_type = result
2183                    .err
2184                    .map(|ty| self.type_name(resolve, ty))
2185                    .unwrap_or_else(|| {
2186                        self.generator.need_unit = true;
2187                        "wit_types.Unit".into()
2188                    });
2189                let result = self.locals.tmp("result");
2190                let tag = &operands[0];
2191                uwriteln!(
2192                    self.src,
2193                    r#"var {result} {ty}
2194switch {tag} {{
2195case 0:
2196        {ok}
2197        {result} = wit_types.Ok[{ok_type}, {err_type}]({ok_result})
2198case 1:
2199        {err}
2200        {result} = wit_types.Err[{ok_type}, {err_type}]({err_result})
2201default:
2202        panic("unreachable")
2203}}"#
2204                );
2205                results.push(result);
2206            }
2207            Instruction::EnumLower { .. } => results.push(format!("int32({})", operands[0])),
2208            Instruction::EnumLift { enum_, .. } => {
2209                results.push(format!("{}({})", int_repr(enum_.tag()), operands[0]))
2210            }
2211            Instruction::VariantLower {
2212                ty,
2213                variant,
2214                results: result_types,
2215                ..
2216            } => {
2217                let blocks = self
2218                    .blocks
2219                    .drain(self.blocks.len() - variant.cases.len()..)
2220                    .collect::<Vec<_>>();
2221
2222                let ty = self.type_name(resolve, Type::Id(*ty));
2223                let value = &operands[0];
2224
2225                let result_names = (0..result_types.len())
2226                    .map(|_| self.locals.tmp("variant"))
2227                    .collect::<Vec<_>>();
2228
2229                let declarations = result_types
2230                    .iter()
2231                    .zip(&result_names)
2232                    .map(|(ty, name)| {
2233                        let ty = wasm_type(*ty);
2234                        format!("var {name} {ty}")
2235                    })
2236                    .collect::<Vec<_>>()
2237                    .join("\n");
2238
2239                let cases = variant
2240                    .cases
2241                    .iter()
2242                    .zip(blocks)
2243                    .map(|(case, (block, block_results))| {
2244                        let assignments = result_names
2245                            .iter()
2246                            .zip(&block_results)
2247                            .map(|(name, result)| format!("{name} = {result}"))
2248                            .collect::<Vec<_>>()
2249                            .join("\n");
2250
2251                        let name = case.name.to_upper_camel_case();
2252
2253                        let set_payload = if case.ty.is_some() {
2254                            format!("{VARIANT_PAYLOAD_NAME} := {value}.{name}()")
2255                        } else {
2256                            String::new()
2257                        };
2258
2259                        format!(
2260                            "case {ty}{name}:
2261        {set_payload}
2262        {block}
2263        {assignments}
2264"
2265                        )
2266                    })
2267                    .collect::<Vec<_>>()
2268                    .join("\n");
2269
2270                results.extend(result_names);
2271
2272                uwriteln!(
2273                    self.src,
2274                    r#"{declarations}
2275switch {value}.Tag() {{
2276{cases}
2277default:
2278        panic("unreachable")
2279}}"#
2280                );
2281            }
2282            Instruction::VariantLift { ty, variant, .. } => {
2283                let blocks = self
2284                    .blocks
2285                    .drain(self.blocks.len() - variant.cases.len()..)
2286                    .collect::<Vec<_>>();
2287
2288                let ty = self.type_name(resolve, Type::Id(*ty));
2289                let result = self.locals.tmp("variant");
2290                let tag = &operands[0];
2291
2292                let (package, name) = if let Some(index) = ty.find('.') {
2293                    (&ty[..index + 1], &ty[index + 1..])
2294                } else {
2295                    ("", ty.as_str())
2296                };
2297
2298                let cases = variant
2299                    .cases
2300                    .iter()
2301                    .zip(blocks)
2302                    .enumerate()
2303                    .map(|(index, (case, (block, block_results)))| {
2304                        assert_eq!(block_results.is_empty(), case.ty.is_none());
2305                        let payload = if case.ty.is_some() {
2306                            &block_results[0]
2307                        } else {
2308                            ""
2309                        };
2310                        let case = case.name.to_upper_camel_case();
2311                        format!(
2312                            "case {index}:
2313        {block}
2314        {result} = {package}Make{name}{case}({payload})
2315"
2316                        )
2317                    })
2318                    .collect::<Vec<_>>()
2319                    .join("\n");
2320
2321                uwriteln!(
2322                    self.src,
2323                    r#"var {result} {ty}
2324switch {tag} {{
2325{cases}
2326default:
2327        panic("unreachable")
2328}}"#
2329                );
2330                results.push(result);
2331            }
2332            Instruction::VariantPayloadName => results.push(VARIANT_PAYLOAD_NAME.into()),
2333            Instruction::IterElem { .. } => results.push(ITER_ELEMENT.into()),
2334            Instruction::IterBasePointer => results.push(ITER_BASE_POINTER.into()),
2335            Instruction::I32Const { val } => results.push(format!("int32({val})")),
2336            Instruction::ConstZero { tys } => {
2337                results.extend(iter::repeat_with(|| "0".into()).take(tys.len()));
2338            }
2339            Instruction::Bitcasts { casts } => {
2340                results.extend(
2341                    casts
2342                        .iter()
2343                        .zip(operands)
2344                        .map(|(which, op)| cast(op, which, &mut self.need_math)),
2345                );
2346            }
2347            Instruction::FutureLower { .. }
2348            | Instruction::StreamLower { .. }
2349            | Instruction::HandleLower {
2350                handle: Handle::Own(_),
2351                ..
2352            } => {
2353                let op = &operands[0];
2354                if self.collect_lifters {
2355                    self.lifter_count += 1;
2356                    let resource = self.locals.tmp("resource");
2357                    let handle = self.locals.tmp("handle");
2358                    uwriteln!(
2359                        self.src,
2360                        "{resource} := {op}
2361{handle} := {resource}.TakeHandle()
2362lifters = append(lifters, func() {{
2363        {resource}.SetHandle({handle})
2364}})"
2365                    );
2366                    results.push(handle)
2367                } else {
2368                    results.push(format!("({op}).TakeHandle()"))
2369                }
2370            }
2371            Instruction::HandleLower {
2372                handle: Handle::Borrow(_),
2373                ..
2374            } => results.push(format!("({}).Handle()", operands[0])),
2375            Instruction::HandleLift { handle, .. } => {
2376                let (which, resource) = match handle {
2377                    Handle::Borrow(resource) => ("Borrow", resource),
2378                    Handle::Own(resource) => ("Own", resource),
2379                };
2380                let handle = &operands[0];
2381                let ty = self.type_name(resolve, Type::Id(*resource));
2382                results.push(format!("{ty}From{which}Handle(int32(uintptr({handle})))"))
2383            }
2384            Instruction::CallWasm { sig, .. } => {
2385                let assignment = match &sig.results[..] {
2386                    [] => String::new(),
2387                    [_] => {
2388                        let result = self.locals.tmp("result");
2389                        let assignment = format!("{result} := ");
2390                        results.push(result);
2391                        assignment
2392                    }
2393                    _ => unreachable!(),
2394                };
2395                let name = &self.function_to_call;
2396                let params = operands.join(", ");
2397                uwriteln!(self.src, "{assignment}{name}({params})")
2398            }
2399            Instruction::Flush { amt } => {
2400                for op in operands.iter().take(*amt) {
2401                    let result = self.locals.tmp("result");
2402                    uwriteln!(self.src, "{result} := {op};");
2403                    results.push(result);
2404                }
2405            }
2406            Instruction::FutureLift { ty, .. } => {
2407                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2408                let owner = self
2409                    .generator
2410                    .futures_and_streams
2411                    .get(&(*ty, exported))
2412                    .unwrap()
2413                    .clone();
2414                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2415                let TypeDefKind::Future(payload_ty) = &resolve.types[*ty].kind else {
2416                    unreachable!()
2417                };
2418                let camel = if let Some(ty) = payload_ty {
2419                    self.generator
2420                        .mangle_name(resolve, *ty, owner.as_ref())
2421                        .to_upper_camel_case()
2422                } else {
2423                    "Unit".into()
2424                };
2425                let handle = &operands[0];
2426                results.push(format!("{package}LiftFuture{camel}({handle})"));
2427            }
2428            Instruction::StreamLift { ty, .. } => {
2429                let exported = self.generator.has_exported_resource(resolve, Type::Id(*ty));
2430                let owner = self
2431                    .generator
2432                    .futures_and_streams
2433                    .get(&(*ty, exported))
2434                    .unwrap()
2435                    .clone();
2436                let package = self.package_for_owner(resolve, owner.as_ref(), *ty);
2437                let TypeDefKind::Stream(payload_ty) = &resolve.types[*ty].kind else {
2438                    unreachable!()
2439                };
2440                let camel = if let Some(ty) = payload_ty {
2441                    self.generator
2442                        .mangle_name(resolve, *ty, owner.as_ref())
2443                        .to_upper_camel_case()
2444                } else {
2445                    "Unit".into()
2446                };
2447                let handle = &operands[0];
2448                results.push(format!("{package}LiftStream{camel}({handle})"));
2449            }
2450            Instruction::GuestDeallocate { .. } => {
2451                // Nothing to do here; should be handled when calling `pinner.Unpin()`
2452            }
2453            _ => unimplemented!("{instruction:?}"),
2454        }
2455    }
2456}
2457
2458struct InterfaceGenerator<'a> {
2459    generator: &'a mut Go,
2460    resolve: &'a Resolve,
2461    interface: Option<(InterfaceId, &'a WorldKey)>,
2462    in_import: bool,
2463    src: String,
2464    imports: BTreeSet<String>,
2465    need_unsafe: bool,
2466    need_runtime: bool,
2467}
2468
2469impl<'a> InterfaceGenerator<'a> {
2470    fn new(
2471        generator: &'a mut Go,
2472        resolve: &'a Resolve,
2473        interface: Option<(InterfaceId, &'a WorldKey)>,
2474        in_import: bool,
2475    ) -> Self {
2476        Self {
2477            generator,
2478            resolve,
2479            interface,
2480            in_import,
2481            src: String::new(),
2482            imports: BTreeSet::new(),
2483            need_unsafe: false,
2484            need_runtime: false,
2485        }
2486    }
2487
2488    fn type_name(&mut self, resolve: &Resolve, ty: Type) -> String {
2489        self.generator.type_name(
2490            resolve,
2491            ty,
2492            self.interface.map(|(_, key)| key),
2493            self.in_import || !self.generator.has_exported_resource(resolve, ty),
2494            &mut self.imports,
2495        )
2496    }
2497}
2498
2499impl<'a> wit_bindgen_core::InterfaceGenerator<'a> for InterfaceGenerator<'a> {
2500    fn resolve(&self) -> &'a Resolve {
2501        self.resolve
2502    }
2503
2504    fn type_record(&mut self, _: TypeId, name: &str, record: &Record, docs: &Docs) {
2505        let name = name.to_upper_camel_case();
2506
2507        let fields = record
2508            .fields
2509            .iter()
2510            .map(|field| {
2511                let ty = self.type_name(self.resolve, field.ty);
2512                let docs = format_docs(&field.docs);
2513                let field = field.name.to_upper_camel_case();
2514                format!("{docs}{field} {ty}")
2515            })
2516            .collect::<Vec<_>>()
2517            .join("\n");
2518
2519        let docs = format_docs(docs);
2520
2521        uwriteln!(
2522            self.src,
2523            "
2524{docs}type {name} struct {{
2525        {fields}
2526}}"
2527        )
2528    }
2529
2530    fn type_resource(&mut self, id: TypeId, name: &str, docs: &Docs) {
2531        self.generator.resources.insert(
2532            id,
2533            if self.in_import {
2534                Direction::Import
2535            } else {
2536                Direction::Export
2537            },
2538        );
2539
2540        let camel = name.to_upper_camel_case();
2541        let module = self
2542            .interface
2543            .map(|(_, key)| self.resolve.name_world_key(key))
2544            .unwrap_or_else(|| "$root".into());
2545
2546        if self.in_import {
2547            self.imports.insert(remote_pkg("wit_runtime"));
2548            self.need_runtime = true;
2549            let docs = format_docs(docs);
2550            uwriteln!(
2551                self.src,
2552                r#"
2553//go:wasmimport {module} [resource-drop]{name}
2554func resourceDrop{camel}(handle int32)
2555
2556{docs}type {camel} struct {{
2557        handle *wit_runtime.Handle
2558}}
2559
2560func (self *{camel}) TakeHandle() int32 {{
2561        return self.handle.Take()
2562}}
2563
2564func (self *{camel}) SetHandle(handle int32) {{
2565        self.handle.Set(handle)
2566}}
2567
2568func (self *{camel}) Handle() int32 {{
2569        return self.handle.Use()
2570}}
2571
2572func (self *{camel}) Drop() {{
2573	handle := self.handle.TakeOrNil()
2574	if handle != 0 {{
2575		resourceDrop{camel}(handle)
2576	}}
2577}}
2578
2579func {camel}FromOwnHandle(handleValue int32) *{camel} {{
2580        handle := wit_runtime.MakeHandle(handleValue)
2581        value := &{camel}{{handle}}
2582        runtime.AddCleanup(value, func(_ int) {{
2583                handleValue := handle.TakeOrNil()
2584                if handleValue != 0 {{
2585                        resourceDrop{camel}(handleValue)
2586                }}
2587        }}, 0)
2588        return value
2589}}
2590
2591func {camel}FromBorrowHandle(handleValue int32) *{camel} {{
2592	handle := wit_runtime.MakeHandle(handleValue)
2593	return &{camel}{{handle}}
2594}}
2595"#
2596            );
2597        } else {
2598            self.need_unsafe = true;
2599            uwriteln!(
2600                self.src,
2601                r#"
2602//go:wasmimport [export]{module} [resource-new]{name}
2603func resourceNew{camel}(pointer unsafe.Pointer) int32
2604
2605//go:wasmimport [export]{module} [resource-rep]{name}
2606func resourceRep{camel}(handle int32) unsafe.Pointer
2607
2608//go:wasmimport [export]{module} [resource-drop]{name}
2609func resourceDrop{camel}(handle int32)
2610
2611//go:wasmexport {module}#[dtor]{name}
2612func resourceDtor{camel}(rep int32) {{
2613        val := (*{camel})(unsafe.Pointer(uintptr(rep)))
2614        val.handle = 0
2615        val.pinner.Unpin()
2616        val.OnDrop()
2617}}
2618
2619func (self *{camel}) TakeHandle() int32 {{
2620	self.pinner.Pin(self)
2621	self.handle = resourceNew{camel}(unsafe.Pointer(self))
2622	return self.handle
2623}}
2624
2625func (self *{camel}) SetHandle(handle int32) {{
2626        if self.handle != handle {{
2627                panic("invalid handle")
2628        }}
2629}}
2630
2631func (self *{camel}) Drop() {{
2632	handle := self.handle
2633	if self.handle != 0 {{
2634		self.handle = 0
2635		resourceDrop{camel}(handle)
2636		self.pinner.Unpin()
2637                self.OnDrop()
2638	}}
2639}}
2640
2641func {camel}FromOwnHandle(handle int32) *{camel} {{
2642	return (*{camel})(unsafe.Pointer(resourceRep{camel}(handle)))
2643}}
2644
2645func {camel}FromBorrowHandle(rep int32) *{camel} {{
2646	return (*{camel})(unsafe.Pointer(uintptr(rep)))
2647}}
2648"#
2649            );
2650
2651            if self.generator.opts.generate_stubs {
2652                self.need_runtime = true;
2653                uwriteln!(
2654                    self.src,
2655                    r#"
2656type {camel} struct {{
2657        pinner runtime.Pinner
2658        handle int32
2659}}
2660
2661func (self *{camel}) OnDrop() {{}}
2662"#
2663                );
2664            }
2665        }
2666    }
2667
2668    fn type_flags(&mut self, _: TypeId, name: &str, flags: &Flags, docs: &Docs) {
2669        let repr = flags_repr(flags);
2670
2671        let name = name.to_upper_camel_case();
2672
2673        let constants = flags
2674            .flags
2675            .iter()
2676            .enumerate()
2677            .map(|(i, flag)| {
2678                let docs = format_docs(&flag.docs);
2679                let flag = flag.name.to_upper_camel_case();
2680                format!("{docs}{name}{flag} {repr} = 1 << {i}")
2681            })
2682            .collect::<Vec<_>>()
2683            .join("\n");
2684
2685        let docs = format_docs(docs);
2686
2687        uwriteln!(
2688            self.src,
2689            "
2690const (
2691{constants}
2692)
2693
2694{docs}type {name} = {repr}"
2695        )
2696    }
2697
2698    fn type_tuple(&mut self, _: TypeId, name: &str, tuple: &Tuple, docs: &Docs) {
2699        self.imports.insert(remote_pkg("wit_types"));
2700        let count = tuple.types.len();
2701        self.generator.tuples.insert(count);
2702        let name = name.to_upper_camel_case();
2703        let docs = format_docs(docs);
2704        let types = tuple
2705            .types
2706            .iter()
2707            .map(|ty| self.type_name(self.resolve, *ty))
2708            .collect::<Vec<_>>()
2709            .join(", ");
2710
2711        uwriteln!(
2712            self.src,
2713            "{docs}type {name} = wit_types.Tuple{count}[{types}]"
2714        );
2715    }
2716
2717    fn type_variant(&mut self, _: TypeId, name: &str, variant: &Variant, docs: &Docs) {
2718        let repr = int_repr(variant.tag());
2719
2720        let name = name.to_upper_camel_case();
2721
2722        let constants = variant
2723            .cases
2724            .iter()
2725            .enumerate()
2726            .map(|(i, case)| {
2727                let docs = format_docs(&case.docs);
2728                let case = case.name.to_upper_camel_case();
2729                format!("{docs}{name}{case} {repr} = {i}")
2730            })
2731            .collect::<Vec<_>>()
2732            .join("\n");
2733
2734        let getters = variant
2735            .cases
2736            .iter()
2737            .filter_map(|case| {
2738                case.ty.map(|ty| {
2739                    let case = case.name.to_upper_camel_case();
2740                    let ty = self.type_name(self.resolve, ty);
2741                    format!(
2742                        r#"func (self {name}) {case}() {ty} {{
2743        if self.tag != {name}{case} {{
2744                panic("tag mismatch")
2745        }}
2746        return self.value.({ty})
2747}}
2748"#
2749                    )
2750                })
2751            })
2752            .collect::<Vec<_>>()
2753            .concat();
2754
2755        let constructors = variant
2756            .cases
2757            .iter()
2758            .map(|case| {
2759                let (param, value) = if let Some(ty) = case.ty {
2760                    let ty = self.type_name(self.resolve, ty);
2761                    (format!("value {ty}"), "value")
2762                } else {
2763                    (String::new(), "nil")
2764                };
2765                let case = case.name.to_upper_camel_case();
2766                format!(
2767                    r#"func Make{name}{case}({param}) {name} {{
2768        return {name}{{{name}{case}, {value}}}
2769}}
2770"#
2771                )
2772            })
2773            .collect::<Vec<_>>()
2774            .concat();
2775
2776        let docs = format_docs(docs);
2777
2778        uwriteln!(
2779            self.src,
2780            "
2781const (
2782{constants}
2783)
2784
2785{docs}type {name} struct {{
2786        tag {repr}
2787        value any
2788}}
2789
2790func (self {name}) Tag() {repr} {{
2791        return self.tag
2792}}
2793
2794{getters}
2795{constructors}
2796"
2797        )
2798    }
2799
2800    fn type_option(&mut self, _: TypeId, name: &str, payload: &Type, docs: &Docs) {
2801        self.generator.need_option = true;
2802        self.imports.insert(remote_pkg("wit_types"));
2803        let name = name.to_upper_camel_case();
2804        let ty = self.type_name(self.resolve, *payload);
2805        let docs = format_docs(docs);
2806        uwriteln!(self.src, "{docs}type {name} = wit_types.Option[{ty}]");
2807    }
2808
2809    fn type_result(&mut self, _: TypeId, name: &str, result: &Result_, docs: &Docs) {
2810        self.generator.need_result = true;
2811        self.imports.insert(remote_pkg("wit_types"));
2812        let name = name.to_upper_camel_case();
2813        let ok_type = result
2814            .ok
2815            .map(|ty| self.type_name(self.resolve, ty))
2816            .unwrap_or_else(|| {
2817                self.generator.need_unit = true;
2818                "wit_types.Unit".into()
2819            });
2820        let err_type = result
2821            .err
2822            .map(|ty| self.type_name(self.resolve, ty))
2823            .unwrap_or_else(|| {
2824                self.generator.need_unit = true;
2825                "wit_types.Unit".into()
2826            });
2827        let docs = format_docs(docs);
2828        uwriteln!(
2829            self.src,
2830            "{docs}type {name} = wit_types.Result[{ok_type}, {err_type}]"
2831        );
2832    }
2833
2834    fn type_enum(&mut self, _: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
2835        let repr = int_repr(enum_.tag());
2836
2837        let name = name.to_upper_camel_case();
2838
2839        let constants = enum_
2840            .cases
2841            .iter()
2842            .enumerate()
2843            .map(|(i, case)| {
2844                let docs = format_docs(&case.docs);
2845                let case = case.name.to_upper_camel_case();
2846                format!("{docs}{name}{case} {repr} = {i}")
2847            })
2848            .collect::<Vec<_>>()
2849            .join("\n");
2850
2851        let docs = format_docs(docs);
2852
2853        uwriteln!(
2854            self.src,
2855            "
2856const (
2857        {constants}
2858)
2859{docs}type {name} = {repr}"
2860        )
2861    }
2862
2863    fn type_alias(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2864        let name = name.to_upper_camel_case();
2865        let ty = self.type_name(self.resolve, *ty);
2866        let docs = format_docs(docs);
2867        uwriteln!(self.src, "{docs}type {name} = {ty}");
2868    }
2869
2870    fn type_list(&mut self, _: TypeId, name: &str, ty: &Type, docs: &Docs) {
2871        let name = name.to_upper_camel_case();
2872        let ty = self.type_name(self.resolve, *ty);
2873        let docs = format_docs(docs);
2874        uwriteln!(self.src, "{docs}type {name} = []{ty}");
2875    }
2876
2877    fn type_builtin(&mut self, id: TypeId, name: &str, ty: &Type, docs: &Docs) {
2878        _ = (id, name, ty, docs);
2879        todo!()
2880    }
2881
2882    fn type_future(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2883        let name = name.to_upper_camel_case();
2884        let ty = self.type_name(self.resolve, Type::Id(id));
2885        let docs = format_docs(docs);
2886        uwriteln!(self.src, "{docs}type {name} = {ty}");
2887    }
2888
2889    fn type_stream(&mut self, id: TypeId, name: &str, _: &Option<Type>, docs: &Docs) {
2890        let name = name.to_upper_camel_case();
2891        let ty = self.type_name(self.resolve, Type::Id(id));
2892        let docs = format_docs(docs);
2893        uwriteln!(self.src, "{docs}type {name} = {ty}");
2894    }
2895}
2896
2897fn interface_name(resolve: &Resolve, interface: Option<&WorldKey>) -> String {
2898    match interface {
2899        Some(WorldKey::Name(name)) => name.to_snake_case(),
2900        Some(WorldKey::Interface(id)) => {
2901            let interface = &resolve.interfaces[*id];
2902            let package = &resolve.packages[interface.package.unwrap()];
2903            let package_has_multiple_versions = resolve.packages.iter().any(|(_, p)| {
2904                p.name.namespace == package.name.namespace
2905                    && p.name.name == package.name.name
2906                    && p.name.version != package.name.version
2907            });
2908            let version = if package_has_multiple_versions {
2909                if let Some(version) = &package.name.version {
2910                    format!("{}_", version.to_string().replace(['.', '-', '+'], "_"))
2911                } else {
2912                    String::new()
2913                }
2914            } else {
2915                String::new()
2916            };
2917            let namespace = package.name.namespace.to_snake_case();
2918            let package = package.name.name.to_snake_case();
2919            let interface = interface.name.as_ref().unwrap().to_snake_case();
2920            format!("{namespace}_{package}_{version}{interface}")
2921        }
2922        None => "wit_world".into(),
2923    }
2924}
2925
2926fn func_name(resolve: &Resolve, interface: Option<&WorldKey>, func: &Function) -> String {
2927    let prefix = interface_name(resolve, interface);
2928    let name = func.name.to_snake_case().replace('.', "_");
2929
2930    format!("{prefix}_{name}")
2931}
2932
2933fn wasm_type(ty: WasmType) -> &'static str {
2934    match ty {
2935        WasmType::I32 => "int32",
2936        WasmType::I64 => "int64",
2937        WasmType::F32 => "float32",
2938        WasmType::F64 => "float64",
2939        WasmType::Pointer => "uintptr",
2940        WasmType::PointerOrI64 => "int64",
2941        WasmType::Length => "uint32",
2942    }
2943}
2944
2945fn format_docs(docs: &Docs) -> String {
2946    docs.contents
2947        .as_ref()
2948        .map(|v| {
2949            v.trim()
2950                .lines()
2951                .map(|line| format!("// {line}\n"))
2952                .collect::<Vec<_>>()
2953                .concat()
2954        })
2955        .unwrap_or_default()
2956}
2957
2958fn flags_repr(flags: &Flags) -> &'static str {
2959    match flags.repr() {
2960        FlagsRepr::U8 => "uint8",
2961        FlagsRepr::U16 => "uint16",
2962        FlagsRepr::U32(1) => "uint32",
2963        _ => unreachable!(),
2964    }
2965}
2966
2967fn int_repr(int: Int) -> &'static str {
2968    match int {
2969        Int::U8 => "uint8",
2970        Int::U16 => "uint16",
2971        Int::U32 => "uint32",
2972        Int::U64 => unreachable!(),
2973    }
2974}
2975
2976fn cast(op: &str, which: &Bitcast, need_math: &mut bool) -> String {
2977    match which {
2978        Bitcast::I32ToF32 | Bitcast::I64ToF32 => {
2979            *need_math = true;
2980            format!("math.Float32frombits(uint32({op}))")
2981        }
2982        Bitcast::F32ToI32 => {
2983            *need_math = true;
2984            format!("int32(math.Float32bits({op}))")
2985        }
2986        Bitcast::F32ToI64 => {
2987            *need_math = true;
2988            format!("int64(math.Float32bits({op}))")
2989        }
2990        Bitcast::I64ToF64 => {
2991            *need_math = true;
2992            format!("math.Float64frombits(uint64({op}))")
2993        }
2994        Bitcast::F64ToI64 => {
2995            *need_math = true;
2996            format!("int64(math.Float64bits({op}))")
2997        }
2998        Bitcast::I32ToI64 | Bitcast::LToI64 => {
2999            format!("int64({op})")
3000        }
3001        Bitcast::PToP64 => {
3002            format!("int64({op})")
3003        }
3004        Bitcast::I64ToI32 | Bitcast::I64ToL | Bitcast::PToI32 => {
3005            format!("int32({op})")
3006        }
3007        Bitcast::I64ToP64 | Bitcast::P64ToI64 => op.into(),
3008        Bitcast::P64ToP | Bitcast::LToP | Bitcast::I32ToP => {
3009            format!("uintptr({op})")
3010        }
3011        Bitcast::PToL => {
3012            format!("uint32({op})")
3013        }
3014        Bitcast::I32ToL => {
3015            format!("uint32({op})")
3016        }
3017        Bitcast::LToI32 => {
3018            format!("uint32({op})")
3019        }
3020        Bitcast::None => op.to_string(),
3021        Bitcast::Sequence(sequence) => {
3022            let [first, second] = &**sequence;
3023            let inner = cast(op, first, need_math);
3024            cast(&inner, second, need_math)
3025        }
3026    }
3027}
3028
3029fn any(resolve: &Resolve, ty: Type, fun: &dyn Fn(Type) -> bool) -> bool {
3030    if fun(ty) {
3031        return true;
3032    }
3033
3034    match ty {
3035        Type::Bool
3036        | Type::U8
3037        | Type::S8
3038        | Type::U16
3039        | Type::S16
3040        | Type::U32
3041        | Type::S32
3042        | Type::U64
3043        | Type::S64
3044        | Type::F32
3045        | Type::F64
3046        | Type::Char
3047        | Type::String => false,
3048        Type::Id(id) => {
3049            let ty = &resolve.types[id];
3050            match &ty.kind {
3051                TypeDefKind::Flags(_) | TypeDefKind::Enum(_) | TypeDefKind::Resource => false,
3052                TypeDefKind::Handle(Handle::Own(resource) | Handle::Borrow(resource)) => {
3053                    any(resolve, Type::Id(*resource), fun)
3054                }
3055                TypeDefKind::Record(record) => record
3056                    .fields
3057                    .iter()
3058                    .any(|field| any(resolve, field.ty, fun)),
3059                TypeDefKind::Variant(variant) => variant
3060                    .cases
3061                    .iter()
3062                    .any(|case| case.ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)),
3063                TypeDefKind::Option(ty) | TypeDefKind::List(ty) | TypeDefKind::Type(ty) => {
3064                    any(resolve, *ty, fun)
3065                }
3066                TypeDefKind::Result(result) => result
3067                    .ok
3068                    .map(|ty| any(resolve, ty, fun))
3069                    .or_else(|| result.err.map(|ty| any(resolve, ty, fun)))
3070                    .unwrap_or(false),
3071                TypeDefKind::Tuple(tuple) => tuple.types.iter().any(|ty| any(resolve, *ty, fun)),
3072                TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
3073                    ty.map(|ty| any(resolve, ty, fun)).unwrap_or(false)
3074                }
3075                _ => todo!("{:?}", ty.kind),
3076            }
3077        }
3078        _ => todo!("{ty:?}"),
3079    }
3080}
3081
3082fn func_declaration(resolve: &Resolve, func: &Function) -> (String, bool) {
3083    match &func.kind {
3084        FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
3085            (func.item_name().to_upper_camel_case(), false)
3086        }
3087        FunctionKind::Constructor(ty) => {
3088            let ty = resolve.types[*ty]
3089                .name
3090                .as_ref()
3091                .unwrap()
3092                .to_upper_camel_case();
3093            (format!("Make{ty}"), false)
3094        }
3095        FunctionKind::Method(ty) | FunctionKind::AsyncMethod(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!("(self *{ty}) {camel}"), true)
3103        }
3104        FunctionKind::Static(ty) | FunctionKind::AsyncStatic(ty) => {
3105            let ty = resolve.types[*ty]
3106                .name
3107                .as_ref()
3108                .unwrap()
3109                .to_upper_camel_case();
3110            let camel = func.item_name().to_upper_camel_case();
3111            (format!("{ty}{camel}"), false)
3112        }
3113    }
3114}
3115
3116fn maybe_gofmt<'a>(format: Format, code: &'a [u8]) -> Cow<'a, [u8]> {
3117    thread::scope(|s| {
3118        if let Format::True = format
3119            && let Ok((reader, mut writer)) = io::pipe()
3120        {
3121            s.spawn(move || {
3122                _ = writer.write_all(code);
3123            });
3124
3125            if let Ok(output) = Command::new("gofmt").stdin(reader).output()
3126                && output.status.success()
3127            {
3128                return Cow::Owned(output.stdout);
3129            }
3130        }
3131
3132        Cow::Borrowed(code)
3133    })
3134}