Skip to main content

linera_wit_bindgen_gen_host_wasmtime_rust/
lib.rs

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