1 use crate::runtime::StoreInner;
2 use crate::trampoline::StoreInstanceHandle;
3 use crate::{Extern, FuncType, Memory, Store, Trap, Val, ValType};
4 use anyhow::{bail, ensure, Context as _, Result};
5 use std::cmp::max;
6 use std::fmt;
7 use std::mem;
8 use std::panic::{self, AssertUnwindSafe};
9 use std::ptr;
10 use std::rc::Weak;
11 use wasmtime_runtime::{raise_user_trap, ExportFunction, VMTrampoline};
12 use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody};
13 
14 /// A WebAssembly function which can be called.
15 ///
16 /// This type can represent a number of callable items, such as:
17 ///
18 /// * An exported function from a WebAssembly module.
19 /// * A user-defined function used to satisfy an import.
20 ///
21 /// These types of callable items are all wrapped up in this `Func` and can be
22 /// used to both instantiate an [`Instance`] as well as be extracted from an
23 /// [`Instance`].
24 ///
25 /// [`Instance`]: crate::Instance
26 ///
27 /// # `Func` and `Clone`
28 ///
29 /// Functions are internally reference counted so you can `clone` a `Func`. The
30 /// cloning process only performs a shallow clone, so two cloned `Func`
31 /// instances are equivalent in their functionality.
32 ///
33 /// # Examples
34 ///
35 /// One way to get a `Func` is from an [`Instance`] after you've instantiated
36 /// it:
37 ///
38 /// ```
39 /// # use wasmtime::*;
40 /// # fn main() -> anyhow::Result<()> {
41 /// let engine = Engine::default();
42 /// let store = Store::new(&engine);
43 /// let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
44 /// let instance = Instance::new(&store, &module, &[])?;
45 /// let foo = instance.get_func("foo").expect("export wasn't a function");
46 ///
47 /// // Work with `foo` as a `Func` at this point, such as calling it
48 /// // dynamically...
49 /// match foo.call(&[]) {
50 ///     Ok(result) => { /* ... */ }
51 ///     Err(trap) => {
52 ///         panic!("execution of `foo` resulted in a wasm trap: {}", trap);
53 ///     }
54 /// }
55 /// foo.call(&[])?;
56 ///
57 /// // ... or we can make a static assertion about its signature and call it.
58 /// // Our first call here can fail if the signatures don't match, and then the
59 /// // second call can fail if the function traps (like the `match` above).
60 /// let foo = foo.get0::<()>()?;
61 /// foo()?;
62 /// # Ok(())
63 /// # }
64 /// ```
65 ///
66 /// You can also use the [`wrap` function](Func::wrap) to create a
67 /// `Func`
68 ///
69 /// ```
70 /// # use wasmtime::*;
71 /// # fn main() -> anyhow::Result<()> {
72 /// let store = Store::default();
73 ///
74 /// // Create a custom `Func` which can execute arbitrary code inside of the
75 /// // closure.
76 /// let add = Func::wrap(&store, |a: i32, b: i32| -> i32 { a + b });
77 ///
78 /// // Next we can hook that up to a wasm module which uses it.
79 /// let module = Module::new(
80 ///     store.engine(),
81 ///     r#"
82 ///         (module
83 ///             (import "" "" (func $add (param i32 i32) (result i32)))
84 ///             (func (export "call_add_twice") (result i32)
85 ///                 i32.const 1
86 ///                 i32.const 2
87 ///                 call $add
88 ///                 i32.const 3
89 ///                 i32.const 4
90 ///                 call $add
91 ///                 i32.add))
92 ///     "#,
93 /// )?;
94 /// let instance = Instance::new(&store, &module, &[add.into()])?;
95 /// let call_add_twice = instance.get_func("call_add_twice").expect("export wasn't a function");
96 /// let call_add_twice = call_add_twice.get0::<i32>()?;
97 ///
98 /// assert_eq!(call_add_twice()?, 10);
99 /// # Ok(())
100 /// # }
101 /// ```
102 ///
103 /// Or you could also create an entirely dynamic `Func`!
104 ///
105 /// ```
106 /// # use wasmtime::*;
107 /// # fn main() -> anyhow::Result<()> {
108 /// let store = Store::default();
109 ///
110 /// // Here we need to define the type signature of our `Double` function and
111 /// // then wrap it up in a `Func`
112 /// let double_type = wasmtime::FuncType::new(
113 ///     Box::new([wasmtime::ValType::I32]),
114 ///     Box::new([wasmtime::ValType::I32])
115 /// );
116 /// let double = Func::new(&store, double_type, |_, params, results| {
117 ///     let mut value = params[0].unwrap_i32();
118 ///     value *= 2;
119 ///     results[0] = value.into();
120 ///     Ok(())
121 /// });
122 ///
123 /// let module = Module::new(
124 ///     store.engine(),
125 ///     r#"
126 ///         (module
127 ///             (import "" "" (func $double (param i32) (result i32)))
128 ///             (func $start
129 ///                 i32.const 1
130 ///                 call $double
131 ///                 drop)
132 ///             (start $start))
133 ///     "#,
134 /// )?;
135 /// let instance = Instance::new(&store, &module, &[double.into()])?;
136 /// // .. work with `instance` if necessary
137 /// # Ok(())
138 /// # }
139 /// ```
140 #[derive(Clone)]
141 pub struct Func {
142     instance: StoreInstanceHandle,
143     export: ExportFunction,
144     trampoline: VMTrampoline,
145 }
146 
147 macro_rules! getters {
148     ($(
149         $(#[$doc:meta])*
150         ($name:ident $(,$args:ident)*)
151     )*) => ($(
152         $(#[$doc])*
153         #[allow(non_snake_case)]
154         pub fn $name<$($args,)* R>(&self)
155             -> anyhow::Result<impl Fn($($args,)*) -> Result<R, Trap>>
156         where
157             $($args: WasmTy,)*
158             R: WasmTy,
159         {
160             // Verify all the paramers match the expected parameters, and that
161             // there are no extra parameters...
162             let ty = self.ty();
163             let mut params = ty.params().iter().cloned();
164             let n = 0;
165             $(
166                 let n = n + 1;
167                 $args::matches(&mut params)
168                     .with_context(|| format!("Type mismatch in argument {}", n))?;
169             )*
170             ensure!(params.next().is_none(), "Type mismatch: too many arguments (expected {})", n);
171 
172             // ... then do the same for the results...
173             let mut results = ty.results().iter().cloned();
174             R::matches(&mut results)
175                 .context("Type mismatch in return type")?;
176             ensure!(results.next().is_none(), "Type mismatch: too many return values (expected 1)");
177 
178             // Pass the instance into the closure so that we keep it live for the lifetime
179             // of the closure. Pass the export in so that we can call it.
180             let instance = self.instance.clone();
181             let export = self.export.clone();
182 
183             // ... and then once we've passed the typechecks we can hand out our
184             // object since our `transmute` below should be safe!
185             Ok(move |$($args: $args),*| -> Result<R, Trap> {
186                 unsafe {
187                     let fnptr = mem::transmute::<
188                         *const VMFunctionBody,
189                         unsafe extern "C" fn(
190                             *mut VMContext,
191                             *mut VMContext,
192                             $($args,)*
193                         ) -> R,
194                     >(export.address);
195                     let mut ret = None;
196                     $(let $args = $args.into_abi();)*
197                     catch_traps(export.vmctx, &instance.store, || {
198                         ret = Some(fnptr(export.vmctx, ptr::null_mut(), $($args,)*));
199                     })?;
200 
201                     Ok(ret.unwrap())
202                 }
203             })
204         }
205     )*)
206 }
207 
208 impl Func {
209     /// Creates a new `Func` with the given arguments, typically to create a
210     /// user-defined function to pass as an import to a module.
211     ///
212     /// * `store` - a cache of data where information is stored, typically
213     ///   shared with a [`Module`](crate::Module).
214     ///
215     /// * `ty` - the signature of this function, used to indicate what the
216     ///   inputs and outputs are, which must be WebAssembly types.
217     ///
218     /// * `func` - the native code invoked whenever this `Func` will be called.
219     ///   This closure is provided a [`Caller`] as its first argument to learn
220     ///   information about the caller, and then it's passed a list of
221     ///   parameters as a slice along with a mutable slice of where to write
222     ///   results.
223     ///
224     /// Note that the implementation of `func` must adhere to the `ty`
225     /// signature given, error or traps may occur if it does not respect the
226     /// `ty` signature.
227     ///
228     /// Additionally note that this is quite a dynamic function since signatures
229     /// are not statically known. For a more performant `Func` it's recommended
230     /// to use [`Func::wrap`] if you can because with statically known
231     /// signatures the engine can optimize the implementation much more.
new( store: &Store, ty: FuncType, func: impl Fn(Caller<'_>, &[Val], &mut [Val]) -> Result<(), Trap> + 'static, ) -> Self232     pub fn new(
233         store: &Store,
234         ty: FuncType,
235         func: impl Fn(Caller<'_>, &[Val], &mut [Val]) -> Result<(), Trap> + 'static,
236     ) -> Self {
237         let store_weak = store.weak();
238         let ty_clone = ty.clone();
239 
240         // Create our actual trampoline function which translates from a bunch
241         // of bit patterns on the stack to actual instances of `Val` being
242         // passed to the given function.
243         let func = Box::new(move |caller_vmctx, values_vec: *mut u128| {
244             // We have a dynamic guarantee that `values_vec` has the right
245             // number of arguments and the right types of arguments. As a result
246             // we should be able to safely run through them all and read them.
247             let mut args = Vec::with_capacity(ty_clone.params().len());
248             let store = Store::upgrade(&store_weak).unwrap();
249             for (i, ty) in ty_clone.params().iter().enumerate() {
250                 unsafe {
251                     args.push(Val::read_value_from(&store, values_vec.add(i), ty));
252                 }
253             }
254             let mut returns = vec![Val::null(); ty_clone.results().len()];
255             func(
256                 Caller {
257                     store: &store_weak,
258                     caller_vmctx,
259                 },
260                 &args,
261                 &mut returns,
262             )?;
263 
264             // Unlike our arguments we need to dynamically check that the return
265             // values produced are correct. There could be a bug in `func` that
266             // produces the wrong number or wrong types of values, and we need
267             // to catch that here.
268             for (i, (ret, ty)) in returns.iter_mut().zip(ty_clone.results()).enumerate() {
269                 if ret.ty() != *ty {
270                     return Err(Trap::new(
271                         "function attempted to return an incompatible value",
272                     ));
273                 }
274                 unsafe {
275                     ret.write_value_to(values_vec.add(i));
276                 }
277             }
278             Ok(())
279         });
280         let (instance, export, trampoline) =
281             crate::trampoline::generate_func_export(&ty, func, store).expect("generated func");
282         Func {
283             instance,
284             export,
285             trampoline,
286         }
287     }
288 
289     /// Creates a new `Func` from the given Rust closure.
290     ///
291     /// This function will create a new `Func` which, when called, will
292     /// execute the given Rust closure. Unlike [`Func::new`] the target
293     /// function being called is known statically so the type signature can
294     /// be inferred. Rust types will map to WebAssembly types as follows:
295     ///
296     /// | Rust Argument Type | WebAssembly Type |
297     /// |--------------------|------------------|
298     /// | `i32`              | `i32`            |
299     /// | `u32`              | `i32`            |
300     /// | `i64`              | `i64`            |
301     /// | `u64`              | `i64`            |
302     /// | `f32`              | `f32`            |
303     /// | `f64`              | `f64`            |
304     /// | (not supported)    | `v128`           |
305     /// | (not supported)    | `externref`         |
306     ///
307     /// Any of the Rust types can be returned from the closure as well, in
308     /// addition to some extra types
309     ///
310     /// | Rust Return Type  | WebAssembly Return Type | Meaning           |
311     /// |-------------------|-------------------------|-------------------|
312     /// | `()`              | nothing                 | no return value   |
313     /// | `Result<T, Trap>` | `T`                     | function may trap |
314     ///
315     /// At this time multi-value returns are not supported, and supporting this
316     /// is the subject of [#1178].
317     ///
318     /// [#1178]: https://github.com/bytecodealliance/wasmtime/issues/1178
319     ///
320     /// Finally you can also optionally take [`Caller`] as the first argument of
321     /// your closure. If inserted then you're able to inspect the caller's
322     /// state, for example the [`Memory`] it has exported so you can read what
323     /// pointers point to.
324     ///
325     /// Note that when using this API, the intention is to create as thin of a
326     /// layer as possible for when WebAssembly calls the function provided. With
327     /// sufficient inlining and optimization the WebAssembly will call straight
328     /// into `func` provided, with no extra fluff entailed.
329     ///
330     /// # Examples
331     ///
332     /// First up we can see how simple wasm imports can be implemented, such
333     /// as a function that adds its two arguments and returns the result.
334     ///
335     /// ```
336     /// # use wasmtime::*;
337     /// # fn main() -> anyhow::Result<()> {
338     /// # let store = Store::default();
339     /// let add = Func::wrap(&store, |a: i32, b: i32| a + b);
340     /// let module = Module::new(
341     ///     store.engine(),
342     ///     r#"
343     ///         (module
344     ///             (import "" "" (func $add (param i32 i32) (result i32)))
345     ///             (func (export "foo") (param i32 i32) (result i32)
346     ///                 local.get 0
347     ///                 local.get 1
348     ///                 call $add))
349     ///     "#,
350     /// )?;
351     /// let instance = Instance::new(&store, &module, &[add.into()])?;
352     /// let foo = instance.get_func("foo").unwrap().get2::<i32, i32, i32>()?;
353     /// assert_eq!(foo(1, 2)?, 3);
354     /// # Ok(())
355     /// # }
356     /// ```
357     ///
358     /// We can also do the same thing, but generate a trap if the addition
359     /// overflows:
360     ///
361     /// ```
362     /// # use wasmtime::*;
363     /// # fn main() -> anyhow::Result<()> {
364     /// # let store = Store::default();
365     /// let add = Func::wrap(&store, |a: i32, b: i32| {
366     ///     match a.checked_add(b) {
367     ///         Some(i) => Ok(i),
368     ///         None => Err(Trap::new("overflow")),
369     ///     }
370     /// });
371     /// let module = Module::new(
372     ///     store.engine(),
373     ///     r#"
374     ///         (module
375     ///             (import "" "" (func $add (param i32 i32) (result i32)))
376     ///             (func (export "foo") (param i32 i32) (result i32)
377     ///                 local.get 0
378     ///                 local.get 1
379     ///                 call $add))
380     ///     "#,
381     /// )?;
382     /// let instance = Instance::new(&store, &module, &[add.into()])?;
383     /// let foo = instance.get_func("foo").unwrap().get2::<i32, i32, i32>()?;
384     /// assert_eq!(foo(1, 2)?, 3);
385     /// assert!(foo(i32::max_value(), 1).is_err());
386     /// # Ok(())
387     /// # }
388     /// ```
389     ///
390     /// And don't forget all the wasm types are supported!
391     ///
392     /// ```
393     /// # use wasmtime::*;
394     /// # fn main() -> anyhow::Result<()> {
395     /// # let store = Store::default();
396     /// let debug = Func::wrap(&store, |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
397     ///
398     ///     println!("a={}", a);
399     ///     println!("b={}", b);
400     ///     println!("c={}", c);
401     ///     println!("d={}", d);
402     ///     println!("e={}", e);
403     ///     println!("f={}", f);
404     /// });
405     /// let module = Module::new(
406     ///     store.engine(),
407     ///     r#"
408     ///         (module
409     ///             (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
410     ///             (func (export "foo")
411     ///                 i32.const -1
412     ///                 i32.const 1
413     ///                 f32.const 2
414     ///                 i64.const -3
415     ///                 i64.const 3
416     ///                 f64.const 4
417     ///                 call $debug))
418     ///     "#,
419     /// )?;
420     /// let instance = Instance::new(&store, &module, &[debug.into()])?;
421     /// let foo = instance.get_func("foo").unwrap().get0::<()>()?;
422     /// foo()?;
423     /// # Ok(())
424     /// # }
425     /// ```
426     ///
427     /// Finally if you want to get really fancy you can also implement
428     /// imports that read/write wasm module's memory
429     ///
430     /// ```
431     /// use std::str;
432     ///
433     /// # use wasmtime::*;
434     /// # fn main() -> anyhow::Result<()> {
435     /// # let store = Store::default();
436     /// let log_str = Func::wrap(&store, |caller: Caller<'_>, ptr: i32, len: i32| {
437     ///     let mem = match caller.get_export("memory") {
438     ///         Some(Extern::Memory(mem)) => mem,
439     ///         _ => return Err(Trap::new("failed to find host memory")),
440     ///     };
441     ///
442     ///     // We're reading raw wasm memory here so we need `unsafe`. Note
443     ///     // though that this should be safe because we don't reenter wasm
444     ///     // while we're reading wasm memory, nor should we clash with
445     ///     // any other memory accessors (assuming they're well-behaved
446     ///     // too).
447     ///     unsafe {
448     ///         let data = mem.data_unchecked()
449     ///             .get(ptr as u32 as usize..)
450     ///             .and_then(|arr| arr.get(..len as u32 as usize));
451     ///         let string = match data {
452     ///             Some(data) => match str::from_utf8(data) {
453     ///                 Ok(s) => s,
454     ///                 Err(_) => return Err(Trap::new("invalid utf-8")),
455     ///             },
456     ///             None => return Err(Trap::new("pointer/length out of bounds")),
457     ///         };
458     ///         assert_eq!(string, "Hello, world!");
459     ///         println!("{}", string);
460     ///     }
461     ///     Ok(())
462     /// });
463     /// let module = Module::new(
464     ///     store.engine(),
465     ///     r#"
466     ///         (module
467     ///             (import "" "" (func $log_str (param i32 i32)))
468     ///             (func (export "foo")
469     ///                 i32.const 4   ;; ptr
470     ///                 i32.const 13  ;; len
471     ///                 call $log_str)
472     ///             (memory (export "memory") 1)
473     ///             (data (i32.const 4) "Hello, world!"))
474     ///     "#,
475     /// )?;
476     /// let instance = Instance::new(&store, &module, &[log_str.into()])?;
477     /// let foo = instance.get_func("foo").unwrap().get0::<()>()?;
478     /// foo()?;
479     /// # Ok(())
480     /// # }
481     /// ```
wrap<Params, Results>(store: &Store, func: impl IntoFunc<Params, Results>) -> Func482     pub fn wrap<Params, Results>(store: &Store, func: impl IntoFunc<Params, Results>) -> Func {
483         func.into_func(store)
484     }
485 
486     /// Returns the underlying wasm type that this `Func` has.
ty(&self) -> FuncType487     pub fn ty(&self) -> FuncType {
488         // Signatures should always be registered in the store's registry of
489         // shared signatures, so we should be able to unwrap safely here.
490         let sig = self.instance.store.lookup_signature(self.export.signature);
491 
492         // This is only called with `Export::Function`, and since it's coming
493         // from wasmtime_runtime itself we should support all the types coming
494         // out of it, so assert such here.
495         FuncType::from_wasm_func_type(&sig).expect("core wasm signature should be supported")
496     }
497 
498     /// Returns the number of parameters that this function takes.
param_arity(&self) -> usize499     pub fn param_arity(&self) -> usize {
500         let sig = self.instance.store.lookup_signature(self.export.signature);
501         sig.params.len()
502     }
503 
504     /// Returns the number of results this function produces.
result_arity(&self) -> usize505     pub fn result_arity(&self) -> usize {
506         let sig = self.instance.store.lookup_signature(self.export.signature);
507         sig.returns.len()
508     }
509 
510     /// Invokes this function with the `params` given, returning the results and
511     /// any trap, if one occurs.
512     ///
513     /// The `params` here must match the type signature of this `Func`, or a
514     /// trap will occur. If a trap occurs while executing this function, then a
515     /// trap will also be returned.
516     ///
517     /// This function should not panic unless the underlying function itself
518     /// initiates a panic.
call(&self, params: &[Val]) -> Result<Box<[Val]>>519     pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>> {
520         // We need to perform a dynamic check that the arguments given to us
521         // match the signature of this function and are appropriate to pass to
522         // this function. This involves checking to make sure we have the right
523         // number and types of arguments as well as making sure everything is
524         // from the same `Store`.
525         let my_ty = self.ty();
526         if my_ty.params().len() != params.len() {
527             bail!(
528                 "expected {} arguments, got {}",
529                 my_ty.params().len(),
530                 params.len()
531             );
532         }
533 
534         let mut values_vec = vec![0; max(params.len(), my_ty.results().len())];
535 
536         // Store the argument values into `values_vec`.
537         let param_tys = my_ty.params().iter();
538         for ((arg, slot), ty) in params.iter().zip(&mut values_vec).zip(param_tys) {
539             if arg.ty() != *ty {
540                 bail!(
541                     "argument type mismatch: found {} but expected {}",
542                     arg.ty(),
543                     ty
544                 );
545             }
546             if !arg.comes_from_same_store(&self.instance.store) {
547                 bail!("cross-`Store` values are not currently supported");
548             }
549             unsafe {
550                 arg.write_value_to(slot);
551             }
552         }
553 
554         // Call the trampoline.
555         catch_traps(self.export.vmctx, &self.instance.store, || unsafe {
556             (self.trampoline)(
557                 self.export.vmctx,
558                 ptr::null_mut(),
559                 self.export.address,
560                 values_vec.as_mut_ptr(),
561             )
562         })?;
563 
564         // Load the return values out of `values_vec`.
565         let mut results = Vec::with_capacity(my_ty.results().len());
566         for (index, ty) in my_ty.results().iter().enumerate() {
567             unsafe {
568                 let ptr = values_vec.as_ptr().add(index);
569                 results.push(Val::read_value_from(&self.instance.store, ptr, ty));
570             }
571         }
572 
573         Ok(results.into())
574     }
575 
wasmtime_function(&self) -> &wasmtime_runtime::ExportFunction576     pub(crate) fn wasmtime_function(&self) -> &wasmtime_runtime::ExportFunction {
577         &self.export
578     }
579 
from_wasmtime_function( export: wasmtime_runtime::ExportFunction, instance: StoreInstanceHandle, ) -> Self580     pub(crate) fn from_wasmtime_function(
581         export: wasmtime_runtime::ExportFunction,
582         instance: StoreInstanceHandle,
583     ) -> Self {
584         // Each function signature in a module should have a trampoline stored
585         // on that module as well, so unwrap the result here since otherwise
586         // it's a bug in wasmtime.
587         let trampoline = instance
588             .trampoline(export.signature)
589             .expect("failed to retrieve trampoline from module");
590 
591         Func {
592             instance,
593             export,
594             trampoline,
595         }
596     }
597 
598     getters! {
599         /// Extracts a natively-callable object from this `Func`, if the
600         /// signature matches.
601         ///
602         /// See the [`Func::get1`] method for more documentation.
603         (get0)
604 
605         /// Extracts a natively-callable object from this `Func`, if the
606         /// signature matches.
607         ///
608         /// This function serves as an optimized version of the [`Func::call`]
609         /// method if the type signature of a function is statically known to
610         /// the program. This method is faster than `call` on a few metrics:
611         ///
612         /// * Runtime type-checking only happens once, when this method is
613         ///   called.
614         /// * The result values, if any, aren't boxed into a vector.
615         /// * Arguments and return values don't go through boxing and unboxing.
616         /// * No trampolines are used to transfer control flow to/from JIT code,
617         ///   instead this function jumps directly into JIT code.
618         ///
619         /// For more information about which Rust types match up to which wasm
620         /// types, see the documentation on [`Func::wrap`].
621         ///
622         /// # Return
623         ///
624         /// This function will return `None` if the type signature asserted
625         /// statically does not match the runtime type signature. `Some`,
626         /// however, will be returned if the underlying function takes one
627         /// parameter of type `A` and returns the parameter `R`. Currently `R`
628         /// can either be `()` (no return values) or one wasm type. At this time
629         /// a multi-value return isn't supported.
630         ///
631         /// The returned closure will always return a `Result<R, Trap>` and an
632         /// `Err` is returned if a trap happens while the wasm is executing.
633         (get1, A1)
634 
635         /// Extracts a natively-callable object from this `Func`, if the
636         /// signature matches.
637         ///
638         /// See the [`Func::get1`] method for more documentation.
639         (get2, A1, A2)
640 
641         /// Extracts a natively-callable object from this `Func`, if the
642         /// signature matches.
643         ///
644         /// See the [`Func::get1`] method for more documentation.
645         (get3, A1, A2, A3)
646 
647         /// Extracts a natively-callable object from this `Func`, if the
648         /// signature matches.
649         ///
650         /// See the [`Func::get1`] method for more documentation.
651         (get4, A1, A2, A3, A4)
652 
653         /// Extracts a natively-callable object from this `Func`, if the
654         /// signature matches.
655         ///
656         /// See the [`Func::get1`] method for more documentation.
657         (get5, A1, A2, A3, A4, A5)
658 
659         /// Extracts a natively-callable object from this `Func`, if the
660         /// signature matches.
661         ///
662         /// See the [`Func::get1`] method for more documentation.
663         (get6, A1, A2, A3, A4, A5, A6)
664 
665         /// Extracts a natively-callable object from this `Func`, if the
666         /// signature matches.
667         ///
668         /// See the [`Func::get1`] method for more documentation.
669         (get7, A1, A2, A3, A4, A5, A6, A7)
670 
671         /// Extracts a natively-callable object from this `Func`, if the
672         /// signature matches.
673         ///
674         /// See the [`Func::get1`] method for more documentation.
675         (get8, A1, A2, A3, A4, A5, A6, A7, A8)
676 
677         /// Extracts a natively-callable object from this `Func`, if the
678         /// signature matches.
679         ///
680         /// See the [`Func::get1`] method for more documentation.
681         (get9, A1, A2, A3, A4, A5, A6, A7, A8, A9)
682 
683         /// Extracts a natively-callable object from this `Func`, if the
684         /// signature matches.
685         ///
686         /// See the [`Func::get1`] method for more documentation.
687         (get10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)
688 
689         /// Extracts a natively-callable object from this `Func`, if the
690         /// signature matches.
691         ///
692         /// See the [`Func::get1`] method for more documentation.
693         (get11, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)
694 
695         /// Extracts a natively-callable object from this `Func`, if the
696         /// signature matches.
697         ///
698         /// See the [`Func::get1`] method for more documentation.
699         (get12, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
700 
701         /// Extracts a natively-callable object from this `Func`, if the
702         /// signature matches.
703         ///
704         /// See the [`Func::get1`] method for more documentation.
705         (get13, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)
706 
707         /// Extracts a natively-callable object from this `Func`, if the
708         /// signature matches.
709         ///
710         /// See the [`Func::get1`] method for more documentation.
711         (get14, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)
712 
713         /// Extracts a natively-callable object from this `Func`, if the
714         /// signature matches.
715         ///
716         /// See the [`Func::get1`] method for more documentation.
717         (get15, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)
718     }
719 
720     /// Get a reference to this function's store.
store(&self) -> &Store721     pub fn store(&self) -> &Store {
722         &self.instance.store
723     }
724 }
725 
726 impl fmt::Debug for Func {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result727     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
728         write!(f, "Func")
729     }
730 }
731 
catch_traps( vmctx: *mut VMContext, store: &Store, closure: impl FnMut(), ) -> Result<(), Trap>732 pub(crate) fn catch_traps(
733     vmctx: *mut VMContext,
734     store: &Store,
735     closure: impl FnMut(),
736 ) -> Result<(), Trap> {
737     let signalhandler = store.signal_handler();
738     unsafe {
739         wasmtime_runtime::catch_traps(
740             vmctx,
741             store.engine().config().max_wasm_stack,
742             |addr| store.is_in_jit_code(addr),
743             signalhandler.as_deref(),
744             closure,
745         )
746         .map_err(Trap::from_runtime)
747     }
748 }
749 
750 /// A trait implemented for types which can be arguments to closures passed to
751 /// [`Func::wrap`] and friends.
752 ///
753 /// This trait should not be implemented by user types. This trait may change at
754 /// any time internally. The types which implement this trait, however, are
755 /// stable over time.
756 ///
757 /// For more information see [`Func::wrap`]
758 pub unsafe trait WasmTy: Copy {
759     #[doc(hidden)]
push(dst: &mut Vec<ValType>)760     fn push(dst: &mut Vec<ValType>);
761     #[doc(hidden)]
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>762     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>;
763     #[doc(hidden)]
load(ptr: &mut *const u128) -> Self764     unsafe fn load(ptr: &mut *const u128) -> Self;
765     #[doc(hidden)]
store(abi: Self, ptr: *mut u128)766     unsafe fn store(abi: Self, ptr: *mut u128);
767 }
768 
769 unsafe impl WasmTy for () {
push(_dst: &mut Vec<ValType>)770     fn push(_dst: &mut Vec<ValType>) {}
matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>771     fn matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
772         Ok(())
773     }
774     #[inline]
load(_ptr: &mut *const u128) -> Self775     unsafe fn load(_ptr: &mut *const u128) -> Self {}
776     #[inline]
store(_abi: Self, _ptr: *mut u128)777     unsafe fn store(_abi: Self, _ptr: *mut u128) {}
778 }
779 
780 unsafe impl WasmTy for i32 {
push(dst: &mut Vec<ValType>)781     fn push(dst: &mut Vec<ValType>) {
782         dst.push(ValType::I32);
783     }
matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>784     fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
785         let next = tys.next();
786         ensure!(
787             next == Some(ValType::I32),
788             "Type mismatch, expected i32, got {:?}",
789             next
790         );
791         Ok(())
792     }
793     #[inline]
load(ptr: &mut *const u128) -> Self794     unsafe fn load(ptr: &mut *const u128) -> Self {
795         let ret = **ptr as Self;
796         *ptr = (*ptr).add(1);
797         return ret;
798     }
799     #[inline]
store(abi: Self, ptr: *mut u128)800     unsafe fn store(abi: Self, ptr: *mut u128) {
801         *ptr = abi as u128;
802     }
803 }
804 
805 unsafe impl WasmTy for u32 {
push(dst: &mut Vec<ValType>)806     fn push(dst: &mut Vec<ValType>) {
807         <i32 as WasmTy>::push(dst)
808     }
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>809     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
810         <i32 as WasmTy>::matches(tys)
811     }
812     #[inline]
load(ptr: &mut *const u128) -> Self813     unsafe fn load(ptr: &mut *const u128) -> Self {
814         <i32 as WasmTy>::load(ptr) as Self
815     }
816     #[inline]
store(abi: Self, ptr: *mut u128)817     unsafe fn store(abi: Self, ptr: *mut u128) {
818         <i32 as WasmTy>::store(abi as i32, ptr)
819     }
820 }
821 
822 unsafe impl WasmTy for i64 {
push(dst: &mut Vec<ValType>)823     fn push(dst: &mut Vec<ValType>) {
824         dst.push(ValType::I64);
825     }
matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>826     fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
827         let next = tys.next();
828         ensure!(
829             next == Some(ValType::I64),
830             "Type mismatch, expected i64, got {:?}",
831             next
832         );
833         Ok(())
834     }
835     #[inline]
load(ptr: &mut *const u128) -> Self836     unsafe fn load(ptr: &mut *const u128) -> Self {
837         let ret = **ptr as Self;
838         *ptr = (*ptr).add(1);
839         return ret;
840     }
841     #[inline]
store(abi: Self, ptr: *mut u128)842     unsafe fn store(abi: Self, ptr: *mut u128) {
843         *ptr = abi as u128;
844     }
845 }
846 
847 unsafe impl WasmTy for u64 {
push(dst: &mut Vec<ValType>)848     fn push(dst: &mut Vec<ValType>) {
849         <i64 as WasmTy>::push(dst)
850     }
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>851     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
852         <i64 as WasmTy>::matches(tys)
853     }
854     #[inline]
load(ptr: &mut *const u128) -> Self855     unsafe fn load(ptr: &mut *const u128) -> Self {
856         <i64 as WasmTy>::load(ptr) as Self
857     }
858     #[inline]
store(abi: Self, ptr: *mut u128)859     unsafe fn store(abi: Self, ptr: *mut u128) {
860         <i64 as WasmTy>::store(abi as i64, ptr)
861     }
862 }
863 
864 unsafe impl WasmTy for f32 {
push(dst: &mut Vec<ValType>)865     fn push(dst: &mut Vec<ValType>) {
866         dst.push(ValType::F32);
867     }
matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>868     fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
869         let next = tys.next();
870         ensure!(
871             next == Some(ValType::F32),
872             "Type mismatch, expected f32, got {:?}",
873             next
874         );
875         Ok(())
876     }
877     #[inline]
load(ptr: &mut *const u128) -> Self878     unsafe fn load(ptr: &mut *const u128) -> Self {
879         let ret = f32::from_bits(**ptr as u32);
880         *ptr = (*ptr).add(1);
881         return ret;
882     }
883     #[inline]
store(abi: Self, ptr: *mut u128)884     unsafe fn store(abi: Self, ptr: *mut u128) {
885         *ptr = abi.to_bits() as u128;
886     }
887 }
888 
889 unsafe impl WasmTy for f64 {
push(dst: &mut Vec<ValType>)890     fn push(dst: &mut Vec<ValType>) {
891         dst.push(ValType::F64);
892     }
matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>893     fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
894         let next = tys.next();
895         ensure!(
896             next == Some(ValType::F64),
897             "Type mismatch, expected f64, got {:?}",
898             next
899         );
900         Ok(())
901     }
902     #[inline]
load(ptr: &mut *const u128) -> Self903     unsafe fn load(ptr: &mut *const u128) -> Self {
904         let ret = f64::from_bits(**ptr as u64);
905         *ptr = (*ptr).add(1);
906         return ret;
907     }
908     #[inline]
store(abi: Self, ptr: *mut u128)909     unsafe fn store(abi: Self, ptr: *mut u128) {
910         *ptr = abi.to_bits() as u128;
911     }
912 }
913 
914 /// A trait implemented for types which can be returned from closures passed to
915 /// [`Func::wrap`] and friends.
916 ///
917 /// This trait should not be implemented by user types. This trait may change at
918 /// any time internally. The types which implement this trait, however, are
919 /// stable over time.
920 ///
921 /// For more information see [`Func::wrap`]
922 pub unsafe trait WasmRet {
923     #[doc(hidden)]
924     type Abi;
925     #[doc(hidden)]
push(dst: &mut Vec<ValType>)926     fn push(dst: &mut Vec<ValType>);
927     #[doc(hidden)]
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>928     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>;
929     #[doc(hidden)]
into_abi(self) -> Self::Abi930     fn into_abi(self) -> Self::Abi;
931     #[doc(hidden)]
store(abi: Self::Abi, ptr: *mut u128)932     unsafe fn store(abi: Self::Abi, ptr: *mut u128);
933 }
934 
935 unsafe impl<T: WasmTy> WasmRet for T {
936     type Abi = T;
push(dst: &mut Vec<ValType>)937     fn push(dst: &mut Vec<ValType>) {
938         T::push(dst)
939     }
940 
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>941     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
942         T::matches(tys)
943     }
944 
945     #[inline]
into_abi(self) -> Self::Abi946     fn into_abi(self) -> Self::Abi {
947         self
948     }
949 
950     #[inline]
store(abi: Self::Abi, ptr: *mut u128)951     unsafe fn store(abi: Self::Abi, ptr: *mut u128) {
952         T::store(abi, ptr);
953     }
954 }
955 
956 unsafe impl<T: WasmTy> WasmRet for Result<T, Trap> {
957     type Abi = T;
push(dst: &mut Vec<ValType>)958     fn push(dst: &mut Vec<ValType>) {
959         T::push(dst)
960     }
961 
matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>962     fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
963         T::matches(tys)
964     }
965 
966     #[inline]
into_abi(self) -> Self::Abi967     fn into_abi(self) -> Self::Abi {
968         match self {
969             Ok(val) => return T::into_abi(val),
970             Err(trap) => handle_trap(trap),
971         }
972 
973         fn handle_trap(trap: Trap) -> ! {
974             unsafe { raise_user_trap(trap.into()) }
975         }
976     }
977 
978     #[inline]
store(abi: Self::Abi, ptr: *mut u128)979     unsafe fn store(abi: Self::Abi, ptr: *mut u128) {
980         T::store(abi, ptr);
981     }
982 }
983 
984 /// Internal trait implemented for all arguments that can be passed to
985 /// [`Func::wrap`].
986 ///
987 /// This trait should not be implemented by external users, it's only intended
988 /// as an implementation detail of this crate.
989 pub trait IntoFunc<Params, Results> {
990     #[doc(hidden)]
into_func(self, store: &Store) -> Func991     fn into_func(self, store: &Store) -> Func;
992 }
993 
994 /// A structure representing the *caller's* context when creating a function
995 /// via [`Func::wrap`].
996 ///
997 /// This structure can be taken as the first parameter of a closure passed to
998 /// [`Func::wrap`], and it can be used to learn information about the caller of
999 /// the function, such as the calling module's memory, exports, etc.
1000 ///
1001 /// The primary purpose of this structure is to provide access to the
1002 /// caller's information, such as it's exported memory. This allows
1003 /// functions which take pointers as arguments to easily read the memory the
1004 /// pointers point into.
1005 ///
1006 /// Note that this is intended to be a pretty temporary mechanism for accessing
1007 /// the caller's memory until interface types has been fully standardized and
1008 /// implemented.
1009 pub struct Caller<'a> {
1010     // Note that this is a `Weak` pointer instead of a `&'a Store`,
1011     // intentionally so. This allows us to break an `Rc` cycle which would
1012     // otherwise look like this:
1013     //
1014     // * A `Store` object ...
1015     // * ... owns all `InstanceHandle` objects ...
1016     // * ... which are created in `Func::wrap` with custom host data ...
1017     // * ... where the custom host data needs to point to `Store` to be stored
1018     //   here
1019     //
1020     // This `Rc` cycle means that we would never actually reclaim any memory or
1021     // deallocate any instances. To break this cycle we use a weak pointer here
1022     // which points back to `Store`. A `Caller` should only ever be usable
1023     // when the original `Store` is alive, however, so this should always be an
1024     // upgrade-able pointer. Alternative solutions or other ideas to break this
1025     // cycle would be most welcome!
1026     store: &'a Weak<StoreInner>,
1027     caller_vmctx: *mut VMContext,
1028 }
1029 
1030 impl Caller<'_> {
1031     /// Looks up an export from the caller's module by the `name` given.
1032     ///
1033     /// Note that this function is only implemented for the `Extern::Memory`
1034     /// type currently. No other exported structure can be acquired through this
1035     /// just yet, but this may be implemented in the future!
1036     ///
1037     /// # Return
1038     ///
1039     /// If a memory export with the `name` provided was found, then it is
1040     /// returned as a `Memory`. There are a number of situations, however, where
1041     /// the memory may not be available:
1042     ///
1043     /// * The caller instance may not have an export named `name`
1044     /// * The export named `name` may not be an exported memory
1045     /// * There may not be a caller available, for example if `Func` was called
1046     ///   directly from host code.
1047     ///
1048     /// It's recommended to take care when calling this API and gracefully
1049     /// handling a `None` return value.
get_export(&self, name: &str) -> Option<Extern>1050     pub fn get_export(&self, name: &str) -> Option<Extern> {
1051         unsafe {
1052             if self.caller_vmctx.is_null() {
1053                 return None;
1054             }
1055             let instance = InstanceHandle::from_vmctx(self.caller_vmctx);
1056             let export = match instance.lookup(name) {
1057                 Some(Export::Memory(m)) => m,
1058                 _ => return None,
1059             };
1060             // Our `Weak` pointer is used only to break a cycle where `Store`
1061             // stores instance handles which have this weak pointer as their
1062             // custom host data. This function should only be invoke-able while
1063             // the `Store` is active, so this upgrade should always succeed.
1064             debug_assert!(self.store.upgrade().is_some());
1065             let handle =
1066                 Store::from_inner(self.store.upgrade()?).existing_instance_handle(instance);
1067             let mem = Memory::from_wasmtime_memory(export, handle);
1068             Some(Extern::Memory(mem))
1069         }
1070     }
1071 
1072     /// Get a handle to this caller's store.
store(&self) -> Store1073     pub fn store(&self) -> Store {
1074         // See comment above the `store` member for why this unwrap is OK.
1075         Store::upgrade(&self.store).unwrap()
1076     }
1077 }
1078 
1079 macro_rules! impl_into_func {
1080     ($(
1081         ($($args:ident)*)
1082     )*) => ($(
1083         // Implement for functions without a leading `&Caller` parameter,
1084         // delegating to the implementation below which does have the leading
1085         // `Caller` parameter.
1086         impl<F, $($args,)* R> IntoFunc<($($args,)*), R> for F
1087         where
1088             F: Fn($($args),*) -> R + 'static,
1089             $($args: WasmTy,)*
1090             R: WasmRet,
1091         {
1092             #[allow(non_snake_case)]
1093             fn into_func(self, store: &Store) -> Func {
1094                 Func::wrap(store, move |_: Caller<'_>, $($args:$args),*| {
1095                     self($($args),*)
1096                 })
1097             }
1098         }
1099 
1100         #[allow(non_snake_case)]
1101         impl<F, $($args,)* R> IntoFunc<(Caller<'_>, $($args,)*), R> for F
1102         where
1103             F: Fn(Caller<'_>, $($args),*) -> R + 'static,
1104             $($args: WasmTy,)*
1105             R: WasmRet,
1106         {
1107             fn into_func(self, store: &Store) -> Func {
1108                 // Note that this shim's ABI must match that expected by
1109                 // cranelift, since cranelift is generating raw function calls
1110                 // directly to this function.
1111                 unsafe extern "C" fn shim<F, $($args,)* R>(
1112                     vmctx: *mut VMContext,
1113                     caller_vmctx: *mut VMContext,
1114                     $($args: $args,)*
1115                 ) -> R::Abi
1116                 where
1117                     F: Fn(Caller<'_>, $($args),*) -> R + 'static,
1118                     $($args: WasmTy,)*
1119                     R: WasmRet,
1120                 {
1121                     let ret = {
1122                         let state = (*vmctx).host_state();
1123                         // Double-check ourselves in debug mode, but we control
1124                         // the `Any` here so an unsafe downcast should also
1125                         // work.
1126                         debug_assert!(state.is::<(F, Weak<StoreInner>)>());
1127                         let (func, store) = &*(state as *const _ as *const (F, Weak<StoreInner>));
1128                         panic::catch_unwind(AssertUnwindSafe(|| {
1129                             func(
1130                                 Caller { store, caller_vmctx },
1131                                 $($args,)*
1132                             )
1133                         }))
1134                     };
1135                     match ret {
1136                         Ok(ret) => ret.into_abi(),
1137                         Err(panic) => wasmtime_runtime::resume_panic(panic),
1138                     }
1139                 }
1140 
1141                 unsafe extern "C" fn trampoline<$($args,)* R>(
1142                     callee_vmctx: *mut VMContext,
1143                     caller_vmctx: *mut VMContext,
1144                     ptr: *const VMFunctionBody,
1145                     args: *mut u128,
1146                 )
1147                 where
1148                     $($args: WasmTy,)*
1149                     R: WasmRet,
1150                 {
1151                     let ptr = mem::transmute::<
1152                         *const VMFunctionBody,
1153                         unsafe extern "C" fn(
1154                             *mut VMContext,
1155                             *mut VMContext,
1156                             $($args,)*
1157                         ) -> R::Abi,
1158                     >(ptr);
1159 
1160                     let mut _next = args as *const u128;
1161                     $(let $args = $args::load(&mut _next);)*
1162                     let ret = ptr(callee_vmctx, caller_vmctx, $($args),*);
1163                     R::store(ret, args);
1164                 }
1165 
1166                 let mut _args = Vec::new();
1167                 $($args::push(&mut _args);)*
1168                 let mut ret = Vec::new();
1169                 R::push(&mut ret);
1170                 let ty = FuncType::new(_args.into(), ret.into());
1171                 let store_weak = store.weak();
1172                 let trampoline = trampoline::<$($args,)* R>;
1173                 let (instance, export) = unsafe {
1174                     crate::trampoline::generate_raw_func_export(
1175                         &ty,
1176                         std::slice::from_raw_parts_mut(
1177                             shim::<F, $($args,)* R> as *mut _,
1178                             0,
1179                         ),
1180                         trampoline,
1181                         store,
1182                         Box::new((self, store_weak)),
1183                     )
1184                     .expect("failed to generate export")
1185                 };
1186                 Func {
1187                     instance,
1188                     export,
1189                     trampoline,
1190                 }
1191             }
1192         }
1193     )*)
1194 }
1195 
1196 impl_into_func! {
1197     ()
1198     (A1)
1199     (A1 A2)
1200     (A1 A2 A3)
1201     (A1 A2 A3 A4)
1202     (A1 A2 A3 A4 A5)
1203     (A1 A2 A3 A4 A5 A6)
1204     (A1 A2 A3 A4 A5 A6 A7)
1205     (A1 A2 A3 A4 A5 A6 A7 A8)
1206     (A1 A2 A3 A4 A5 A6 A7 A8 A9)
1207     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
1208     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
1209     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
1210     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
1211     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
1212     (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
1213 }
1214 
1215 #[test]
wasm_ty_roundtrip() -> Result<(), anyhow::Error>1216 fn wasm_ty_roundtrip() -> Result<(), anyhow::Error> {
1217     use crate::*;
1218     let store = Store::default();
1219     let debug = Func::wrap(&store, |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
1220         assert_eq!(a, -1);
1221         assert_eq!(b, 1);
1222         assert_eq!(c, 2.0);
1223         assert_eq!(d, -3);
1224         assert_eq!(e, 3);
1225         assert_eq!(f, 4.0);
1226     });
1227     let module = Module::new(
1228         store.engine(),
1229         r#"
1230              (module
1231                  (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
1232                  (func (export "foo") (param i32 i32 f32 i64 i64 f64)
1233                     (if (i32.ne (local.get 0) (i32.const -1))
1234                         (then unreachable)
1235                     )
1236                     (if (i32.ne (local.get 1) (i32.const 1))
1237                         (then unreachable)
1238                     )
1239                     (if (f32.ne (local.get 2) (f32.const 2))
1240                         (then unreachable)
1241                     )
1242                     (if (i64.ne (local.get 3) (i64.const -3))
1243                         (then unreachable)
1244                     )
1245                     (if (i64.ne (local.get 4) (i64.const 3))
1246                         (then unreachable)
1247                     )
1248                     (if (f64.ne (local.get 5) (f64.const 4))
1249                         (then unreachable)
1250                     )
1251                     local.get 0
1252                     local.get 1
1253                     local.get 2
1254                     local.get 3
1255                     local.get 4
1256                     local.get 5
1257                     call $debug
1258                 )
1259             )
1260          "#,
1261     )?;
1262     let instance = Instance::new(&store, &module, &[debug.into()])?;
1263     let foo = instance
1264         .get_func("foo")
1265         .unwrap()
1266         .get6::<i32, u32, f32, i64, u64, f64, ()>()?;
1267     foo(-1, 1, 2.0, -3, 3, 4.0)?;
1268     Ok(())
1269 }
1270