wai_bindgen_gen_wasmer/
lib.rs

1use heck::*;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::io::{Read, Write};
4use std::mem;
5use std::process::{Command, Stdio};
6use std::str::FromStr;
7use wai_bindgen_gen_core::wai_parser::abi::{
8    AbiVariant, Bindgen, Instruction, LiftLower, WasmType,
9};
10use wai_bindgen_gen_core::{wai_parser::*, Direction, Files, Generator, Source, TypeInfo, Types};
11use wai_bindgen_gen_rust::{
12    to_rust_ident, wasm_type, FnSig, RustFlagsRepr, RustFunctionGenerator, RustGenerator, TypeMode,
13};
14
15#[derive(Default)]
16pub struct Wasmer {
17    src: Source,
18    opts: Opts,
19    needs_memory: bool,
20    needs_functions: BTreeMap<String, NeededFunction>,
21    needs_char_from_i32: bool,
22    needs_invalid_variant: bool,
23    needs_validate_flags: bool,
24    needs_raw_mem: bool,
25    needs_bad_int: bool,
26    needs_copy_slice: bool,
27    needs_buffer_glue: bool,
28    needs_le: bool,
29    needs_custom_error_to_trap: bool,
30    needs_custom_error_to_types: BTreeSet<String>,
31    needs_lazy_initialized: bool,
32    all_needed_handles: BTreeSet<String>,
33    exported_resources: BTreeSet<ResourceId>,
34    types: Types,
35    guest_imports: HashMap<String, Vec<Import>>,
36    guest_exports: HashMap<String, Exports>,
37    in_import: bool,
38    in_trait: bool,
39    trait_name: String,
40    sizes: SizeAlign,
41}
42
43enum NeededFunction {
44    Realloc,
45    Free,
46}
47
48struct Import {
49    is_async: bool,
50    name: String,
51    trait_signature: String,
52    closure: String,
53}
54
55#[derive(Default)]
56struct Exports {
57    fields: BTreeMap<String, (String, String)>,
58    funcs: Vec<String>,
59}
60
61#[derive(Default, Debug, Clone)]
62#[cfg_attr(feature = "structopt", derive(structopt::StructOpt))]
63pub struct Opts {
64    /// Whether or not `rustfmt` is executed to format generated code.
65    #[cfg_attr(feature = "structopt", structopt(long))]
66    pub rustfmt: bool,
67
68    /// Whether or not to emit `tracing` macro calls on function entry/exit.
69    #[cfg_attr(feature = "structopt", structopt(long))]
70    pub tracing: bool,
71
72    /// Indicates which functions should be `async`: `all`, `none`, or a
73    /// comma-separated list.
74    #[cfg_attr(
75        feature = "structopt",
76        structopt(long = "async", default_value = "none")
77    )]
78    pub async_: Async,
79
80    /// A flag to indicate that all trait methods in imports should return a
81    /// custom trait-defined error. Applicable for import bindings.
82    #[cfg_attr(feature = "structopt", structopt(long))]
83    pub custom_error: bool,
84}
85
86#[derive(Debug, Clone)]
87pub enum Async {
88    None,
89    All,
90    Only(HashSet<String>),
91}
92
93impl Async {
94    fn includes(&self, name: &str) -> bool {
95        match self {
96            Async::None => false,
97            Async::All => true,
98            Async::Only(list) => list.contains(name),
99        }
100    }
101
102    fn is_none(&self) -> bool {
103        match self {
104            Async::None => true,
105            _ => false,
106        }
107    }
108}
109
110impl Default for Async {
111    fn default() -> Async {
112        Async::None
113    }
114}
115
116impl FromStr for Async {
117    type Err = String;
118    fn from_str(s: &str) -> Result<Async, String> {
119        Ok(if s == "all" {
120            Async::All
121        } else if s == "none" {
122            Async::None
123        } else {
124            Async::Only(s.split(',').map(|s| s.trim().to_string()).collect())
125        })
126    }
127}
128
129impl Opts {
130    pub fn build(self) -> Wasmer {
131        let mut r = Wasmer::new();
132        r.opts = self;
133        r
134    }
135}
136
137enum FunctionRet {
138    /// The function return is normal and needs to extra handling.
139    Normal,
140    /// The function return was wrapped in a `Result` in Rust. The `Ok` variant
141    /// is the actual value that will be lowered, and the `Err`, if present,
142    /// means that a trap has occurred.
143    CustomToTrap,
144    /// The function returns a `Result` in both wasm and in Rust, but the
145    /// Rust error type is a custom error and must be converted to `err`. The
146    /// `ok` variant payload is provided here too.
147    CustomToError { ok: Type, err: String },
148}
149
150impl Wasmer {
151    pub fn new() -> Wasmer {
152        Wasmer::default()
153    }
154
155    fn abi_variant(dir: Direction) -> AbiVariant {
156        // This generator uses a reversed mapping! In the Wasmer host-side
157        // bindings, we don't use any extra adapter layer between guest wasm
158        // modules and the host. When the guest imports functions using the
159        // `GuestImport` ABI, the host directly implements the `GuestImport`
160        // ABI, even though the host is *exporting* functions. Similarly, when
161        // the guest exports functions using the `GuestExport` ABI, the host
162        // directly imports them with the `GuestExport` ABI, even though the
163        // host is *importing* functions.
164        match dir {
165            Direction::Import => AbiVariant::GuestExport,
166            Direction::Export => AbiVariant::GuestImport,
167        }
168    }
169
170    fn print_intrinsics(&mut self) {
171        if self.needs_lazy_initialized || !self.exported_resources.is_empty() {
172            self.push_str("use wai_bindgen_wasmer::once_cell::unsync::OnceCell;\n");
173        }
174
175        self.push_str("#[allow(unused_imports)]\n");
176        self.push_str("use wasmer::AsStoreMut as _;\n");
177        self.push_str("#[allow(unused_imports)]\n");
178        self.push_str("use wasmer::AsStoreRef as _;\n");
179        if self.needs_raw_mem {
180            self.push_str("use wai_bindgen_wasmer::rt::RawMem;\n");
181        }
182        if self.needs_char_from_i32 {
183            self.push_str("use wai_bindgen_wasmer::rt::char_from_i32;\n");
184        }
185        if self.needs_invalid_variant {
186            self.push_str("use wai_bindgen_wasmer::rt::invalid_variant;\n");
187        }
188        if self.needs_bad_int {
189            self.push_str("use core::convert::TryFrom;\n");
190            self.push_str("use wai_bindgen_wasmer::rt::bad_int;\n");
191        }
192        if self.needs_validate_flags {
193            self.push_str("use wai_bindgen_wasmer::rt::validate_flags;\n");
194        }
195        if self.needs_le {
196            self.push_str("use wai_bindgen_wasmer::Le;\n");
197        }
198        if self.needs_copy_slice {
199            self.push_str("use wai_bindgen_wasmer::rt::copy_slice;\n");
200        }
201    }
202
203    /// Classifies the return value of a function to see if it needs handling
204    /// with respect to the `custom_error` configuration option.
205    fn classify_fn_ret(&mut self, iface: &Interface, f: &Function) -> FunctionRet {
206        if !self.opts.custom_error {
207            return FunctionRet::Normal;
208        }
209
210        if let Type::Id(id) = &f.result {
211            if let TypeDefKind::Expected(e) = &iface.types[*id].kind {
212                if let Type::Id(err) = e.err {
213                    if let Some(name) = &iface.types[err].name {
214                        self.needs_custom_error_to_types.insert(name.clone());
215                        return FunctionRet::CustomToError {
216                            ok: e.ok,
217                            err: name.to_string(),
218                        };
219                    }
220                }
221            }
222        }
223
224        self.needs_custom_error_to_trap = true;
225        FunctionRet::CustomToTrap
226    }
227}
228
229impl RustGenerator for Wasmer {
230    fn default_param_mode(&self) -> TypeMode {
231        if self.in_import {
232            // The default here is that only leaf values can be borrowed because
233            // otherwise lists and such need to be copied into our own memory.
234            TypeMode::LeafBorrowed("'a")
235        } else {
236            // When we're calling wasm exports, however, there's no need to take
237            // any ownership of anything from the host so everything is borrowed
238            // in the parameter position.
239            TypeMode::AllBorrowed("'a")
240        }
241    }
242
243    fn handle_projection(&self) -> Option<(&'static str, String)> {
244        if self.in_import {
245            if self.in_trait {
246                Some(("Self", self.trait_name.clone()))
247            } else {
248                Some(("T", self.trait_name.clone()))
249            }
250        } else {
251            None
252        }
253    }
254
255    fn handle_wrapper(&self) -> Option<&'static str> {
256        None
257    }
258
259    fn push_str(&mut self, s: &str) {
260        self.src.push_str(s);
261    }
262
263    fn info(&self, ty: TypeId) -> TypeInfo {
264        self.types.get(ty)
265    }
266
267    fn types_mut(&mut self) -> &mut Types {
268        &mut self.types
269    }
270
271    fn print_borrowed_slice(
272        &mut self,
273        iface: &Interface,
274        mutbl: bool,
275        ty: &Type,
276        lifetime: &'static str,
277    ) {
278        if self.sizes.align(ty) > 1 && self.in_import {
279            // If we're generating bindings for an import we ideally want to
280            // hand out raw pointers into memory. We can't guarantee anything
281            // about alignment in memory, though, so if the alignment
282            // requirement is bigger than one then we have to use slices where
283            // the type has a `Le<...>` wrapper.
284            //
285            // For exports we're generating functions that take values from
286            // Rust, so we can assume alignment and use raw slices. For types
287            // with an align of 1, then raw pointers are fine since Rust will
288            // have the same alignment requirement.
289            self.needs_le = true;
290            self.push_str("&");
291            if lifetime != "'_" {
292                self.push_str(lifetime);
293                self.push_str(" ");
294            }
295            if mutbl {
296                self.push_str(" mut ");
297            }
298            self.push_str("[Le<");
299            self.print_ty(iface, ty, TypeMode::AllBorrowed(lifetime));
300            self.push_str(">]");
301        } else {
302            self.print_rust_slice(iface, mutbl, ty, lifetime);
303        }
304    }
305
306    fn print_borrowed_str(&mut self, lifetime: &'static str) {
307        self.push_str("&");
308        if lifetime != "'_" {
309            self.push_str(lifetime);
310            self.push_str(" ");
311        }
312        self.push_str(" str");
313    }
314}
315
316impl Generator for Wasmer {
317    fn preprocess_one(&mut self, iface: &Interface, dir: Direction) {
318        let variant = Self::abi_variant(dir);
319        self.types.analyze(iface);
320        self.in_import = variant == AbiVariant::GuestImport;
321        self.trait_name = iface.name.to_camel_case();
322        self.src.push_str(&format!(
323            "#[allow(clippy::all)]\npub mod {} {{\n",
324            iface.name.to_snake_case()
325        ));
326        self.src
327            .push_str("#[allow(unused_imports)]\nuse wai_bindgen_wasmer::{anyhow, wasmer};\n");
328        self.sizes.fill(iface);
329    }
330
331    fn type_record(
332        &mut self,
333        iface: &Interface,
334        id: TypeId,
335        name: &str,
336        record: &Record,
337        docs: &Docs,
338    ) {
339        self.print_typedef_record(iface, id, record, docs);
340
341        // If this record might be used as a slice type in various places then
342        // we synthesize an `Endian` implementation for it so `&[Le<ThisType>]`
343        // is usable.
344        if !self.modes_of(iface, id).is_empty()
345            && record.fields.iter().all(|f| iface.all_bits_valid(&f.ty))
346        {
347            self.src.push_str("impl wai_bindgen_wasmer::Endian for ");
348            self.src.push_str(&name.to_camel_case());
349            self.src.push_str(" {\n");
350
351            self.src.push_str("fn into_le(self) -> Self {\n");
352            self.src.push_str("Self {\n");
353            for field in record.fields.iter() {
354                self.src.push_str(&field.name.to_snake_case());
355                self.src.push_str(": self.");
356                self.src.push_str(&field.name.to_snake_case());
357                self.src.push_str(".into_le(),\n");
358            }
359            self.src.push_str("}\n");
360            self.src.push_str("}\n");
361
362            self.src.push_str("fn from_le(self) -> Self {\n");
363            self.src.push_str("Self {\n");
364            for field in record.fields.iter() {
365                self.src.push_str(&field.name.to_snake_case());
366                self.src.push_str(": self.");
367                self.src.push_str(&field.name.to_snake_case());
368                self.src.push_str(".from_le(),\n");
369            }
370            self.src.push_str("}\n");
371            self.src.push_str("}\n");
372
373            self.src.push_str("}\n");
374
375            // Also add an `AllBytesValid` valid impl since this structure's
376            // byte representations are valid (guarded by the `all_bits_valid`
377            // predicate).
378            self.src
379                .push_str("unsafe impl wai_bindgen_wasmer::AllBytesValid for ");
380            self.src.push_str(&name.to_camel_case());
381            self.src.push_str(" {}\n");
382        }
383    }
384
385    fn type_tuple(
386        &mut self,
387        iface: &Interface,
388        id: TypeId,
389        _name: &str,
390        tuple: &Tuple,
391        docs: &Docs,
392    ) {
393        self.print_typedef_tuple(iface, id, tuple, docs);
394    }
395
396    fn type_flags(
397        &mut self,
398        _iface: &Interface,
399        _id: TypeId,
400        name: &str,
401        flags: &Flags,
402        docs: &Docs,
403    ) {
404        self.src
405            .push_str("wai_bindgen_wasmer::bitflags::bitflags! {\n");
406        self.rustdoc(docs);
407        let repr = RustFlagsRepr::new(flags);
408        self.src
409            .push_str(&format!("pub struct {}: {repr} {{", name.to_camel_case()));
410        for (i, flag) in flags.flags.iter().enumerate() {
411            self.rustdoc(&flag.docs);
412            self.src.push_str(&format!(
413                "const {} = 1 << {};\n",
414                flag.name.to_shouty_snake_case(),
415                i,
416            ));
417        }
418        self.src.push_str("}\n");
419        self.src.push_str("}\n\n");
420
421        self.src.push_str("impl core::fmt::Display for ");
422        self.src.push_str(&name.to_camel_case());
423        self.src.push_str(
424            "{\nfn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n",
425        );
426
427        self.src.push_str("f.write_str(\"");
428        self.src.push_str(&name.to_camel_case());
429        self.src.push_str("(\")?;\n");
430        self.src.push_str("core::fmt::Debug::fmt(self, f)?;\n");
431        self.src.push_str("f.write_str(\" (0x\")?;\n");
432        self.src
433            .push_str("core::fmt::LowerHex::fmt(&self.bits, f)?;\n");
434        self.src.push_str("f.write_str(\"))\")?;\n");
435        self.src.push_str("Ok(())");
436
437        self.src.push_str("}\n");
438        self.src.push_str("}\n\n");
439    }
440
441    fn type_variant(
442        &mut self,
443        iface: &Interface,
444        id: TypeId,
445        _name: &str,
446        variant: &Variant,
447        docs: &Docs,
448    ) {
449        self.print_typedef_variant(iface, id, variant, docs);
450    }
451
452    fn type_enum(&mut self, _iface: &Interface, id: TypeId, name: &str, enum_: &Enum, docs: &Docs) {
453        self.print_typedef_enum(id, name, enum_, docs);
454    }
455
456    fn type_union(
457        &mut self,
458        iface: &Interface,
459        id: TypeId,
460        _name: &str,
461        union: &Union,
462        docs: &Docs,
463    ) {
464        self.print_typedef_union(iface, id, union, docs);
465    }
466
467    fn type_option(
468        &mut self,
469        iface: &Interface,
470        id: TypeId,
471        _name: &str,
472        payload: &Type,
473        docs: &Docs,
474    ) {
475        self.print_typedef_option(iface, id, payload, docs);
476    }
477
478    fn type_expected(
479        &mut self,
480        iface: &Interface,
481        id: TypeId,
482        _name: &str,
483        expected: &Expected,
484        docs: &Docs,
485    ) {
486        self.print_typedef_expected(iface, id, expected, docs);
487    }
488
489    fn type_resource(&mut self, iface: &Interface, ty: ResourceId) {
490        let name = &iface.resources[ty].name;
491        self.all_needed_handles.insert(name.to_string());
492
493        // If we're binding imports then all handles are associated types so
494        // there's nothing that we need to do about that.
495        if self.in_import {
496            return;
497        }
498
499        self.exported_resources.insert(ty);
500
501        // ... otherwise for exports we generate a newtype wrapper around an
502        // `i32` to manage the resultt.
503        let tyname = name.to_camel_case();
504        self.rustdoc(&iface.resources[ty].docs);
505        self.src.push_str("#[derive(Debug)]\n");
506        self.src.push_str(&format!(
507            "pub struct {}(wai_bindgen_wasmer::rt::ResourceIndex);\n",
508            tyname
509        ));
510    }
511
512    fn type_alias(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
513        self.print_typedef_alias(iface, id, ty, docs);
514    }
515
516    fn type_list(&mut self, iface: &Interface, id: TypeId, _name: &str, ty: &Type, docs: &Docs) {
517        self.print_type_list(iface, id, ty, docs);
518    }
519
520    fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) {
521        self.rustdoc(docs);
522        self.src
523            .push_str(&format!("pub type {}", name.to_camel_case()));
524        self.src.push_str(" = ");
525        self.print_ty(iface, ty, TypeMode::Owned);
526        self.src.push_str(";\n");
527    }
528
529    // As with `abi_variant` above, we're generating host-side bindings here
530    // so a user "export" uses the "guest import" ABI variant on the inside of
531    // this `Generator` implementation.
532    fn export(&mut self, iface: &Interface, func: &Function) {
533        assert!(!func.is_async, "async not supported yet");
534        let prev = mem::take(&mut self.src);
535
536        // Generate the closure that's passed to a `Linker`, the final piece of
537        // codegen here.
538        let sig = iface.wasm_signature(AbiVariant::GuestImport, func);
539        let params = (0..sig.params.len())
540            .map(|i| format!("arg{}", i))
541            .collect::<Vec<_>>();
542        let mut f = FunctionBindgen::new(self, params);
543        iface.call(
544            AbiVariant::GuestImport,
545            LiftLower::LiftArgsLowerResults,
546            func,
547            &mut f,
548        );
549        let FunctionBindgen {
550            src,
551            cleanup,
552            needs_borrow_checker,
553            needs_memory,
554            needs_buffer_transaction,
555            needs_functions,
556            closures,
557            async_intrinsic_called,
558            ..
559        } = f;
560        assert!(cleanup.is_none());
561        assert!(!needs_buffer_transaction);
562
563        // Generate the signature this function will have in the final trait
564        let self_arg = "&mut self".to_string();
565        self.in_trait = true;
566
567        let mut fnsig = FnSig::default();
568        fnsig.private = true;
569        fnsig.self_arg = Some(self_arg);
570        self.print_docs_and_params(iface, func, TypeMode::LeafBorrowed("'_"), &fnsig);
571        // The Rust return type may differ from the wasm return type based on
572        // the `custom_error` configuration of this code generator.
573        match self.classify_fn_ret(iface, func) {
574            FunctionRet::Normal => {
575                self.push_str(" -> ");
576                self.print_ty(iface, &func.result, TypeMode::Owned);
577            }
578            FunctionRet::CustomToTrap => {
579                self.push_str(" -> Result<");
580                self.print_ty(iface, &func.result, TypeMode::Owned);
581                self.push_str(", Self::Error>");
582            }
583            FunctionRet::CustomToError { ok, .. } => {
584                self.push_str(" -> Result<");
585                self.print_ty(iface, &ok, TypeMode::Owned);
586                self.push_str(", Self::Error>");
587            }
588        }
589        self.in_trait = false;
590        let trait_signature = mem::take(&mut self.src).into();
591
592        // Generate the closure that's passed to a `Linker`, the final piece of
593        // codegen here.
594        let result_ty = match &sig.results[..] {
595            &[] => "()".to_string(),
596            &[ty] => wasm_type(ty).to_string(),
597            tys => format!(
598                "({})",
599                tys.iter()
600                    .map(|&ty| wasm_type(ty))
601                    .collect::<Vec<_>>()
602                    .join(", ")
603            ),
604        };
605        self.src
606            .push_str("move |mut store: wasmer::FunctionEnvMut<EnvWrapper<T>>");
607        for (i, param) in sig.params.iter().enumerate() {
608            let arg = format!("arg{}", i);
609            self.src.push_str(",");
610            self.src.push_str(&arg);
611            self.src.push_str(":");
612            self.wasm_type(*param);
613        }
614        self.src.push_str(&format!(
615            "| -> Result<{}, wasmer::RuntimeError> {{\n",
616            result_ty
617        ));
618
619        // If an intrinsic was called asynchronously, which happens if anything
620        // in the module could be asynchronous, then we must wrap this host
621        // import with an async block. Otherwise if the function is itself
622        // explicitly async then we must also wrap it in an async block.
623        //
624        // If none of that happens, then this is fine to be sync because
625        // everything is sync.
626        let is_async = if async_intrinsic_called || self.opts.async_.includes(&func.name) {
627            self.src.push_str("Box::new(async move {\n");
628            true
629        } else {
630            false
631        };
632
633        if self.opts.tracing {
634            self.src.push_str(&format!(
635                "
636                    let span = wai_bindgen_wasmer::tracing::span!(
637                        wai_bindgen_wasmer::tracing::Level::TRACE,
638                        \"wai-bindgen abi\",
639                        module = \"{}\",
640                        function = \"{}\",
641                    );
642                    let _enter = span.enter();
643                ",
644                iface.name, func.name,
645            ));
646        }
647        self.src.push_str(&closures);
648
649        for name in needs_functions.keys() {
650            self.src.push_str(&format!(
651                "let func_{name} = store
652                    .data()
653                    .lazy
654                    .get()
655                    .unwrap()
656                    .func_{name}
657                    .clone();\n"
658            ));
659        }
660        self.needs_functions.extend(needs_functions);
661        self.needs_memory |= needs_memory || needs_borrow_checker;
662
663        if self.needs_memory {
664            self.src.push_str(
665                "let _memory: wasmer::Memory = store.data().lazy.get().unwrap().memory.clone();\n",
666            );
667        }
668
669        if needs_borrow_checker {
670            // TODO: This isn't actually sound and should be replaced with use
671            // of WasmPtr/WasmCell.
672            self.src.push_str(
673                "let _memory_view = _memory.view(&store);
674                let mut _bc = wai_bindgen_wasmer::BorrowChecker::new(unsafe {
675                        _memory_view.data_unchecked_mut()
676                 });\n",
677            );
678        }
679
680        self.src.push_str("let data_mut = store.data_mut();\n");
681
682        if !self.all_needed_handles.is_empty() {
683            self.src
684                .push_str("let tables = data_mut.tables.borrow_mut();\n");
685        }
686
687        self.src.push_str(&String::from(src));
688
689        if is_async {
690            self.src.push_str("})\n");
691        }
692        self.src.push_str("}");
693        let closure = mem::replace(&mut self.src, prev).into();
694
695        self.guest_imports
696            .entry(iface.name.to_string())
697            .or_default()
698            .push(Import {
699                is_async,
700                name: func.name.to_string(),
701                closure,
702                trait_signature,
703            });
704    }
705
706    // As with `abi_variant` above, we're generating host-side bindings here
707    // so a user "import" uses the "export" ABI variant on the inside of
708    // this `Generator` implementation.
709    fn import(&mut self, iface: &Interface, func: &Function) {
710        assert!(!func.is_async, "async not supported yet");
711        let prev = mem::take(&mut self.src);
712
713        // If anything is asynchronous on exports then everything must be
714        // asynchronous, we can't intermix async and sync calls because
715        // it's unknown whether the wasm module will make an async host call.
716        let is_async = !self.opts.async_.is_none();
717        let mut sig = FnSig::default();
718        sig.async_ = is_async;
719
720        // Adding the store to the self_arg is an ugly workaround, but the
721        // FnSig and Function types don't really leave a lot of room for
722        // implementing this in a better way.
723        sig.self_arg = Some("&self, store: &mut wasmer::Store".to_string());
724        self.print_docs_and_params(iface, func, TypeMode::AllBorrowed("'_"), &sig);
725        self.push_str("-> Result<");
726        self.print_ty(iface, &func.result, TypeMode::Owned);
727        self.push_str(", wasmer::RuntimeError> {\n");
728
729        let params = func
730            .params
731            .iter()
732            .map(|(name, _)| to_rust_ident(name))
733            .collect();
734        let mut f = FunctionBindgen::new(self, params);
735        iface.call(
736            AbiVariant::GuestExport,
737            LiftLower::LowerArgsLiftResults,
738            func,
739            &mut f,
740        );
741        let FunctionBindgen {
742            needs_memory,
743            src,
744            needs_borrow_checker,
745            needs_buffer_transaction,
746            closures,
747            needs_functions,
748            ..
749        } = f;
750
751        let exports = self
752            .guest_exports
753            .entry(iface.name.to_string())
754            .or_insert_with(Exports::default);
755
756        for (name, func) in needs_functions {
757            self.src
758                .push_str(&format!("let func_{name} = &self.func_{name};\n"));
759            let get = format!("_instance.exports.get_typed_function(&store, \"{name}\")?",);
760            exports
761                .fields
762                .insert(format!("func_{name}"), (func.ty(), get));
763        }
764
765        self.src.push_str(&closures);
766
767        assert!(!needs_borrow_checker);
768        if needs_memory {
769            self.src.push_str("let _memory = &self.memory;\n");
770            exports.fields.insert(
771                "memory".to_string(),
772                (
773                    "wasmer::Memory".to_string(),
774                    "_instance.exports.get_memory(\"memory\")?.clone()".to_string(),
775                ),
776            );
777        }
778
779        if needs_buffer_transaction {
780            self.needs_buffer_glue = true;
781            self.src
782                .push_str("let mut buffer_transaction = self.buffer_glue.transaction();\n");
783        }
784
785        self.src.push_str(&String::from(src));
786        self.src.push_str("}\n");
787        let func_body = mem::replace(&mut self.src, prev);
788        exports.funcs.push(func_body.into());
789
790        // Create the code snippet which will define the type of this field in
791        // the struct that we're exporting and additionally extracts the
792        // function from an instantiated instance.
793        let sig = iface.wasm_signature(AbiVariant::GuestExport, func);
794        let mut cvt = String::new();
795        if sig.params.len() == 1 {
796            cvt.push_str(wasm_type(sig.params[0]));
797        } else {
798            cvt.push('(');
799            for param in sig.params.iter() {
800                cvt.push_str(wasm_type(*param));
801                cvt.push(',');
802            }
803            cvt.push(')');
804        }
805        cvt.push_str(", ");
806        if sig.results.len() == 1 {
807            cvt.push_str(wasm_type(sig.results[0]));
808        } else {
809            cvt.push('(');
810            for result in sig.results.iter() {
811                cvt.push_str(wasm_type(*result));
812                cvt.push(',');
813            }
814            cvt.push(')');
815        }
816        exports.fields.insert(
817            format!("func_{}", to_rust_ident(&func.name)),
818            (
819                format!("wasmer::TypedFunction<{cvt}>"),
820                format!(
821                    "_instance.exports.get_typed_function(&store, \"{}\")?",
822                    func.name,
823                ),
824            ),
825        );
826    }
827
828    fn finish_one(&mut self, iface: &Interface, files: &mut Files) {
829        for (module, funcs) in sorted_iter(&self.guest_imports) {
830            let module_camel = module.to_camel_case();
831            let is_async = !self.opts.async_.is_none();
832            if is_async {
833                self.src.push_str("#[wai_bindgen_wasmer::async_trait]\n");
834            }
835            self.src.push_str("pub trait ");
836            self.src.push_str(&module_camel);
837            self.src.push_str(": Sized + Send + Sync + 'static");
838            self.src.push_str("{\n");
839            if !self.all_needed_handles.is_empty() {
840                for handle in self.all_needed_handles.iter() {
841                    self.src.push_str("type ");
842                    self.src.push_str(&handle.to_camel_case());
843                    self.src.push_str(": std::fmt::Debug");
844                    if is_async {
845                        self.src.push_str(" + Send + Sync");
846                    }
847                    self.src.push_str(";\n");
848                }
849            }
850            if self.opts.custom_error {
851                self.src.push_str("type Error;\n");
852                if self.needs_custom_error_to_trap {
853                    self.src.push_str(
854                        "fn error_to_trap(&mut self, err: Self::Error) -> wasmer::RuntimeError;\n",
855                    );
856                }
857                for ty in self.needs_custom_error_to_types.iter() {
858                    self.src.push_str(&format!(
859                        "fn error_to_{}(&mut self, err: Self::Error) -> Result<{}, wasmer::RuntimeError>;\n",
860                        ty.to_snake_case(),
861                        ty.to_camel_case(),
862                    ));
863                }
864            }
865            for f in funcs {
866                self.src.push_str(&f.trait_signature);
867                self.src.push_str(";\n\n");
868            }
869            for handle in self.all_needed_handles.iter() {
870                self.src.push_str(&format!(
871                    "fn drop_{}(&mut self, state: Self::{}) {{
872                        drop(state);
873                    }}\n",
874                    handle.to_snake_case(),
875                    handle.to_camel_case(),
876                ));
877            }
878            self.src.push_str("}\n");
879
880            if !self.all_needed_handles.is_empty() {
881                self.src.push_str("\npub struct ");
882                self.src.push_str(&module_camel);
883                self.src.push_str("Tables<T: ");
884                self.src.push_str(&module_camel);
885                self.src.push_str("> {\n");
886                for handle in self.all_needed_handles.iter() {
887                    self.src.push_str("pub(crate) ");
888                    self.src.push_str(&handle.to_snake_case());
889                    self.src.push_str("_table: wai_bindgen_wasmer::Table<T::");
890                    self.src.push_str(&handle.to_camel_case());
891                    self.src.push_str(">,\n");
892                }
893                self.src.push_str("}\n");
894                self.src.push_str("impl<T: ");
895                self.src.push_str(&module_camel);
896                self.src.push_str("> Default for ");
897                self.src.push_str(&module_camel);
898                self.src.push_str("Tables<T> {\n");
899                self.src.push_str("fn default() -> Self { Self {");
900                for handle in self.all_needed_handles.iter() {
901                    self.src.push_str(&handle.to_snake_case());
902                    self.src.push_str("_table: Default::default(),");
903                }
904                self.src.push_str("}}}");
905                self.src.push_str("impl<T: ");
906                self.src.push_str(&module_camel);
907                self.src.push_str("> Clone for ");
908                self.src.push_str(&module_camel);
909                self.src.push_str("Tables<T> {\n");
910                self.src.push_str("fn clone(&self) -> Self {\n");
911                self.src.push_str("Self::default()\n");
912                self.src.push_str("}}\n");
913            }
914        }
915
916        self.needs_lazy_initialized |= self.needs_memory;
917        self.needs_lazy_initialized |= !self.needs_functions.is_empty();
918        for (module, funcs) in mem::take(&mut self.guest_imports) {
919            let module_camel = module.to_camel_case();
920
921            if self.needs_lazy_initialized {
922                self.push_str("pub struct LazyInitialized {\n");
923                if self.needs_memory {
924                    self.push_str("memory: wasmer::Memory,\n");
925                }
926                for (name, func) in &self.needs_functions {
927                    self.src.push_str(&format!(
928                        "func_{name}: wasmer::TypedFunction<{cvt}>,\n",
929                        name = name,
930                        cvt = func.cvt(),
931                    ));
932                }
933                self.push_str("}\n");
934            }
935
936            self.push_str("\n#[must_use = \"The returned initializer function must be called\n");
937            self.push_str("with the instance and the store before starting the runtime\"]\n");
938            self.push_str("pub fn add_to_imports<T>(store: &mut wasmer::Store, imports: &mut wasmer::Imports, data: T)\n");
939            self.push_str("-> impl FnOnce(&wasmer::Instance, &dyn wasmer::AsStoreRef) -> Result<(), anyhow::Error>\n");
940            self.push_str("where T: ");
941            self.push_str(&module_camel);
942            self.push_str("\n{\n");
943
944            self.push_str("#[derive(Clone)]");
945            self.push_str("struct EnvWrapper<T: ");
946            self.push_str(&module_camel);
947            self.push_str("> {\n");
948            self.push_str("data: T,\n");
949            if !self.all_needed_handles.is_empty() {
950                self.push_str("tables: std::rc::Rc<core::cell::RefCell<");
951                self.push_str(&module_camel);
952                self.push_str("Tables<T>>>,\n");
953            }
954            if self.needs_lazy_initialized {
955                self.push_str("lazy: std::rc::Rc<OnceCell<LazyInitialized>>,\n");
956            }
957            self.push_str("}\n");
958            self.push_str("unsafe impl<T: ");
959            self.push_str(&module_camel);
960            self.push_str("> Send for EnvWrapper<T> {}\n");
961            self.push_str("unsafe impl<T: ");
962            self.push_str(&module_camel);
963            self.push_str("> Sync for EnvWrapper<T> {}\n");
964
965            if self.needs_lazy_initialized {
966                self.push_str("let lazy = std::rc::Rc::new(OnceCell::new());\n");
967            }
968
969            self.push_str("let env = EnvWrapper {\n");
970            self.push_str("data,\n");
971            if !self.all_needed_handles.is_empty() {
972                self.push_str("tables: std::rc::Rc::default(),\n");
973            }
974            if self.needs_lazy_initialized {
975                self.push_str("lazy: std::rc::Rc::clone(&lazy),\n");
976            }
977            self.push_str("};\n");
978            self.push_str("let env = wasmer::FunctionEnv::new(&mut *store, env);\n");
979            self.push_str("let mut exports = wasmer::Exports::new();\n");
980            self.push_str("let mut store = store.as_store_mut();\n");
981
982            for f in funcs {
983                if f.is_async {
984                    unimplemented!();
985                }
986                self.push_str(&format!(
987                    "exports.insert(
988                        \"{}\",
989                        wasmer::Function::new_typed_with_env(
990                            &mut store,
991                            &env,
992                            {}
993                    ));\n",
994                    f.name, f.closure,
995                ));
996            }
997            self.push_str(&format!(
998                "imports.register_namespace(\"{}\", exports);\n",
999                module
1000            ));
1001
1002            if !self.all_needed_handles.is_empty() {
1003                self.push_str("let mut canonical_abi = imports.get_namespace_exports(\"canonical_abi\").unwrap_or_else(wasmer::Exports::new);\n");
1004                for handle in self.all_needed_handles.iter() {
1005                    self.src.push_str(&format!(
1006                        "canonical_abi.insert(
1007                            \"resource_drop_{name}\",
1008                            wasmer::Function::new_typed_with_env(
1009                                &mut store,
1010                                &env,
1011                                move |mut store: wasmer::FunctionEnvMut<EnvWrapper<T>>, handle: u32| -> Result<(), wasmer::RuntimeError> {{
1012                                    let data_mut = store.data_mut();
1013                                    let mut tables = data_mut.tables.borrow_mut();
1014                                    let handle = tables
1015                                        .{snake}_table
1016                                        .remove(handle)
1017                                        .map_err(|e| {{
1018                                            wasmer::RuntimeError::new(format!(\"failed to remove handle: {{}}\", e))
1019                                        }})?;
1020                                    let host = &mut data_mut.data;
1021                                    host.drop_{snake}(handle);
1022                                    Ok(())
1023                                }}
1024                            )
1025                        );\n",
1026                        name = handle,
1027                        snake = handle.to_snake_case(),
1028                    ));
1029                }
1030                self.push_str("imports.register_namespace(\"canonical_abi\", canonical_abi);\n");
1031            }
1032
1033            self.push_str(
1034                "move |_instance: &wasmer::Instance, _store: &dyn wasmer::AsStoreRef| {\n",
1035            );
1036            if self.needs_lazy_initialized {
1037                if self.needs_memory {
1038                    self.push_str(
1039                        "let memory = _instance.exports.get_memory(\"memory\")?.clone();\n",
1040                    );
1041                }
1042                for name in self.needs_functions.keys() {
1043                    self.src.push_str(&format!(
1044                        "let func_{name} = _instance
1045                        .exports
1046                        .get_typed_function(
1047                            &_store.as_store_ref(),
1048                            \"{name}\",
1049                        )
1050                        .unwrap()
1051                        .clone();\n"
1052                    ));
1053                }
1054                self.push_str("lazy.set(LazyInitialized {\n");
1055                if self.needs_memory {
1056                    self.push_str("memory,\n");
1057                }
1058                for name in self.needs_functions.keys() {
1059                    self.src.push_str(&format!("func_{name},\n"));
1060                }
1061                self.push_str("})\n");
1062                self.push_str(
1063                    ".map_err(|_e| anyhow::anyhow!(\"Couldn't set lazy initialized data\"))?;\n",
1064                );
1065            }
1066            self.push_str("Ok(())\n");
1067            self.push_str("}\n");
1068
1069            self.push_str("}\n");
1070        }
1071
1072        for (module, exports) in sorted_iter(&mem::take(&mut self.guest_exports)) {
1073            let name = module.to_camel_case();
1074
1075            // Generate a struct that is the "state" of this exported module
1076            // which is held internally.
1077            self.push_str(
1078                "
1079                /// Auxiliary data associated with the wasm exports.
1080                ",
1081            );
1082            self.push_str("#[derive(Default)]\n");
1083            self.push_str("pub struct ");
1084            self.push_str(&name);
1085            self.push_str("Data {\n");
1086            for r in self.exported_resources.iter() {
1087                self.src.push_str(&format!(
1088                    "
1089                        index_slab{idx}: wai_bindgen_wasmer::rt::IndexSlab,
1090                        resource_slab{idx}: wai_bindgen_wasmer::rt::ResourceSlab,
1091                        dtor{idx}: OnceCell<wasmer::TypedFunction<i32, ()>>,
1092                    ",
1093                    idx = r.index(),
1094                ));
1095            }
1096            self.push_str("}\n\n");
1097
1098            self.push_str("pub struct ");
1099            self.push_str(&name);
1100            self.push_str(" {\n");
1101            self.push_str("#[allow(dead_code)]\n");
1102            self.push_str(&format!("env: wasmer::FunctionEnv<{}Data>,\n", name));
1103            for (name, (ty, _)) in exports.fields.iter() {
1104                self.push_str(name);
1105                self.push_str(": ");
1106                self.push_str(ty);
1107                self.push_str(",\n");
1108            }
1109            self.push_str("}\n");
1110            self.push_str(&format!("impl {} {{\n", name));
1111
1112            if self.exported_resources.is_empty() {
1113                self.push_str("#[allow(unused_variables)]\n");
1114            }
1115            self.push_str(&format!(
1116                "
1117                    /// Adds any intrinsics, if necessary for this exported wasm
1118                    /// functionality to the `ImportObject` provided.
1119                    ///
1120                    /// This function returns the `{0}Data` which needs to be
1121                    /// passed through to `{0}::new`.
1122                    fn add_to_imports(
1123                        mut store: impl wasmer::AsStoreMut,
1124                        imports: &mut wasmer::Imports,
1125                    ) -> wasmer::FunctionEnv<{0}Data> {{
1126                ",
1127                name,
1128            ));
1129            self.push_str(&format!(
1130                "let env = wasmer::FunctionEnv::new(&mut store, {name}Data::default());\n"
1131            ));
1132            if !self.all_needed_handles.is_empty() {
1133                self.push_str("let mut canonical_abi = imports.get_namespace_exports(\"canonical_abi\").unwrap_or_else(wasmer::Exports::new);\n");
1134                for r in self.exported_resources.iter() {
1135                    if !self.opts.async_.is_none() {
1136                        unimplemented!();
1137                    }
1138                    self.src.push_str(&format!(
1139                        "
1140                        canonical_abi.insert(
1141                            \"resource_drop_{resource}\",
1142                            wasmer::Function::new_typed_with_env(
1143                                &mut store,
1144                                &env,
1145                                move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<(), wasmer::RuntimeError> {{
1146                                    let resource_idx = store.data_mut().index_slab{idx}.remove(idx)?;
1147                                    let wasm = match store.data_mut().resource_slab{idx}.drop(resource_idx) {{
1148                                        Some(wasm) => wasm,
1149                                        None => return Ok(()),
1150                                    }};
1151                                    let dtor = store.data_mut().dtor{idx}.get().unwrap().clone();
1152                                    dtor.call(&mut store, wasm)?;
1153                                    Ok(())
1154                                }},
1155                            )
1156                        );
1157                        canonical_abi.insert(
1158                            \"resource_clone_{resource}\",
1159                            wasmer::Function::new_typed_with_env(
1160                                &mut store,
1161                                &env,
1162                                move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<u32, wasmer::RuntimeError>  {{
1163                                    let state = &mut *store.data_mut();
1164                                    let resource_idx = state.index_slab{idx}.get(idx)?;
1165                                    state.resource_slab{idx}.clone(resource_idx)?;
1166                                    Ok(state.index_slab{idx}.insert(resource_idx))
1167                                }},
1168                            )
1169                        );
1170                        canonical_abi.insert(
1171                            \"resource_get_{resource}\",
1172                            wasmer::Function::new_typed_with_env(
1173                                &mut store,
1174                                &env,
1175                                move |mut store: wasmer::FunctionEnvMut<{name}Data>, idx: u32| -> Result<i32, wasmer::RuntimeError>  {{
1176                                    let state = &mut *store.data_mut();
1177                                    let resource_idx = state.index_slab{idx}.get(idx)?;
1178                                    Ok(state.resource_slab{idx}.get(resource_idx))
1179                                }},
1180                            )
1181                        );
1182                        canonical_abi.insert(
1183                            \"resource_new_{resource}\",
1184                            wasmer::Function::new_typed_with_env(
1185                                &mut store,
1186                                &env,
1187                                move |mut store: wasmer::FunctionEnvMut<{name}Data>, val: i32| -> Result<u32, wasmer::RuntimeError>  {{
1188                                    let state = &mut *store.data_mut();
1189                                    let resource_idx = state.resource_slab{idx}.insert(val);
1190                                    Ok(state.index_slab{idx}.insert(resource_idx))
1191                                }},
1192                            )
1193                        );
1194                    ",
1195                        name = name,
1196                        resource = iface.resources[*r].name,
1197                        idx = r.index(),
1198                    ));
1199                }
1200                self.push_str("imports.register_namespace(\"canonical_abi\", canonical_abi);\n");
1201            }
1202            self.push_str("env\n");
1203            self.push_str("}\n");
1204
1205            if !self.opts.async_.is_none() {
1206                unimplemented!();
1207            }
1208            self.push_str(
1209                "
1210                    /// Instantiates the provided `module` using the specified
1211                    /// parameters, wrapping up the result in a structure that
1212                    /// translates between wasm and the host.
1213                    ///
1214                    /// The `imports` provided will have intrinsics added to it
1215                    /// automatically, so it's not necessary to call
1216                    /// `add_to_imports` beforehand. This function will
1217                    /// instantiate the `module` otherwise using `imports`, and
1218                    /// both an instance of this structure and the underlying
1219                    /// `wasmer::Instance` will be returned.
1220                    pub fn instantiate(
1221                        mut store: impl wasmer::AsStoreMut,
1222                        module: &wasmer::Module,
1223                        imports: &mut wasmer::Imports,
1224                    ) -> anyhow::Result<(Self, wasmer::Instance)> {
1225                        let env = Self::add_to_imports(&mut store, imports);
1226                        let instance = wasmer::Instance::new(
1227                            &mut store, module, &*imports)?;
1228                        ",
1229            );
1230            if !self.exported_resources.is_empty() {
1231                self.push_str("{\n");
1232                for r in self.exported_resources.iter() {
1233                    self.src.push_str(&format!(
1234                        "let dtor{idx} = instance
1235                                .exports
1236                                .get_typed_function(
1237                                    &store,
1238                                    \"canonical_abi_drop_{name}\",
1239                                )?
1240                                .clone();
1241                                ",
1242                        name = iface.resources[*r].name,
1243                        idx = r.index(),
1244                    ));
1245                }
1246                self.push_str("\n");
1247
1248                for r in self.exported_resources.iter() {
1249                    self.src.push_str(&format!(
1250                            "env
1251                                .as_mut(&mut store)
1252                                .dtor{idx}
1253                                .set(dtor{idx})
1254                                .map_err(|_e| anyhow::anyhow!(\"Couldn't set canonical_abi_drop_{name}\"))?;
1255                                ",
1256                                name = iface.resources[*r].name,
1257                                idx = r.index(),
1258                                ));
1259                }
1260                self.push_str("}\n");
1261            }
1262            self.push_str(
1263                "
1264                        Ok((Self::new(store, &instance, env)?, instance))
1265                    }
1266                ",
1267            );
1268
1269            self.push_str(&format!(
1270                "
1271                    /// Low-level creation wrapper for wrapping up the exports
1272                    /// of the `instance` provided in this structure of wasm
1273                    /// exports.
1274                    ///
1275                    /// This function will extract exports from the `instance`
1276                    /// and wrap them all up in the returned structure which can
1277                    /// be used to interact with the wasm module.
1278                    pub fn new(
1279                        store: impl wasmer::AsStoreMut,
1280                        _instance: &wasmer::Instance,
1281                        env: wasmer::FunctionEnv<{}Data>,
1282                    ) -> Result<Self, wasmer::ExportError> {{
1283                ",
1284                name,
1285            ));
1286            //assert!(!self.needs_get_func);
1287            for (name, (_, get)) in exports.fields.iter() {
1288                self.push_str("let ");
1289                self.push_str(name);
1290                self.push_str("= ");
1291                self.push_str(get);
1292                self.push_str(";\n");
1293            }
1294            self.push_str("Ok(");
1295            self.push_str(&name);
1296            self.push_str("{\n");
1297            for (name, _) in exports.fields.iter() {
1298                self.push_str(name);
1299                self.push_str(",\n");
1300            }
1301            self.push_str("env,\n");
1302            self.push_str("})\n");
1303            self.push_str("}\n");
1304
1305            for func in exports.funcs.iter() {
1306                self.push_str(func);
1307            }
1308
1309            for r in self.exported_resources.iter() {
1310                if !self.opts.async_.is_none() {
1311                    unimplemented!();
1312                }
1313                self.src.push_str(&format!(
1314                    "
1315                        /// Drops the host-owned handle to the resource
1316                        /// specified.
1317                        ///
1318                        /// Note that this may execute the WebAssembly-defined
1319                        /// destructor for this type. This also may not run
1320                        /// the destructor if there are still other references
1321                        /// to this type.
1322                        pub fn drop_{name_snake}(
1323                            &self,
1324                            store: &mut wasmer::Store,
1325                            val: {name_camel},
1326                        ) -> Result<(), wasmer::RuntimeError> {{
1327                            let state = self.env.as_mut(store);
1328                            let wasm = match state.resource_slab{idx}.drop(val.0) {{
1329                                Some(val) => val,
1330                                None => return Ok(()),
1331                            }};
1332                            let dtor{idx} = state.dtor{idx}.get().unwrap().clone();
1333                            dtor{idx}.call(store, wasm)?;
1334                            Ok(())
1335                        }}
1336                    ",
1337                    name_snake = iface.resources[*r].name.to_snake_case(),
1338                    name_camel = iface.resources[*r].name.to_camel_case(),
1339                    idx = r.index(),
1340                ));
1341            }
1342
1343            self.push_str("}\n");
1344        }
1345        self.print_intrinsics();
1346
1347        // Close the opening `mod`.
1348        self.push_str("}\n");
1349
1350        let mut src = mem::take(&mut self.src);
1351        if self.opts.rustfmt {
1352            let mut child = Command::new("rustfmt")
1353                .arg("--edition=2018")
1354                .stdin(Stdio::piped())
1355                .stdout(Stdio::piped())
1356                .spawn()
1357                .expect("failed to spawn `rustfmt`");
1358            child
1359                .stdin
1360                .take()
1361                .unwrap()
1362                .write_all(src.as_bytes())
1363                .unwrap();
1364            src.as_mut_string().truncate(0);
1365            child
1366                .stdout
1367                .take()
1368                .unwrap()
1369                .read_to_string(src.as_mut_string())
1370                .unwrap();
1371            let status = child.wait().unwrap();
1372            assert!(status.success());
1373        }
1374
1375        files.push("bindings.rs", src.as_bytes());
1376    }
1377}
1378
1379struct FunctionBindgen<'a> {
1380    gen: &'a mut Wasmer,
1381
1382    // Number used to assign unique names to temporary variables.
1383    tmp: usize,
1384
1385    // Destination where source code is pushed onto for this function
1386    src: Source,
1387
1388    // The named parameters that are available to this function
1389    params: Vec<String>,
1390
1391    // Management of block scopes used by `Bindgen`.
1392    block_storage: Vec<Source>,
1393    blocks: Vec<String>,
1394
1395    // Whether or not the code generator is after the invocation of wasm or the
1396    // host, used for knowing where to acquire memory from.
1397    after_call: bool,
1398    // Whether or not the `caller_memory` variable has been defined and is
1399    // available for use.
1400    caller_memory_available: bool,
1401    // Whether or not a helper function was called in an async fashion. If so
1402    // and this is an import, then the import must be defined asynchronously as
1403    // well.
1404    async_intrinsic_called: bool,
1405    // Code that must be executed before a return, generated during instruction
1406    // lowering.
1407    cleanup: Option<String>,
1408
1409    // Rust clousures for buffers that must be placed at the front of the
1410    // function.
1411    closures: Source,
1412
1413    // Various intrinsic properties this function's codegen required, must be
1414    // satisfied in the function header if any are set.
1415    needs_buffer_transaction: bool,
1416    needs_borrow_checker: bool,
1417    needs_memory: bool,
1418    needs_functions: HashMap<String, NeededFunction>,
1419}
1420
1421impl FunctionBindgen<'_> {
1422    fn new(gen: &mut Wasmer, params: Vec<String>) -> FunctionBindgen<'_> {
1423        FunctionBindgen {
1424            gen,
1425            block_storage: Vec::new(),
1426            blocks: Vec::new(),
1427            src: Source::default(),
1428            after_call: false,
1429            caller_memory_available: false,
1430            async_intrinsic_called: false,
1431            tmp: 0,
1432            cleanup: None,
1433            closures: Source::default(),
1434            needs_buffer_transaction: false,
1435            needs_borrow_checker: false,
1436            needs_memory: false,
1437            needs_functions: HashMap::new(),
1438            params,
1439        }
1440    }
1441
1442    fn memory_src(&mut self) -> String {
1443        if self.gen.in_import {
1444            if !self.after_call {
1445                // Before calls we use `_bc` which is a borrow checker used for
1446                // getting long-lasting borrows into memory.
1447                self.needs_borrow_checker = true;
1448                return "_bc".to_string();
1449            }
1450
1451            if !self.caller_memory_available {
1452                self.needs_memory = true;
1453                self.caller_memory_available = true;
1454                self.push_str("let _memory_view = _memory.view(&store);\n");
1455                self.push_str(
1456                    "let caller_memory = unsafe { _memory_view.data_unchecked_mut() };\n",
1457                );
1458            }
1459            "caller_memory".to_string()
1460        } else {
1461            self.needs_memory = true;
1462            self.push_str("let _memory_view = _memory.view(&store);\n");
1463            "unsafe { _memory_view.data_unchecked_mut() }".to_string()
1464        }
1465    }
1466
1467    fn call_intrinsic(&mut self, name: &str, args: String) {
1468        if !self.gen.opts.async_.is_none() {
1469            self.async_intrinsic_called = true;
1470            unimplemented!();
1471        };
1472        self.push_str(&format!("func_{name}.call({args})?;\n"));
1473        self.caller_memory_available = false; // invalidated by call
1474    }
1475
1476    fn load(&mut self, offset: i32, ty: &str, operands: &[String]) -> String {
1477        let mem = self.memory_src();
1478        self.gen.needs_raw_mem = true;
1479        let tmp = self.tmp();
1480        self.push_str(&format!(
1481            "let load{} = {}.load::<{}>({} + {})?;\n",
1482            tmp, mem, ty, operands[0], offset
1483        ));
1484        format!("load{}", tmp)
1485    }
1486
1487    fn store(&mut self, offset: i32, method: &str, extra: &str, operands: &[String]) {
1488        let mem = self.memory_src();
1489        self.gen.needs_raw_mem = true;
1490        self.push_str(&format!(
1491            "{}.store({} + {}, wai_bindgen_wasmer::rt::{}({}){})?;\n",
1492            mem, operands[1], offset, method, operands[0], extra
1493        ));
1494    }
1495}
1496
1497impl RustFunctionGenerator for FunctionBindgen<'_> {
1498    fn push_str(&mut self, s: &str) {
1499        self.src.push_str(s);
1500    }
1501
1502    fn tmp(&mut self) -> usize {
1503        let ret = self.tmp;
1504        self.tmp += 1;
1505        ret
1506    }
1507
1508    fn rust_gen(&self) -> &dyn RustGenerator {
1509        self.gen
1510    }
1511
1512    fn lift_lower(&self) -> LiftLower {
1513        if self.gen.in_import {
1514            LiftLower::LiftArgsLowerResults
1515        } else {
1516            LiftLower::LowerArgsLiftResults
1517        }
1518    }
1519}
1520
1521impl Bindgen for FunctionBindgen<'_> {
1522    type Operand = String;
1523
1524    fn sizes(&self) -> &SizeAlign {
1525        &self.gen.sizes
1526    }
1527
1528    fn push_block(&mut self) {
1529        let prev = mem::take(&mut self.src);
1530        self.block_storage.push(prev);
1531    }
1532
1533    fn finish_block(&mut self, operands: &mut Vec<String>) {
1534        let to_restore = self.block_storage.pop().unwrap();
1535        let src = mem::replace(&mut self.src, to_restore);
1536        let expr = match operands.len() {
1537            0 => "()".to_string(),
1538            1 => operands[0].clone(),
1539            _ => format!("({})", operands.join(", ")),
1540        };
1541        if src.is_empty() {
1542            self.blocks.push(expr);
1543        } else if operands.is_empty() {
1544            self.blocks.push(format!("{{\n{}}}", &src[..]));
1545        } else {
1546            self.blocks.push(format!("{{\n{}{}\n}}", &src[..], expr));
1547        }
1548        self.caller_memory_available = false;
1549    }
1550
1551    fn return_pointer(&mut self, _iface: &Interface, _size: usize, _align: usize) -> String {
1552        unimplemented!()
1553    }
1554
1555    fn is_list_canonical(&self, iface: &Interface, ty: &Type) -> bool {
1556        iface.all_bits_valid(ty)
1557    }
1558
1559    fn emit(
1560        &mut self,
1561        iface: &Interface,
1562        inst: &Instruction<'_>,
1563        operands: &mut Vec<String>,
1564        results: &mut Vec<String>,
1565    ) {
1566        let mut top_as = |cvt: &str| {
1567            let mut s = operands.pop().unwrap();
1568            s.push_str(" as ");
1569            s.push_str(cvt);
1570            results.push(s);
1571        };
1572
1573        let mut try_from = |cvt: &str, operands: &[String], results: &mut Vec<String>| {
1574            self.gen.needs_bad_int = true;
1575            let result = format!("{}::try_from({}).map_err(bad_int)?", cvt, operands[0]);
1576            results.push(result);
1577        };
1578
1579        match inst {
1580            Instruction::GetArg { nth } => results.push(self.params[*nth].clone()),
1581            Instruction::I32Const { val } => results.push(format!("{}i32", val)),
1582            Instruction::ConstZero { tys } => {
1583                for ty in tys.iter() {
1584                    match ty {
1585                        WasmType::I32 => results.push("0i32".to_string()),
1586                        WasmType::I64 => results.push("0i64".to_string()),
1587                        WasmType::F32 => results.push("0.0f32".to_string()),
1588                        WasmType::F64 => results.push("0.0f64".to_string()),
1589                    }
1590                }
1591            }
1592
1593            Instruction::I64FromU64 | Instruction::I64FromS64 => {
1594                let s = operands.pop().unwrap();
1595                results.push(format!("wai_bindgen_wasmer::rt::as_i64({})", s));
1596            }
1597            Instruction::I32FromChar
1598            | Instruction::I32FromU8
1599            | Instruction::I32FromS8
1600            | Instruction::I32FromU16
1601            | Instruction::I32FromS16
1602            | Instruction::I32FromU32
1603            | Instruction::I32FromS32 => {
1604                let s = operands.pop().unwrap();
1605                results.push(format!("wai_bindgen_wasmer::rt::as_i32({})", s));
1606            }
1607
1608            Instruction::F32FromFloat32
1609            | Instruction::F64FromFloat64
1610            | Instruction::Float32FromF32
1611            | Instruction::Float64FromF64
1612            | Instruction::S32FromI32
1613            | Instruction::S64FromI64 => {
1614                results.push(operands.pop().unwrap());
1615            }
1616
1617            // Downcasts from `i32` into smaller integers are checked to ensure
1618            // that they fit within the valid range. While not strictly
1619            // necessary since we could chop bits off this should be more
1620            // forward-compatible with any future changes.
1621            Instruction::S8FromI32 => try_from("i8", operands, results),
1622            Instruction::U8FromI32 => try_from("u8", operands, results),
1623            Instruction::S16FromI32 => try_from("i16", operands, results),
1624            Instruction::U16FromI32 => try_from("u16", operands, results),
1625
1626            // Casts of the same bit width simply use `as` since we're just
1627            // reinterpreting the bits already there.
1628            Instruction::U32FromI32 => top_as("u32"),
1629            Instruction::U64FromI64 => top_as("u64"),
1630
1631            Instruction::CharFromI32 => {
1632                self.gen.needs_char_from_i32 = true;
1633                results.push(format!("char_from_i32({})?", operands[0]));
1634            }
1635
1636            Instruction::Bitcasts { casts } => {
1637                wai_bindgen_gen_rust::bitcast(casts, operands, results)
1638            }
1639
1640            Instruction::UnitLower => {
1641                self.push_str(&format!("let () = {};\n", operands[0]));
1642            }
1643            Instruction::UnitLift => {
1644                results.push("()".to_string());
1645            }
1646
1647            Instruction::I32FromBool => {
1648                results.push(format!("match {} {{ true => 1, false => 0 }}", operands[0]));
1649            }
1650            Instruction::BoolFromI32 => {
1651                self.gen.needs_invalid_variant = true;
1652                results.push(format!(
1653                    "match {} {{
1654                        0 => false,
1655                        1 => true,
1656                        _ => return Err(invalid_variant(\"bool\")),
1657                    }}",
1658                    operands[0],
1659                ));
1660            }
1661
1662            Instruction::I32FromOwnedHandle { ty } => {
1663                let name = &iface.resources[*ty].name;
1664                results.push(format!(
1665                    "{{
1666                        let data_mut = store.data_mut();
1667                        let mut tables = data_mut.tables.borrow_mut();
1668                        tables.{}_table.insert({}) as i32
1669                    }}",
1670                    name.to_snake_case(),
1671                    operands[0]
1672                ));
1673            }
1674            Instruction::HandleBorrowedFromI32 { ty } => {
1675                let name = &iface.resources[*ty].name;
1676                results.push(format!(
1677                    "tables
1678                        .{}_table
1679                        .get(({}) as u32)
1680                        .ok_or_else(|| {{
1681                            wasmer::RuntimeError::new(\"invalid handle index\")
1682                        }})?",
1683                    name.to_snake_case(),
1684                    operands[0]
1685                ));
1686            }
1687            Instruction::I32FromBorrowedHandle { ty } => {
1688                let tmp = self.tmp();
1689                self.push_str(&format!(
1690                    "
1691                        let obj{tmp} = {op};
1692                        let handle{tmp} = {{
1693                            let state = self.env.as_mut(store);
1694                            state.resource_slab{idx}.clone(obj{tmp}.0)?;
1695                            state.index_slab{idx}.insert(obj{tmp}.0)
1696                        }};
1697                    ",
1698                    tmp = tmp,
1699                    idx = ty.index(),
1700                    op = operands[0],
1701                ));
1702
1703                results.push(format!("handle{} as i32", tmp,));
1704            }
1705            Instruction::HandleOwnedFromI32 { ty } => {
1706                let tmp = self.tmp();
1707                self.push_str(&format!(
1708                    "let state = self.env.as_mut(store);
1709                    let handle{} = state.index_slab{}.remove({} as u32)?;\n",
1710                    tmp,
1711                    ty.index(),
1712                    operands[0],
1713                ));
1714
1715                let name = iface.resources[*ty].name.to_camel_case();
1716                results.push(format!("{}(handle{})", name, tmp));
1717            }
1718
1719            Instruction::RecordLower { ty, record, .. } => {
1720                self.record_lower(iface, *ty, record, &operands[0], results);
1721            }
1722            Instruction::RecordLift { ty, record, .. } => {
1723                self.record_lift(iface, *ty, record, operands, results);
1724            }
1725
1726            Instruction::TupleLower { tuple, .. } => {
1727                self.tuple_lower(tuple, &operands[0], results);
1728            }
1729            Instruction::TupleLift { .. } => {
1730                self.tuple_lift(operands, results);
1731            }
1732
1733            Instruction::FlagsLower { flags, .. } => {
1734                let tmp = self.tmp();
1735                self.push_str(&format!("let flags{} = {};\n", tmp, operands[0]));
1736                for i in 0..flags.repr().count() {
1737                    results.push(format!("(flags{}.bits >> {}) as i32", tmp, i * 32));
1738                }
1739            }
1740            Instruction::FlagsLift { flags, name, .. } => {
1741                self.gen.needs_validate_flags = true;
1742                let repr = RustFlagsRepr::new(flags);
1743                let mut flags = String::from("0");
1744                for (i, op) in operands.iter().enumerate() {
1745                    flags.push_str(&format!("| (({} as {repr}) << {})", op, i * 32));
1746                }
1747                results.push(format!(
1748                    "validate_flags(
1749                        {},
1750                        {name}::all().bits(),
1751                        \"{name}\",
1752                        |bits| {name} {{ bits }}
1753                    )?",
1754                    flags,
1755                    name = name.to_camel_case(),
1756                ));
1757            }
1758
1759            Instruction::VariantPayloadName => results.push("e".to_string()),
1760
1761            Instruction::VariantLower {
1762                variant,
1763                results: result_types,
1764                ty,
1765                ..
1766            } => {
1767                let blocks = self
1768                    .blocks
1769                    .drain(self.blocks.len() - variant.cases.len()..)
1770                    .collect::<Vec<_>>();
1771                self.let_results(result_types.len(), results);
1772                let op0 = &operands[0];
1773                self.push_str(&format!("match {op0} {{\n"));
1774                let name = self.typename_lower(iface, *ty);
1775                for (case, block) in variant.cases.iter().zip(blocks) {
1776                    let case_name = case.name.to_camel_case();
1777                    self.push_str(&format!("{name}::{case_name}"));
1778                    if case.ty == Type::Unit {
1779                        self.push_str(&format!(" => {{\nlet e = ();\n{block}\n}}\n"));
1780                    } else {
1781                        self.push_str(&format!("(e) => {block},\n"));
1782                    }
1783                }
1784                self.push_str("};\n");
1785            }
1786
1787            Instruction::VariantLift { variant, ty, .. } => {
1788                let blocks = self
1789                    .blocks
1790                    .drain(self.blocks.len() - variant.cases.len()..)
1791                    .collect::<Vec<_>>();
1792                let op0 = &operands[0];
1793                let mut result = format!("match {op0} {{\n");
1794                let name = self.typename_lift(iface, *ty);
1795                for (i, (case, block)) in variant.cases.iter().zip(blocks).enumerate() {
1796                    let block = if case.ty != Type::Unit {
1797                        format!("({block})")
1798                    } else {
1799                        String::new()
1800                    };
1801                    let case = case.name.to_camel_case();
1802                    result.push_str(&format!("{i} => {name}::{case}{block},\n"));
1803                }
1804                result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1805                result.push('}');
1806                results.push(result);
1807                self.gen.needs_invalid_variant = true;
1808            }
1809
1810            Instruction::UnionLower {
1811                union,
1812                results: result_types,
1813                ty,
1814                ..
1815            } => {
1816                let blocks = self
1817                    .blocks
1818                    .drain(self.blocks.len() - union.cases.len()..)
1819                    .collect::<Vec<_>>();
1820                self.let_results(result_types.len(), results);
1821                let op0 = &operands[0];
1822                self.push_str(&format!("match {op0} {{\n"));
1823                let name = self.typename_lower(iface, *ty);
1824                for (case_name, block) in self
1825                    .gen
1826                    .union_case_names(iface, union)
1827                    .into_iter()
1828                    .zip(blocks)
1829                {
1830                    self.push_str(&format!("{name}::{case_name}(e) => {block},\n"));
1831                }
1832                self.push_str("};\n");
1833            }
1834
1835            Instruction::UnionLift { union, ty, .. } => {
1836                let blocks = self
1837                    .blocks
1838                    .drain(self.blocks.len() - union.cases.len()..)
1839                    .collect::<Vec<_>>();
1840                let op0 = &operands[0];
1841                let mut result = format!("match {op0} {{\n");
1842                let name = self.typename_lift(iface, *ty);
1843                for (i, (case_name, block)) in self
1844                    .gen
1845                    .union_case_names(iface, union)
1846                    .into_iter()
1847                    .zip(blocks)
1848                    .enumerate()
1849                {
1850                    result.push_str(&format!("{i} => {name}::{case_name}({block}),\n"));
1851                }
1852                result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1853                result.push('}');
1854                results.push(result);
1855            }
1856
1857            Instruction::OptionLower {
1858                results: result_types,
1859                ..
1860            } => {
1861                let some = self.blocks.pop().unwrap();
1862                let none = self.blocks.pop().unwrap();
1863                self.let_results(result_types.len(), results);
1864                let operand = &operands[0];
1865                self.push_str(&format!(
1866                    "match {operand} {{
1867                        Some(e) => {some},
1868                        None => {{\nlet e = ();\n{none}\n}},
1869                    }};"
1870                ));
1871            }
1872
1873            Instruction::OptionLift { .. } => {
1874                let some = self.blocks.pop().unwrap();
1875                let none = self.blocks.pop().unwrap();
1876                assert_eq!(none, "()");
1877                let operand = &operands[0];
1878                results.push(format!(
1879                    "match {operand} {{
1880                        0 => None,
1881                        1 => Some({some}),
1882                        _ => return Err(invalid_variant(\"option\")),
1883                    }}"
1884                ));
1885                self.gen.needs_invalid_variant = true;
1886            }
1887
1888            Instruction::ExpectedLower {
1889                results: result_types,
1890                ..
1891            } => {
1892                let err = self.blocks.pop().unwrap();
1893                let ok = self.blocks.pop().unwrap();
1894                self.let_results(result_types.len(), results);
1895                let operand = &operands[0];
1896                self.push_str(&format!(
1897                    "match {operand} {{
1898                        Ok(e) => {{ {ok} }},
1899                        Err(e) => {{ {err} }},
1900                    }};"
1901                ));
1902            }
1903
1904            Instruction::ExpectedLift { .. } => {
1905                let err = self.blocks.pop().unwrap();
1906                let ok = self.blocks.pop().unwrap();
1907                let operand = &operands[0];
1908                results.push(format!(
1909                    "match {operand} {{
1910                        0 => Ok({ok}),
1911                        1 => Err({err}),
1912                        _ => return Err(invalid_variant(\"expected\")),
1913                    }}"
1914                ));
1915                self.gen.needs_invalid_variant = true;
1916            }
1917
1918            Instruction::EnumLower { .. } => {
1919                results.push(format!("{} as i32", operands[0]));
1920            }
1921
1922            Instruction::EnumLift { name, enum_, .. } => {
1923                let op0 = &operands[0];
1924                let mut result = format!("match {op0} {{\n");
1925                let name = name.to_camel_case();
1926                for (i, case) in enum_.cases.iter().enumerate() {
1927                    let case = case.name.to_camel_case();
1928                    result.push_str(&format!("{i} => {name}::{case},\n"));
1929                }
1930                result.push_str(&format!("_ => return Err(invalid_variant(\"{name}\")),\n"));
1931                result.push('}');
1932                results.push(result);
1933                self.gen.needs_invalid_variant = true;
1934            }
1935
1936            Instruction::ListCanonLower { element, realloc } => {
1937                // Lowering only happens when we're passing lists into wasm,
1938                // which forces us to always allocate, so this should always be
1939                // `Some`.
1940                let realloc = realloc.unwrap();
1941                self.needs_functions
1942                    .insert(realloc.to_string(), NeededFunction::Realloc);
1943                let (size, align) = (self.gen.sizes.size(element), self.gen.sizes.align(element));
1944
1945                // Store the operand into a temporary...
1946                let tmp = self.tmp();
1947                let val = format!("vec{}", tmp);
1948                self.push_str(&format!("let {} = {};\n", val, operands[0]));
1949
1950                // ... and then realloc space for the result in the guest module
1951                let ptr = format!("ptr{}", tmp);
1952                self.push_str(&format!("let {} = ", ptr));
1953                self.call_intrinsic(
1954                    realloc,
1955                    format!(
1956                        "&mut store.as_store_mut(), 0, 0, {}, ({}.len() as i32) * {}",
1957                        align, val, size
1958                    ),
1959                );
1960
1961                // ... and then copy over the result.
1962                let mem = self.memory_src();
1963                self.push_str(&format!("{}.store_many({}, &{})?;\n", mem, ptr, val));
1964                self.gen.needs_raw_mem = true;
1965                self.needs_memory = true;
1966                results.push(ptr);
1967                results.push(format!("{}.len() as i32", val));
1968            }
1969
1970            Instruction::ListCanonLift { element, free, .. } => match free {
1971                Some(free) => {
1972                    self.needs_memory = true;
1973                    self.gen.needs_copy_slice = true;
1974                    self.needs_functions
1975                        .insert(free.to_string(), NeededFunction::Free);
1976                    let align = self.gen.sizes.align(element);
1977                    let tmp = self.tmp();
1978                    self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1979                    self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
1980                    let result = format!(
1981                        "
1982                                copy_slice(
1983                                    store,
1984                                    _memory,
1985                                    func_{},
1986                                    ptr{tmp}, len{tmp}, {}
1987                                )?
1988                            ",
1989                        free,
1990                        align,
1991                        tmp = tmp
1992                    );
1993                    results.push(result);
1994                }
1995                None => {
1996                    self.needs_borrow_checker = true;
1997                    let tmp = self.tmp();
1998                    self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
1999                    self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2000                    let slice = format!("_bc.slice(ptr{0}, len{0})?", tmp);
2001                    results.push(slice);
2002                }
2003            },
2004
2005            Instruction::StringLower { realloc } => {
2006                // see above for this unwrap
2007                let realloc = realloc.unwrap();
2008                self.needs_functions
2009                    .insert(realloc.to_string(), NeededFunction::Realloc);
2010
2011                // Store the operand into a temporary...
2012                let tmp = self.tmp();
2013                let val = format!("vec{}", tmp);
2014                self.push_str(&format!("let {} = {};\n", val, operands[0]));
2015
2016                // ... and then realloc space for the result in the guest module
2017                let ptr = format!("ptr{}", tmp);
2018                self.push_str(&format!("let {} = ", ptr));
2019                self.call_intrinsic(
2020                    realloc,
2021                    format!("&mut store.as_store_mut(), 0, 0, 1, {}.len() as i32", val),
2022                );
2023
2024                // ... and then copy over the result.
2025                let mem = self.memory_src();
2026                self.push_str(&format!(
2027                    "{}.store_many({}, {}.as_bytes())?;\n",
2028                    mem, ptr, val
2029                ));
2030                self.gen.needs_raw_mem = true;
2031                self.needs_memory = true;
2032                results.push(ptr);
2033                results.push(format!("{}.len() as i32", val));
2034            }
2035
2036            Instruction::StringLift { free } => match free {
2037                Some(free) => {
2038                    self.needs_memory = true;
2039                    self.gen.needs_copy_slice = true;
2040                    self.needs_functions
2041                        .insert(free.to_string(), NeededFunction::Free);
2042                    let tmp = self.tmp();
2043                    self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
2044                    self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2045                    self.push_str(&format!(
2046                        "
2047                            let data{tmp} = copy_slice(
2048                                store,
2049                                _memory,
2050                                func_{},
2051                                ptr{tmp}, len{tmp}, 1,
2052                            )?;
2053                        ",
2054                        free,
2055                        tmp = tmp,
2056                    ));
2057                    results.push(format!(
2058                        "String::from_utf8(data{})
2059                            .map_err(|_| wasmer::RuntimeError::new(\"invalid utf-8\"))?",
2060                        tmp,
2061                    ));
2062                }
2063                None => {
2064                    self.needs_borrow_checker = true;
2065                    let tmp = self.tmp();
2066                    self.push_str(&format!("let ptr{} = {};\n", tmp, operands[0]));
2067                    self.push_str(&format!("let len{} = {};\n", tmp, operands[1]));
2068                    let slice = format!("_bc.slice_str(ptr{0}, len{0})?", tmp);
2069                    results.push(slice);
2070                }
2071            },
2072
2073            Instruction::ListLower { element, realloc } => {
2074                let realloc = realloc.unwrap();
2075                let body = self.blocks.pop().unwrap();
2076                let tmp = self.tmp();
2077                let vec = format!("vec{}", tmp);
2078                let result = format!("result{}", tmp);
2079                let len = format!("len{}", tmp);
2080                self.needs_functions
2081                    .insert(realloc.to_string(), NeededFunction::Realloc);
2082                let size = self.gen.sizes.size(element);
2083                let align = self.gen.sizes.align(element);
2084
2085                // first store our vec-to-lower in a temporary since we'll
2086                // reference it multiple times.
2087                self.push_str(&format!("let {} = {};\n", vec, operands[0]));
2088                self.push_str(&format!("let {} = {}.len() as i32;\n", len, vec));
2089
2090                // ... then realloc space for the result in the guest module
2091                self.push_str(&format!("let {} = ", result));
2092                self.call_intrinsic(
2093                    realloc,
2094                    format!(
2095                        "&mut store.as_store_mut(), 0, 0, {}, {} * {}",
2096                        align, len, size
2097                    ),
2098                );
2099
2100                // ... then consume the vector and use the block to lower the
2101                // result.
2102                self.push_str(&format!(
2103                    "for (i, e) in {}.into_iter().enumerate() {{\n",
2104                    vec
2105                ));
2106                self.push_str(&format!("let base = {} + (i as i32) * {};\n", result, size));
2107                self.push_str(&body);
2108                self.push_str("}");
2109
2110                results.push(result);
2111                results.push(len);
2112            }
2113
2114            Instruction::ListLift { element, free, .. } => {
2115                let body = self.blocks.pop().unwrap();
2116                let tmp = self.tmp();
2117                let size = self.gen.sizes.size(element);
2118                let align = self.gen.sizes.align(element);
2119                let len = format!("len{}", tmp);
2120                self.push_str(&format!("let {} = {};\n", len, operands[1]));
2121                let base = format!("base{}", tmp);
2122                self.push_str(&format!("let {} = {};\n", base, operands[0]));
2123                let result = format!("result{}", tmp);
2124                self.push_str(&format!(
2125                    "let mut {} = Vec::with_capacity({} as usize);\n",
2126                    result, len,
2127                ));
2128
2129                self.push_str("for i in 0..");
2130                self.push_str(&len);
2131                self.push_str(" {\n");
2132                self.push_str("let base = ");
2133                self.push_str(&base);
2134                self.push_str(" + i *");
2135                self.push_str(&size.to_string());
2136                self.push_str(";\n");
2137                self.push_str(&result);
2138                self.push_str(".push(");
2139                self.push_str(&body);
2140                self.push_str(");\n");
2141                self.push_str("}\n");
2142                results.push(result);
2143
2144                if let Some(free) = free {
2145                    self.call_intrinsic(
2146                        free,
2147                        format!(
2148                            "&mut store.as_store_mut(), {}, {} * {}, {}",
2149                            base, len, size, align
2150                        ),
2151                    );
2152                    self.needs_functions
2153                        .insert(free.to_string(), NeededFunction::Free);
2154                }
2155            }
2156
2157            Instruction::IterElem { .. } => {
2158                self.caller_memory_available = false; // invalidated by for loop
2159                results.push("e".to_string())
2160            }
2161
2162            Instruction::IterBasePointer => results.push("base".to_string()),
2163
2164            Instruction::CallWasm {
2165                iface: _,
2166                name,
2167                sig,
2168            } => {
2169                if !sig.results.is_empty() {
2170                    let tmp = self.tmp();
2171                    if sig.results.len() == 1 {
2172                        self.push_str("let ");
2173                        let arg = format!("result{}", tmp);
2174                        self.push_str(&arg);
2175                        results.push(arg);
2176                        self.push_str(" = ");
2177                    } else {
2178                        self.push_str("let (");
2179                        for i in 0..sig.results.len() {
2180                            let arg = format!("result{}_{}", tmp, i);
2181                            self.push_str(&arg);
2182                            self.push_str(",");
2183                            results.push(arg);
2184                        }
2185                        self.push_str(") = ");
2186                    }
2187                }
2188                self.push_str("self.func_");
2189                self.push_str(&to_rust_ident(name));
2190                if self.gen.opts.async_.includes(name) {
2191                    self.push_str(".call_async(store, ");
2192                } else {
2193                    self.push_str(".call(store, ");
2194                }
2195                for operand in operands {
2196                    self.push_str(operand);
2197                    self.push_str(", ");
2198                }
2199                self.push_str(")");
2200                if self.gen.opts.async_.includes(name) {
2201                    self.push_str(".await");
2202                }
2203                self.push_str("?;\n");
2204                self.after_call = true;
2205                self.caller_memory_available = false; // invalidated by call
2206            }
2207
2208            Instruction::CallWasmAsyncImport { .. } => unimplemented!(),
2209            Instruction::CallWasmAsyncExport { .. } => unimplemented!(),
2210
2211            Instruction::CallInterface { module: _, func } => {
2212                for (i, operand) in operands.iter().enumerate() {
2213                    self.push_str(&format!("let param{} = {};\n", i, operand));
2214                }
2215                if self.gen.opts.tracing && !func.params.is_empty() {
2216                    self.push_str("wai_bindgen_wasmer::tracing::event!(\n");
2217                    self.push_str("wai_bindgen_wasmer::tracing::Level::TRACE,\n");
2218                    for (i, (name, _ty)) in func.params.iter().enumerate() {
2219                        self.push_str(&format!(
2220                            "{} = wai_bindgen_wasmer::tracing::field::debug(&param{}),\n",
2221                            to_rust_ident(name),
2222                            i
2223                        ));
2224                    }
2225                    self.push_str(");\n");
2226                }
2227
2228                let mut call = format!("host.{}(", func.name.to_snake_case());
2229                for i in 0..operands.len() {
2230                    call.push_str(&format!("param{}, ", i));
2231                }
2232                call.push(')');
2233                if self.gen.opts.async_.includes(&func.name) {
2234                    call.push_str(".await");
2235                }
2236
2237                self.push_str("let host = &mut data_mut.data;\n");
2238                self.push_str("let result = ");
2239                results.push("result".to_string());
2240                match self.gen.classify_fn_ret(iface, func) {
2241                    FunctionRet::Normal => self.push_str(&call),
2242                    // Unwrap the result, translating errors to unconditional
2243                    // traps
2244                    FunctionRet::CustomToTrap => {
2245                        self.push_str("match ");
2246                        self.push_str(&call);
2247                        self.push_str("{\n");
2248                        self.push_str("Ok(val) => val,\n");
2249                        self.push_str("Err(e) => return Err(host.error_to_trap(e)),\n");
2250                        self.push_str("}");
2251                    }
2252                    // Keep the `Result` as a `Result`, but convert the error
2253                    // to either the expected destination value or a trap,
2254                    // propagating a trap outwards.
2255                    FunctionRet::CustomToError { err, .. } => {
2256                        self.push_str("match ");
2257                        self.push_str(&call);
2258                        self.push_str("{\n");
2259                        self.push_str("Ok(val) => Ok(val),\n");
2260                        self.push_str(&format!("Err(e) => Err(host.error_to_{}(e)?),\n", err));
2261                        self.push_str("}");
2262                    }
2263                }
2264                self.push_str(";\n");
2265
2266                if !self.gen.all_needed_handles.is_empty() {
2267                    self.push_str("drop(tables);\n");
2268                }
2269
2270                self.after_call = true;
2271
2272                match &func.result {
2273                    Type::Unit => {}
2274                    _ if self.gen.opts.tracing => {
2275                        self.push_str("wai_bindgen_wasmer::tracing::event!(\n");
2276                        self.push_str("wai_bindgen_wasmer::tracing::Level::TRACE,\n");
2277                        self.push_str(&format!(
2278                            "{} = wai_bindgen_wasmer::tracing::field::debug(&{0}),\n",
2279                            results[0],
2280                        ));
2281                        self.push_str(");\n");
2282                    }
2283                    _ => {}
2284                }
2285            }
2286
2287            Instruction::Return { amt, .. } => {
2288                let result = match amt {
2289                    0 => "Ok(())\n".to_string(),
2290                    1 => format!("Ok({})\n", operands[0]),
2291                    _ => format!("Ok(({}))\n", operands.join(", ")),
2292                };
2293                match self.cleanup.take() {
2294                    Some(cleanup) => {
2295                        self.push_str("let ret = ");
2296                        self.push_str(&result);
2297                        self.push_str(";\n");
2298                        self.push_str(&cleanup);
2299                        self.push_str("ret");
2300                    }
2301                    None => self.push_str(&result),
2302                }
2303            }
2304
2305            Instruction::ReturnAsyncExport { .. } => unimplemented!(),
2306            Instruction::ReturnAsyncImport { .. } => unimplemented!(),
2307
2308            Instruction::I32Load { offset } => results.push(self.load(*offset, "i32", operands)),
2309            Instruction::I32Load8U { offset } => {
2310                results.push(format!("i32::from({})", self.load(*offset, "u8", operands)));
2311            }
2312            Instruction::I32Load8S { offset } => {
2313                results.push(format!("i32::from({})", self.load(*offset, "i8", operands)));
2314            }
2315            Instruction::I32Load16U { offset } => {
2316                results.push(format!(
2317                    "i32::from({})",
2318                    self.load(*offset, "u16", operands)
2319                ));
2320            }
2321            Instruction::I32Load16S { offset } => {
2322                results.push(format!(
2323                    "i32::from({})",
2324                    self.load(*offset, "i16", operands)
2325                ));
2326            }
2327            Instruction::I64Load { offset } => results.push(self.load(*offset, "i64", operands)),
2328            Instruction::F32Load { offset } => results.push(self.load(*offset, "f32", operands)),
2329            Instruction::F64Load { offset } => results.push(self.load(*offset, "f64", operands)),
2330
2331            Instruction::I32Store { offset } => self.store(*offset, "as_i32", "", operands),
2332            Instruction::I64Store { offset } => self.store(*offset, "as_i64", "", operands),
2333            Instruction::F32Store { offset } => self.store(*offset, "as_f32", "", operands),
2334            Instruction::F64Store { offset } => self.store(*offset, "as_f64", "", operands),
2335            Instruction::I32Store8 { offset } => self.store(*offset, "as_i32", " as u8", operands),
2336            Instruction::I32Store16 { offset } => {
2337                self.store(*offset, "as_i32", " as u16", operands)
2338            }
2339
2340            Instruction::Malloc {
2341                realloc,
2342                size,
2343                align,
2344            } => {
2345                self.needs_functions
2346                    .insert(realloc.to_string(), NeededFunction::Realloc);
2347                let tmp = self.tmp();
2348                let ptr = format!("ptr{}", tmp);
2349                self.push_str(&format!("let {} = ", ptr));
2350                self.call_intrinsic(realloc, format!("store, 0, 0, {}, {}", align, size));
2351                results.push(ptr);
2352            }
2353
2354            Instruction::Free { .. } => unimplemented!(),
2355        }
2356    }
2357}
2358
2359impl NeededFunction {
2360    fn cvt(&self) -> &'static str {
2361        match self {
2362            NeededFunction::Realloc => "(i32, i32, i32, i32), i32",
2363            NeededFunction::Free => "(i32, i32, i32), ()",
2364        }
2365    }
2366
2367    fn ty(&self) -> String {
2368        format!("wasmer::TypedFunction<{}>", self.cvt())
2369    }
2370}
2371
2372fn sorted_iter<K: Ord, V>(map: &HashMap<K, V>) -> impl Iterator<Item = (&K, &V)> {
2373    let mut list = map.iter().collect::<Vec<_>>();
2374    list.sort_by_key(|p| p.0);
2375    list.into_iter()
2376}