substrate_wasmtime/
func.rs

1use crate::runtime::StoreInner;
2use crate::trampoline::StoreInstanceHandle;
3use crate::{Extern, ExternRef, FuncType, Memory, Store, Trap, Val, ValType};
4use anyhow::{bail, ensure, Context as _, Result};
5use smallvec::{smallvec, SmallVec};
6use std::cmp::max;
7use std::fmt;
8use std::mem;
9use std::panic::{self, AssertUnwindSafe};
10use std::ptr::{self, NonNull};
11use std::rc::Weak;
12use wasmtime_runtime::{
13    raise_user_trap, Export, InstanceHandle, VMContext, VMFunctionBody, VMSharedSignatureIndex,
14    VMTrampoline,
15};
16
17/// A WebAssembly function which can be called.
18///
19/// This type can represent a number of callable items, such as:
20///
21/// * An exported function from a WebAssembly module.
22/// * A user-defined function used to satisfy an import.
23///
24/// These types of callable items are all wrapped up in this `Func` and can be
25/// used to both instantiate an [`Instance`] as well as be extracted from an
26/// [`Instance`].
27///
28/// [`Instance`]: crate::Instance
29///
30/// # `Func` and `Clone`
31///
32/// Functions are internally reference counted so you can `clone` a `Func`. The
33/// cloning process only performs a shallow clone, so two cloned `Func`
34/// instances are equivalent in their functionality.
35///
36/// # Examples
37///
38/// One way to get a `Func` is from an [`Instance`] after you've instantiated
39/// it:
40///
41/// ```
42/// # use wasmtime::*;
43/// # fn main() -> anyhow::Result<()> {
44/// let engine = Engine::default();
45/// let store = Store::new(&engine);
46/// let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?;
47/// let instance = Instance::new(&store, &module, &[])?;
48/// let foo = instance.get_func("foo").expect("export wasn't a function");
49///
50/// // Work with `foo` as a `Func` at this point, such as calling it
51/// // dynamically...
52/// match foo.call(&[]) {
53///     Ok(result) => { /* ... */ }
54///     Err(trap) => {
55///         panic!("execution of `foo` resulted in a wasm trap: {}", trap);
56///     }
57/// }
58/// foo.call(&[])?;
59///
60/// // ... or we can make a static assertion about its signature and call it.
61/// // Our first call here can fail if the signatures don't match, and then the
62/// // second call can fail if the function traps (like the `match` above).
63/// let foo = foo.get0::<()>()?;
64/// foo()?;
65/// # Ok(())
66/// # }
67/// ```
68///
69/// You can also use the [`wrap` function](Func::wrap) to create a
70/// `Func`
71///
72/// ```
73/// # use wasmtime::*;
74/// # fn main() -> anyhow::Result<()> {
75/// let store = Store::default();
76///
77/// // Create a custom `Func` which can execute arbitrary code inside of the
78/// // closure.
79/// let add = Func::wrap(&store, |a: i32, b: i32| -> i32 { a + b });
80///
81/// // Next we can hook that up to a wasm module which uses it.
82/// let module = Module::new(
83///     store.engine(),
84///     r#"
85///         (module
86///             (import "" "" (func $add (param i32 i32) (result i32)))
87///             (func (export "call_add_twice") (result i32)
88///                 i32.const 1
89///                 i32.const 2
90///                 call $add
91///                 i32.const 3
92///                 i32.const 4
93///                 call $add
94///                 i32.add))
95///     "#,
96/// )?;
97/// let instance = Instance::new(&store, &module, &[add.into()])?;
98/// let call_add_twice = instance.get_func("call_add_twice").expect("export wasn't a function");
99/// let call_add_twice = call_add_twice.get0::<i32>()?;
100///
101/// assert_eq!(call_add_twice()?, 10);
102/// # Ok(())
103/// # }
104/// ```
105///
106/// Or you could also create an entirely dynamic `Func`!
107///
108/// ```
109/// # use wasmtime::*;
110/// # fn main() -> anyhow::Result<()> {
111/// let store = Store::default();
112///
113/// // Here we need to define the type signature of our `Double` function and
114/// // then wrap it up in a `Func`
115/// let double_type = wasmtime::FuncType::new(
116///     Box::new([wasmtime::ValType::I32]),
117///     Box::new([wasmtime::ValType::I32])
118/// );
119/// let double = Func::new(&store, double_type, |_, params, results| {
120///     let mut value = params[0].unwrap_i32();
121///     value *= 2;
122///     results[0] = value.into();
123///     Ok(())
124/// });
125///
126/// let module = Module::new(
127///     store.engine(),
128///     r#"
129///         (module
130///             (import "" "" (func $double (param i32) (result i32)))
131///             (func $start
132///                 i32.const 1
133///                 call $double
134///                 drop)
135///             (start $start))
136///     "#,
137/// )?;
138/// let instance = Instance::new(&store, &module, &[double.into()])?;
139/// // .. work with `instance` if necessary
140/// # Ok(())
141/// # }
142/// ```
143#[derive(Clone)]
144pub struct Func {
145    instance: StoreInstanceHandle,
146    trampoline: VMTrampoline,
147    export: wasmtime_runtime::ExportFunction,
148}
149
150macro_rules! getters {
151    ($(
152        $(#[$doc:meta])*
153        ($name:ident $(,$args:ident)*)
154    )*) => ($(
155        $(#[$doc])*
156        #[allow(non_snake_case)]
157        pub fn $name<$($args,)* R>(&self)
158            -> anyhow::Result<impl Fn($($args,)*) -> Result<R, Trap>>
159        where
160            $($args: WasmTy,)*
161            R: WasmTy,
162        {
163            // Verify all the paramers match the expected parameters, and that
164            // there are no extra parameters...
165            let ty = self.ty();
166            let mut params = ty.params().iter().cloned();
167            let n = 0;
168            $(
169                let n = n + 1;
170                $args::matches(&mut params)
171                    .with_context(|| format!("Type mismatch in argument {}", n))?;
172            )*
173            ensure!(params.next().is_none(), "Type mismatch: too many arguments (expected {})", n);
174
175            // ... then do the same for the results...
176            let mut results = ty.results().iter().cloned();
177            R::matches(&mut results)
178                .context("Type mismatch in return type")?;
179            ensure!(results.next().is_none(), "Type mismatch: too many return values (expected 1)");
180
181            // Pass the instance into the closure so that we keep it live for
182            // the lifetime of the closure. Pass the `anyfunc` in so that we can
183            // call it.
184            let instance = self.instance.clone();
185            let anyfunc = self.export.anyfunc;
186
187            // ... and then once we've passed the typechecks we can hand out our
188            // object since our `transmute` below should be safe!
189            Ok(move |$($args: $args),*| -> Result<R, Trap> {
190                unsafe {
191                    let fnptr = mem::transmute::<
192                        *const VMFunctionBody,
193                        unsafe extern "C" fn(
194                            *mut VMContext,
195                            *mut VMContext,
196                            $( $args::Abi, )*
197                        ) -> R::Abi,
198                    >(anyfunc.as_ref().func_ptr.as_ptr());
199
200                    let mut ret = None;
201
202                    let weak_store = instance.store.weak();
203                    let weak_store = WeakStore(&weak_store);
204
205                    $(
206                        // Because this returned closure is not marked `unsafe`,
207                        // we have to check that incoming values are compatible
208                        // with our store.
209                        if !$args.compatible_with_store(weak_store) {
210                            return Err(Trap::new(
211                                "attempt to pass cross-`Store` value to Wasm as function argument"
212                            ));
213                        }
214
215                        let $args = $args.into_abi_for_arg(weak_store);
216                    )*
217
218                    invoke_wasm_and_catch_traps(anyfunc.as_ref().vmctx, &instance.store, || {
219                        ret = Some(fnptr(
220                            anyfunc.as_ref().vmctx,
221                            ptr::null_mut(),
222                            $( $args, )*
223                        ));
224                    })?;
225
226                    Ok(R::from_abi(ret.unwrap(), weak_store))
227                }
228            })
229        }
230    )*)
231}
232
233impl Func {
234    /// Creates a new `Func` with the given arguments, typically to create a
235    /// user-defined function to pass as an import to a module.
236    ///
237    /// * `store` - a cache of data where information is stored, typically
238    ///   shared with a [`Module`](crate::Module).
239    ///
240    /// * `ty` - the signature of this function, used to indicate what the
241    ///   inputs and outputs are, which must be WebAssembly types.
242    ///
243    /// * `func` - the native code invoked whenever this `Func` will be called.
244    ///   This closure is provided a [`Caller`] as its first argument to learn
245    ///   information about the caller, and then it's passed a list of
246    ///   parameters as a slice along with a mutable slice of where to write
247    ///   results.
248    ///
249    /// Note that the implementation of `func` must adhere to the `ty`
250    /// signature given, error or traps may occur if it does not respect the
251    /// `ty` signature.
252    ///
253    /// Additionally note that this is quite a dynamic function since signatures
254    /// are not statically known. For a more performant `Func` it's recommended
255    /// to use [`Func::wrap`] if you can because with statically known
256    /// signatures the engine can optimize the implementation much more.
257    pub fn new(
258        store: &Store,
259        ty: FuncType,
260        func: impl Fn(Caller<'_>, &[Val], &mut [Val]) -> Result<(), Trap> + 'static,
261    ) -> Self {
262        let store_weak = store.weak();
263        let ty_clone = ty.clone();
264
265        // Create our actual trampoline function which translates from a bunch
266        // of bit patterns on the stack to actual instances of `Val` being
267        // passed to the given function.
268        let func = Box::new(move |caller_vmctx, values_vec: *mut u128| {
269            // We have a dynamic guarantee that `values_vec` has the right
270            // number of arguments and the right types of arguments. As a result
271            // we should be able to safely run through them all and read them.
272            const STACK_ARGS: usize = 4;
273            const STACK_RETURNS: usize = 2;
274            let mut args: SmallVec<[Val; STACK_ARGS]> =
275                SmallVec::with_capacity(ty_clone.params().len());
276            let store = Store::upgrade(&store_weak).unwrap();
277            for (i, ty) in ty_clone.params().iter().enumerate() {
278                unsafe {
279                    let val = Val::read_value_from(&store, values_vec.add(i), ty);
280                    args.push(val);
281                }
282            }
283
284            let mut returns: SmallVec<[Val; STACK_RETURNS]> =
285                smallvec![Val::null(); ty_clone.results().len()];
286
287            func(
288                Caller {
289                    store: &store_weak,
290                    caller_vmctx,
291                },
292                &args,
293                &mut returns,
294            )?;
295
296            // Unlike our arguments we need to dynamically check that the return
297            // values produced are correct. There could be a bug in `func` that
298            // produces the wrong number or wrong types of values, and we need
299            // to catch that here.
300            for (i, (ret, ty)) in returns.into_iter().zip(ty_clone.results()).enumerate() {
301                if ret.ty() != *ty {
302                    return Err(Trap::new(
303                        "function attempted to return an incompatible value",
304                    ));
305                }
306                unsafe {
307                    ret.write_value_to(&store, values_vec.add(i));
308                }
309            }
310            Ok(())
311        });
312        let (instance, export, trampoline) =
313            crate::trampoline::generate_func_export(&ty, func, store).expect("generated func");
314        Func {
315            instance,
316            trampoline,
317            export,
318        }
319    }
320
321    pub(crate) unsafe fn from_caller_checked_anyfunc(
322        store: &Store,
323        anyfunc: *mut wasmtime_runtime::VMCallerCheckedAnyfunc,
324    ) -> Option<Self> {
325        let anyfunc = NonNull::new(anyfunc)?;
326        debug_assert!(
327            anyfunc.as_ref().type_index != wasmtime_runtime::VMSharedSignatureIndex::default()
328        );
329
330        let instance_handle = wasmtime_runtime::InstanceHandle::from_vmctx(anyfunc.as_ref().vmctx);
331        let export = wasmtime_runtime::ExportFunction { anyfunc };
332        let instance = store.existing_instance_handle(instance_handle);
333        let f = Func::from_wasmtime_function(export, instance);
334        Some(f)
335    }
336
337    /// Creates a new `Func` from the given Rust closure.
338    ///
339    /// This function will create a new `Func` which, when called, will
340    /// execute the given Rust closure. Unlike [`Func::new`] the target
341    /// function being called is known statically so the type signature can
342    /// be inferred. Rust types will map to WebAssembly types as follows:
343    ///
344    /// | Rust Argument Type  | WebAssembly Type |
345    /// |---------------------|------------------|
346    /// | `i32`               | `i32`            |
347    /// | `u32`               | `i32`            |
348    /// | `i64`               | `i64`            |
349    /// | `u64`               | `i64`            |
350    /// | `f32`               | `f32`            |
351    /// | `f64`               | `f64`            |
352    /// | (not supported)     | `v128`           |
353    /// | `Option<Func>`      | `funcref`        |
354    /// | `Option<ExternRef>` | `externref`      |
355    ///
356    /// Any of the Rust types can be returned from the closure as well, in
357    /// addition to some extra types
358    ///
359    /// | Rust Return Type  | WebAssembly Return Type | Meaning           |
360    /// |-------------------|-------------------------|-------------------|
361    /// | `()`              | nothing                 | no return value   |
362    /// | `Result<T, Trap>` | `T`                     | function may trap |
363    ///
364    /// At this time multi-value returns are not supported, and supporting this
365    /// is the subject of [#1178].
366    ///
367    /// [#1178]: https://github.com/bytecodealliance/wasmtime/issues/1178
368    ///
369    /// Finally you can also optionally take [`Caller`] as the first argument of
370    /// your closure. If inserted then you're able to inspect the caller's
371    /// state, for example the [`Memory`] it has exported so you can read what
372    /// pointers point to.
373    ///
374    /// Note that when using this API, the intention is to create as thin of a
375    /// layer as possible for when WebAssembly calls the function provided. With
376    /// sufficient inlining and optimization the WebAssembly will call straight
377    /// into `func` provided, with no extra fluff entailed.
378    ///
379    /// # Examples
380    ///
381    /// First up we can see how simple wasm imports can be implemented, such
382    /// as a function that adds its two arguments and returns the result.
383    ///
384    /// ```
385    /// # use wasmtime::*;
386    /// # fn main() -> anyhow::Result<()> {
387    /// # let store = Store::default();
388    /// let add = Func::wrap(&store, |a: i32, b: i32| a + b);
389    /// let module = Module::new(
390    ///     store.engine(),
391    ///     r#"
392    ///         (module
393    ///             (import "" "" (func $add (param i32 i32) (result i32)))
394    ///             (func (export "foo") (param i32 i32) (result i32)
395    ///                 local.get 0
396    ///                 local.get 1
397    ///                 call $add))
398    ///     "#,
399    /// )?;
400    /// let instance = Instance::new(&store, &module, &[add.into()])?;
401    /// let foo = instance.get_func("foo").unwrap().get2::<i32, i32, i32>()?;
402    /// assert_eq!(foo(1, 2)?, 3);
403    /// # Ok(())
404    /// # }
405    /// ```
406    ///
407    /// We can also do the same thing, but generate a trap if the addition
408    /// overflows:
409    ///
410    /// ```
411    /// # use wasmtime::*;
412    /// # fn main() -> anyhow::Result<()> {
413    /// # let store = Store::default();
414    /// let add = Func::wrap(&store, |a: i32, b: i32| {
415    ///     match a.checked_add(b) {
416    ///         Some(i) => Ok(i),
417    ///         None => Err(Trap::new("overflow")),
418    ///     }
419    /// });
420    /// let module = Module::new(
421    ///     store.engine(),
422    ///     r#"
423    ///         (module
424    ///             (import "" "" (func $add (param i32 i32) (result i32)))
425    ///             (func (export "foo") (param i32 i32) (result i32)
426    ///                 local.get 0
427    ///                 local.get 1
428    ///                 call $add))
429    ///     "#,
430    /// )?;
431    /// let instance = Instance::new(&store, &module, &[add.into()])?;
432    /// let foo = instance.get_func("foo").unwrap().get2::<i32, i32, i32>()?;
433    /// assert_eq!(foo(1, 2)?, 3);
434    /// assert!(foo(i32::max_value(), 1).is_err());
435    /// # Ok(())
436    /// # }
437    /// ```
438    ///
439    /// And don't forget all the wasm types are supported!
440    ///
441    /// ```
442    /// # use wasmtime::*;
443    /// # fn main() -> anyhow::Result<()> {
444    /// # let store = Store::default();
445    /// let debug = Func::wrap(&store, |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
446    ///
447    ///     println!("a={}", a);
448    ///     println!("b={}", b);
449    ///     println!("c={}", c);
450    ///     println!("d={}", d);
451    ///     println!("e={}", e);
452    ///     println!("f={}", f);
453    /// });
454    /// let module = Module::new(
455    ///     store.engine(),
456    ///     r#"
457    ///         (module
458    ///             (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
459    ///             (func (export "foo")
460    ///                 i32.const -1
461    ///                 i32.const 1
462    ///                 f32.const 2
463    ///                 i64.const -3
464    ///                 i64.const 3
465    ///                 f64.const 4
466    ///                 call $debug))
467    ///     "#,
468    /// )?;
469    /// let instance = Instance::new(&store, &module, &[debug.into()])?;
470    /// let foo = instance.get_func("foo").unwrap().get0::<()>()?;
471    /// foo()?;
472    /// # Ok(())
473    /// # }
474    /// ```
475    ///
476    /// Finally if you want to get really fancy you can also implement
477    /// imports that read/write wasm module's memory
478    ///
479    /// ```
480    /// use std::str;
481    ///
482    /// # use wasmtime::*;
483    /// # fn main() -> anyhow::Result<()> {
484    /// # let store = Store::default();
485    /// let log_str = Func::wrap(&store, |caller: Caller<'_>, ptr: i32, len: i32| {
486    ///     let mem = match caller.get_export("memory") {
487    ///         Some(Extern::Memory(mem)) => mem,
488    ///         _ => return Err(Trap::new("failed to find host memory")),
489    ///     };
490    ///
491    ///     // We're reading raw wasm memory here so we need `unsafe`. Note
492    ///     // though that this should be safe because we don't reenter wasm
493    ///     // while we're reading wasm memory, nor should we clash with
494    ///     // any other memory accessors (assuming they're well-behaved
495    ///     // too).
496    ///     unsafe {
497    ///         let data = mem.data_unchecked()
498    ///             .get(ptr as u32 as usize..)
499    ///             .and_then(|arr| arr.get(..len as u32 as usize));
500    ///         let string = match data {
501    ///             Some(data) => match str::from_utf8(data) {
502    ///                 Ok(s) => s,
503    ///                 Err(_) => return Err(Trap::new("invalid utf-8")),
504    ///             },
505    ///             None => return Err(Trap::new("pointer/length out of bounds")),
506    ///         };
507    ///         assert_eq!(string, "Hello, world!");
508    ///         println!("{}", string);
509    ///     }
510    ///     Ok(())
511    /// });
512    /// let module = Module::new(
513    ///     store.engine(),
514    ///     r#"
515    ///         (module
516    ///             (import "" "" (func $log_str (param i32 i32)))
517    ///             (func (export "foo")
518    ///                 i32.const 4   ;; ptr
519    ///                 i32.const 13  ;; len
520    ///                 call $log_str)
521    ///             (memory (export "memory") 1)
522    ///             (data (i32.const 4) "Hello, world!"))
523    ///     "#,
524    /// )?;
525    /// let instance = Instance::new(&store, &module, &[log_str.into()])?;
526    /// let foo = instance.get_func("foo").unwrap().get0::<()>()?;
527    /// foo()?;
528    /// # Ok(())
529    /// # }
530    /// ```
531    pub fn wrap<Params, Results>(store: &Store, func: impl IntoFunc<Params, Results>) -> Func {
532        func.into_func(store)
533    }
534
535    pub(crate) fn sig_index(&self) -> VMSharedSignatureIndex {
536        unsafe { self.export.anyfunc.as_ref().type_index }
537    }
538
539    /// Returns the underlying wasm type that this `Func` has.
540    pub fn ty(&self) -> FuncType {
541        // Signatures should always be registered in the store's registry of
542        // shared signatures, so we should be able to unwrap safely here.
543        let wft = self.instance.store.lookup_signature(self.sig_index());
544
545        // This is only called with `Export::Function`, and since it's coming
546        // from wasmtime_runtime itself we should support all the types coming
547        // out of it, so assert such here.
548        FuncType::from_wasm_func_type(&wft)
549    }
550
551    /// Returns the number of parameters that this function takes.
552    pub fn param_arity(&self) -> usize {
553        let sig = self
554            .instance
555            .store
556            .lookup_signature(unsafe { self.export.anyfunc.as_ref().type_index });
557        sig.params.len()
558    }
559
560    /// Returns the number of results this function produces.
561    pub fn result_arity(&self) -> usize {
562        let sig = self
563            .instance
564            .store
565            .lookup_signature(unsafe { self.export.anyfunc.as_ref().type_index });
566        sig.returns.len()
567    }
568
569    /// Invokes this function with the `params` given, returning the results and
570    /// any trap, if one occurs.
571    ///
572    /// The `params` here must match the type signature of this `Func`, or a
573    /// trap will occur. If a trap occurs while executing this function, then a
574    /// trap will also be returned.
575    ///
576    /// This function should not panic unless the underlying function itself
577    /// initiates a panic.
578    pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>> {
579        // We need to perform a dynamic check that the arguments given to us
580        // match the signature of this function and are appropriate to pass to
581        // this function. This involves checking to make sure we have the right
582        // number and types of arguments as well as making sure everything is
583        // from the same `Store`.
584        let my_ty = self.ty();
585        if my_ty.params().len() != params.len() {
586            bail!(
587                "expected {} arguments, got {}",
588                my_ty.params().len(),
589                params.len()
590            );
591        }
592
593        let mut values_vec = vec![0; max(params.len(), my_ty.results().len())];
594
595        // Store the argument values into `values_vec`.
596        let param_tys = my_ty.params().iter();
597        for ((arg, slot), ty) in params.iter().cloned().zip(&mut values_vec).zip(param_tys) {
598            if arg.ty() != *ty {
599                bail!(
600                    "argument type mismatch: found {} but expected {}",
601                    arg.ty(),
602                    ty
603                );
604            }
605            if !arg.comes_from_same_store(&self.instance.store) {
606                bail!("cross-`Store` values are not currently supported");
607            }
608            unsafe {
609                arg.write_value_to(&self.instance.store, slot);
610            }
611        }
612
613        // Call the trampoline.
614        unsafe {
615            let anyfunc = self.export.anyfunc.as_ref();
616            invoke_wasm_and_catch_traps(anyfunc.vmctx, &self.instance.store, || {
617                (self.trampoline)(
618                    anyfunc.vmctx,
619                    ptr::null_mut(),
620                    anyfunc.func_ptr.as_ptr(),
621                    values_vec.as_mut_ptr(),
622                )
623            })?;
624        }
625
626        // Load the return values out of `values_vec`.
627        let mut results = Vec::with_capacity(my_ty.results().len());
628        for (index, ty) in my_ty.results().iter().enumerate() {
629            unsafe {
630                let ptr = values_vec.as_ptr().add(index);
631                results.push(Val::read_value_from(&self.instance.store, ptr, ty));
632            }
633        }
634
635        Ok(results.into())
636    }
637
638    pub(crate) fn wasmtime_function(&self) -> &wasmtime_runtime::ExportFunction {
639        &self.export
640    }
641
642    pub(crate) fn caller_checked_anyfunc(
643        &self,
644    ) -> NonNull<wasmtime_runtime::VMCallerCheckedAnyfunc> {
645        self.export.anyfunc
646    }
647
648    pub(crate) fn from_wasmtime_function(
649        export: wasmtime_runtime::ExportFunction,
650        instance: StoreInstanceHandle,
651    ) -> Self {
652        // Each function signature in a module should have a trampoline stored
653        // on that module as well, so unwrap the result here since otherwise
654        // it's a bug in wasmtime.
655        let trampoline = instance
656            .trampoline(unsafe { export.anyfunc.as_ref().type_index })
657            .expect("failed to retrieve trampoline from module");
658
659        Func {
660            instance,
661            export,
662            trampoline,
663        }
664    }
665
666    getters! {
667        /// Extracts a natively-callable object from this `Func`, if the
668        /// signature matches.
669        ///
670        /// See the [`Func::get1`] method for more documentation.
671        (get0)
672
673        /// Extracts a natively-callable object from this `Func`, if the
674        /// signature matches.
675        ///
676        /// This function serves as an optimized version of the [`Func::call`]
677        /// method if the type signature of a function is statically known to
678        /// the program. This method is faster than `call` on a few metrics:
679        ///
680        /// * Runtime type-checking only happens once, when this method is
681        ///   called.
682        /// * The result values, if any, aren't boxed into a vector.
683        /// * Arguments and return values don't go through boxing and unboxing.
684        /// * No trampolines are used to transfer control flow to/from JIT code,
685        ///   instead this function jumps directly into JIT code.
686        ///
687        /// For more information about which Rust types match up to which wasm
688        /// types, see the documentation on [`Func::wrap`].
689        ///
690        /// # Return
691        ///
692        /// This function will return `None` if the type signature asserted
693        /// statically does not match the runtime type signature. `Some`,
694        /// however, will be returned if the underlying function takes one
695        /// parameter of type `A` and returns the parameter `R`. Currently `R`
696        /// can either be `()` (no return values) or one wasm type. At this time
697        /// a multi-value return isn't supported.
698        ///
699        /// The returned closure will always return a `Result<R, Trap>` and an
700        /// `Err` is returned if a trap happens while the wasm is executing.
701        (get1, A1)
702
703        /// Extracts a natively-callable object from this `Func`, if the
704        /// signature matches.
705        ///
706        /// See the [`Func::get1`] method for more documentation.
707        (get2, A1, A2)
708
709        /// Extracts a natively-callable object from this `Func`, if the
710        /// signature matches.
711        ///
712        /// See the [`Func::get1`] method for more documentation.
713        (get3, A1, A2, A3)
714
715        /// Extracts a natively-callable object from this `Func`, if the
716        /// signature matches.
717        ///
718        /// See the [`Func::get1`] method for more documentation.
719        (get4, A1, A2, A3, A4)
720
721        /// Extracts a natively-callable object from this `Func`, if the
722        /// signature matches.
723        ///
724        /// See the [`Func::get1`] method for more documentation.
725        (get5, A1, A2, A3, A4, A5)
726
727        /// Extracts a natively-callable object from this `Func`, if the
728        /// signature matches.
729        ///
730        /// See the [`Func::get1`] method for more documentation.
731        (get6, A1, A2, A3, A4, A5, A6)
732
733        /// Extracts a natively-callable object from this `Func`, if the
734        /// signature matches.
735        ///
736        /// See the [`Func::get1`] method for more documentation.
737        (get7, A1, A2, A3, A4, A5, A6, A7)
738
739        /// Extracts a natively-callable object from this `Func`, if the
740        /// signature matches.
741        ///
742        /// See the [`Func::get1`] method for more documentation.
743        (get8, A1, A2, A3, A4, A5, A6, A7, A8)
744
745        /// Extracts a natively-callable object from this `Func`, if the
746        /// signature matches.
747        ///
748        /// See the [`Func::get1`] method for more documentation.
749        (get9, A1, A2, A3, A4, A5, A6, A7, A8, A9)
750
751        /// Extracts a natively-callable object from this `Func`, if the
752        /// signature matches.
753        ///
754        /// See the [`Func::get1`] method for more documentation.
755        (get10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)
756
757        /// Extracts a natively-callable object from this `Func`, if the
758        /// signature matches.
759        ///
760        /// See the [`Func::get1`] method for more documentation.
761        (get11, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)
762
763        /// Extracts a natively-callable object from this `Func`, if the
764        /// signature matches.
765        ///
766        /// See the [`Func::get1`] method for more documentation.
767        (get12, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)
768
769        /// Extracts a natively-callable object from this `Func`, if the
770        /// signature matches.
771        ///
772        /// See the [`Func::get1`] method for more documentation.
773        (get13, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)
774
775        /// Extracts a natively-callable object from this `Func`, if the
776        /// signature matches.
777        ///
778        /// See the [`Func::get1`] method for more documentation.
779        (get14, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)
780
781        /// Extracts a natively-callable object from this `Func`, if the
782        /// signature matches.
783        ///
784        /// See the [`Func::get1`] method for more documentation.
785        (get15, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)
786    }
787
788    /// Get a reference to this function's store.
789    pub fn store(&self) -> &Store {
790        &self.instance.store
791    }
792}
793
794impl fmt::Debug for Func {
795    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
796        write!(f, "Func")
797    }
798}
799
800pub(crate) fn invoke_wasm_and_catch_traps(
801    vmctx: *mut VMContext,
802    store: &Store,
803    closure: impl FnMut(),
804) -> Result<(), Trap> {
805    let signalhandler = store.signal_handler();
806    unsafe {
807        let canary = 0;
808        let _auto_reset_canary = store
809            .externref_activations_table()
810            .set_stack_canary(&canary);
811
812        wasmtime_runtime::catch_traps(
813            vmctx,
814            store.engine().config().max_wasm_stack,
815            |addr| store.is_in_jit_code(addr),
816            signalhandler.as_deref(),
817            closure,
818        )
819        .map_err(Trap::from_runtime)
820    }
821}
822
823// Public (but hidden) wrapper around a `Weak<StoreInner>` so that we can use it
824// in public (but hidden) trait methods.
825#[doc(hidden)]
826#[derive(Clone, Copy)]
827pub struct WeakStore<'a>(&'a Weak<StoreInner>);
828
829/// A trait implemented for types which can be arguments to closures passed to
830/// [`Func::wrap`] and friends.
831///
832/// This trait should not be implemented by user types. This trait may change at
833/// any time internally. The types which implement this trait, however, are
834/// stable over time.
835///
836/// For more information see [`Func::wrap`]
837pub unsafe trait WasmTy {
838    // The raw ABI representation of this type inside Wasm.
839    #[doc(hidden)]
840    type Abi: Copy;
841
842    // Is this value compatible with the given store?
843    #[doc(hidden)]
844    fn compatible_with_store<'a>(&self, store: WeakStore<'a>) -> bool;
845
846    // Convert this value into its ABI representation, when passing a value into
847    // Wasm as an argument.
848    #[doc(hidden)]
849    fn into_abi_for_arg<'a>(self, store: WeakStore<'a>) -> Self::Abi;
850
851    // Convert from the raw ABI representation back into `Self`, when receiving
852    // a value from Wasm.
853    //
854    // Safety: The abi value *must* have be valid for this type (e.g. for
855    // `externref`, it must be a valid raw `VMExternRef` pointer, not some
856    // random, dangling pointer).
857    #[doc(hidden)]
858    unsafe fn from_abi<'a>(abi: Self::Abi, store: WeakStore<'a>) -> Self;
859
860    // Add this type to the given vec of expected valtypes.
861    #[doc(hidden)]
862    fn push(dst: &mut Vec<ValType>);
863
864    // Does the next valtype(s) match this type?
865    #[doc(hidden)]
866    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>;
867
868    // Load this type's raw ABI representation from an args array.
869    #[doc(hidden)]
870    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi;
871
872    // Store this type's raw ABI representation into an args array.
873    #[doc(hidden)]
874    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128);
875}
876
877/// A trait implemented for types which can be returned from closures passed to
878/// [`Func::wrap`] and friends.
879///
880/// This trait should not be implemented by user types. This trait may change at
881/// any time internally. The types which implement this trait, however, are
882/// stable over time.
883///
884/// For more information see [`Func::wrap`]
885pub unsafe trait WasmRet {
886    // Same as `WasmTy::Abi`.
887    #[doc(hidden)]
888    type Abi: Copy;
889
890    // Same as `WasmTy::compatible_with_store`.
891    #[doc(hidden)]
892    fn compatible_with_store<'a>(&self, store: WeakStore<'a>) -> bool;
893
894    // Similar to `WasmTy::into_abi_for_arg` but used when host code is
895    // returning a value into Wasm, rather than host code passing an argument to
896    // a Wasm call. Unlike `into_abi_for_arg`, implementors of this method can
897    // raise traps, which means that callers must ensure that
898    // `invoke_wasm_and_catch_traps` is on the stack, and therefore this method
899    // is unsafe.
900    #[doc(hidden)]
901    unsafe fn into_abi_for_ret<'a>(self, store: WeakStore<'a>) -> Self::Abi;
902
903    // Same as `WasmTy::from_abi`.
904    #[doc(hidden)]
905    unsafe fn from_abi<'a>(abi: Self::Abi, store: WeakStore<'a>) -> Self;
906
907    // Same as `WasmTy::push`.
908    #[doc(hidden)]
909    fn push(dst: &mut Vec<ValType>);
910
911    // Same as `WasmTy::matches`.
912    #[doc(hidden)]
913    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()>;
914
915    // Same as `WasmTy::load_from_args`.
916    #[doc(hidden)]
917    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi;
918
919    // Same as `WasmTy::store_to_args`.
920    #[doc(hidden)]
921    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128);
922}
923
924unsafe impl WasmTy for () {
925    type Abi = Self;
926
927    #[inline]
928    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
929        true
930    }
931
932    #[inline]
933    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {}
934
935    #[inline]
936    unsafe fn from_abi<'a>(_abi: Self::Abi, _store: WeakStore<'a>) -> Self {}
937
938    fn push(_dst: &mut Vec<ValType>) {}
939
940    fn matches(_tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
941        Ok(())
942    }
943
944    #[inline]
945    unsafe fn load_from_args(_ptr: &mut *const u128) -> Self::Abi {}
946
947    #[inline]
948    unsafe fn store_to_args(_abi: Self::Abi, _ptr: *mut u128) {}
949}
950
951unsafe impl WasmTy for i32 {
952    type Abi = Self;
953
954    #[inline]
955    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
956        true
957    }
958
959    #[inline]
960    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
961        self
962    }
963
964    #[inline]
965    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
966        abi
967    }
968
969    fn push(dst: &mut Vec<ValType>) {
970        dst.push(ValType::I32);
971    }
972
973    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
974        let next = tys.next();
975        ensure!(
976            next == Some(ValType::I32),
977            "Type mismatch, expected i32, got {:?}",
978            next
979        );
980        Ok(())
981    }
982
983    #[inline]
984    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
985        let ret = **ptr as Self;
986        *ptr = (*ptr).add(1);
987        return ret;
988    }
989
990    #[inline]
991    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
992        *ptr = abi as u128;
993    }
994}
995
996unsafe impl WasmTy for u32 {
997    type Abi = <i32 as WasmTy>::Abi;
998
999    #[inline]
1000    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1001        true
1002    }
1003
1004    #[inline]
1005    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1006        self as i32
1007    }
1008
1009    #[inline]
1010    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1011        abi as Self
1012    }
1013
1014    fn push(dst: &mut Vec<ValType>) {
1015        <i32 as WasmTy>::push(dst)
1016    }
1017
1018    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1019        <i32 as WasmTy>::matches(tys)
1020    }
1021
1022    #[inline]
1023    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1024        <i32 as WasmTy>::load_from_args(ptr)
1025    }
1026
1027    #[inline]
1028    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1029        <i32 as WasmTy>::store_to_args(abi, ptr)
1030    }
1031}
1032
1033unsafe impl WasmTy for i64 {
1034    type Abi = Self;
1035
1036    #[inline]
1037    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1038        true
1039    }
1040
1041    #[inline]
1042    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1043        self
1044    }
1045
1046    #[inline]
1047    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1048        abi
1049    }
1050
1051    fn push(dst: &mut Vec<ValType>) {
1052        dst.push(ValType::I64);
1053    }
1054
1055    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1056        let next = tys.next();
1057        ensure!(
1058            next == Some(ValType::I64),
1059            "Type mismatch, expected i64, got {:?}",
1060            next
1061        );
1062        Ok(())
1063    }
1064
1065    #[inline]
1066    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1067        let ret = **ptr as Self;
1068        *ptr = (*ptr).add(1);
1069        return ret;
1070    }
1071
1072    #[inline]
1073    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1074        *ptr = abi as u128;
1075    }
1076}
1077
1078unsafe impl WasmTy for u64 {
1079    type Abi = <i64 as WasmTy>::Abi;
1080
1081    #[inline]
1082    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1083        true
1084    }
1085
1086    #[inline]
1087    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1088        self as i64
1089    }
1090
1091    #[inline]
1092    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1093        abi as Self
1094    }
1095
1096    fn push(dst: &mut Vec<ValType>) {
1097        <i64 as WasmTy>::push(dst)
1098    }
1099
1100    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1101        <i64 as WasmTy>::matches(tys)
1102    }
1103
1104    #[inline]
1105    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1106        <i64 as WasmTy>::load_from_args(ptr)
1107    }
1108
1109    #[inline]
1110    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1111        <i64 as WasmTy>::store_to_args(abi, ptr)
1112    }
1113}
1114
1115unsafe impl WasmTy for f32 {
1116    type Abi = Self;
1117
1118    #[inline]
1119    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1120        true
1121    }
1122
1123    #[inline]
1124    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1125        self
1126    }
1127
1128    #[inline]
1129    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1130        abi
1131    }
1132
1133    fn push(dst: &mut Vec<ValType>) {
1134        dst.push(ValType::F32);
1135    }
1136
1137    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1138        let next = tys.next();
1139        ensure!(
1140            next == Some(ValType::F32),
1141            "Type mismatch, expected f32, got {:?}",
1142            next
1143        );
1144        Ok(())
1145    }
1146
1147    #[inline]
1148    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1149        let ret = f32::from_bits(**ptr as u32);
1150        *ptr = (*ptr).add(1);
1151        return ret;
1152    }
1153
1154    #[inline]
1155    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1156        *ptr = abi.to_bits() as u128;
1157    }
1158}
1159
1160unsafe impl WasmTy for f64 {
1161    type Abi = Self;
1162
1163    #[inline]
1164    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1165        true
1166    }
1167
1168    #[inline]
1169    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1170        self
1171    }
1172
1173    #[inline]
1174    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1175        abi
1176    }
1177
1178    fn push(dst: &mut Vec<ValType>) {
1179        dst.push(ValType::F64);
1180    }
1181
1182    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1183        let next = tys.next();
1184        ensure!(
1185            next == Some(ValType::F64),
1186            "Type mismatch, expected f64, got {:?}",
1187            next
1188        );
1189        Ok(())
1190    }
1191
1192    #[inline]
1193    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1194        let ret = f64::from_bits(**ptr as u64);
1195        *ptr = (*ptr).add(1);
1196        return ret;
1197    }
1198
1199    #[inline]
1200    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1201        *ptr = abi.to_bits() as u128;
1202    }
1203}
1204
1205unsafe impl WasmTy for Option<ExternRef> {
1206    type Abi = *mut u8;
1207
1208    #[inline]
1209    fn compatible_with_store<'a>(&self, _store: WeakStore<'a>) -> bool {
1210        true
1211    }
1212
1213    #[inline]
1214    fn into_abi_for_arg<'a>(self, store: WeakStore<'a>) -> Self::Abi {
1215        if let Some(x) = self {
1216            let store = Store::upgrade(store.0).unwrap();
1217            let abi = x.inner.as_raw();
1218            unsafe {
1219                store
1220                    .externref_activations_table()
1221                    .insert_with_gc(x.inner, store.stack_map_registry());
1222            }
1223            abi
1224        } else {
1225            ptr::null_mut()
1226        }
1227    }
1228
1229    #[inline]
1230    unsafe fn from_abi<'a>(abi: Self::Abi, _store: WeakStore<'a>) -> Self {
1231        if abi.is_null() {
1232            None
1233        } else {
1234            Some(ExternRef {
1235                inner: wasmtime_runtime::VMExternRef::clone_from_raw(abi),
1236            })
1237        }
1238    }
1239
1240    fn push(dst: &mut Vec<ValType>) {
1241        dst.push(ValType::ExternRef);
1242    }
1243
1244    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1245        let next = tys.next();
1246        ensure!(
1247            next == Some(ValType::ExternRef),
1248            "Type mismatch, expected externref, got {:?}",
1249            next
1250        );
1251        Ok(())
1252    }
1253
1254    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1255        let ret = **ptr as usize as *mut u8;
1256        *ptr = (*ptr).add(1);
1257        ret
1258    }
1259
1260    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1261        ptr::write(ptr, abi as usize as u128);
1262    }
1263}
1264
1265unsafe impl WasmTy for Option<Func> {
1266    type Abi = *mut wasmtime_runtime::VMCallerCheckedAnyfunc;
1267
1268    #[inline]
1269    fn compatible_with_store<'a>(&self, store: WeakStore<'a>) -> bool {
1270        if let Some(f) = self {
1271            let store = Store::upgrade(store.0).unwrap();
1272            Store::same(&store, f.store())
1273        } else {
1274            true
1275        }
1276    }
1277
1278    #[inline]
1279    fn into_abi_for_arg<'a>(self, _store: WeakStore<'a>) -> Self::Abi {
1280        if let Some(f) = self {
1281            f.caller_checked_anyfunc().as_ptr()
1282        } else {
1283            ptr::null_mut()
1284        }
1285    }
1286
1287    #[inline]
1288    unsafe fn from_abi<'a>(abi: Self::Abi, store: WeakStore<'a>) -> Self {
1289        let store = Store::upgrade(store.0).unwrap();
1290        Func::from_caller_checked_anyfunc(&store, abi)
1291    }
1292
1293    fn push(dst: &mut Vec<ValType>) {
1294        dst.push(ValType::FuncRef);
1295    }
1296
1297    fn matches(mut tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1298        let next = tys.next();
1299        ensure!(
1300            next == Some(ValType::FuncRef),
1301            "Type mismatch, expected funcref, got {:?}",
1302            next
1303        );
1304        Ok(())
1305    }
1306
1307    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1308        let ret = **ptr as usize as *mut wasmtime_runtime::VMCallerCheckedAnyfunc;
1309        *ptr = (*ptr).add(1);
1310        ret
1311    }
1312
1313    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1314        ptr::write(ptr, abi as usize as u128);
1315    }
1316}
1317
1318unsafe impl<T> WasmRet for T
1319where
1320    T: WasmTy,
1321{
1322    type Abi = <T as WasmTy>::Abi;
1323
1324    #[inline]
1325    fn compatible_with_store<'a>(&self, store: WeakStore<'a>) -> bool {
1326        <Self as WasmTy>::compatible_with_store(self, store)
1327    }
1328
1329    #[inline]
1330    unsafe fn into_abi_for_ret<'a>(self, store: WeakStore<'a>) -> Self::Abi {
1331        <Self as WasmTy>::into_abi_for_arg(self, store)
1332    }
1333
1334    #[inline]
1335    unsafe fn from_abi<'a>(abi: Self::Abi, store: WeakStore<'a>) -> Self {
1336        <Self as WasmTy>::from_abi(abi, store)
1337    }
1338
1339    #[inline]
1340    fn push(dst: &mut Vec<ValType>) {
1341        <Self as WasmTy>::push(dst)
1342    }
1343
1344    #[inline]
1345    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1346        <Self as WasmTy>::matches(tys)
1347    }
1348
1349    #[inline]
1350    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1351        <Self as WasmTy>::load_from_args(ptr)
1352    }
1353
1354    #[inline]
1355    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1356        <Self as WasmTy>::store_to_args(abi, ptr)
1357    }
1358}
1359
1360unsafe impl<T> WasmRet for Result<T, Trap>
1361where
1362    T: WasmTy,
1363{
1364    type Abi = <T as WasmTy>::Abi;
1365
1366    #[inline]
1367    fn compatible_with_store<'a>(&self, store: WeakStore<'a>) -> bool {
1368        match self {
1369            Ok(x) => <T as WasmTy>::compatible_with_store(x, store),
1370            Err(_) => true,
1371        }
1372    }
1373
1374    #[inline]
1375    unsafe fn into_abi_for_ret<'a>(self, store: WeakStore<'a>) -> Self::Abi {
1376        match self {
1377            Ok(val) => return <T as WasmTy>::into_abi_for_arg(val, store),
1378            Err(trap) => handle_trap(trap),
1379        }
1380
1381        unsafe fn handle_trap(trap: Trap) -> ! {
1382            raise_user_trap(trap.into())
1383        }
1384    }
1385
1386    #[inline]
1387    unsafe fn from_abi<'a>(abi: Self::Abi, store: WeakStore<'a>) -> Self {
1388        Ok(<T as WasmTy>::from_abi(abi, store))
1389    }
1390
1391    fn push(dst: &mut Vec<ValType>) {
1392        <T as WasmTy>::push(dst)
1393    }
1394
1395    fn matches(tys: impl Iterator<Item = ValType>) -> anyhow::Result<()> {
1396        <T as WasmTy>::matches(tys)
1397    }
1398
1399    #[inline]
1400    unsafe fn load_from_args(ptr: &mut *const u128) -> Self::Abi {
1401        <T as WasmTy>::load_from_args(ptr)
1402    }
1403
1404    #[inline]
1405    unsafe fn store_to_args(abi: Self::Abi, ptr: *mut u128) {
1406        <T as WasmTy>::store_to_args(abi, ptr);
1407    }
1408}
1409
1410/// Internal trait implemented for all arguments that can be passed to
1411/// [`Func::wrap`].
1412///
1413/// This trait should not be implemented by external users, it's only intended
1414/// as an implementation detail of this crate.
1415pub trait IntoFunc<Params, Results> {
1416    #[doc(hidden)]
1417    fn into_func(self, store: &Store) -> Func;
1418}
1419
1420/// A structure representing the *caller's* context when creating a function
1421/// via [`Func::wrap`].
1422///
1423/// This structure can be taken as the first parameter of a closure passed to
1424/// [`Func::wrap`], and it can be used to learn information about the caller of
1425/// the function, such as the calling module's memory, exports, etc.
1426///
1427/// The primary purpose of this structure is to provide access to the
1428/// caller's information, such as it's exported memory. This allows
1429/// functions which take pointers as arguments to easily read the memory the
1430/// pointers point into.
1431///
1432/// Note that this is intended to be a pretty temporary mechanism for accessing
1433/// the caller's memory until interface types has been fully standardized and
1434/// implemented.
1435pub struct Caller<'a> {
1436    // Note that this is a `Weak` pointer instead of a `&'a Store`,
1437    // intentionally so. This allows us to break an `Rc` cycle which would
1438    // otherwise look like this:
1439    //
1440    // * A `Store` object ...
1441    // * ... owns all `InstanceHandle` objects ...
1442    // * ... which are created in `Func::wrap` with custom host data ...
1443    // * ... where the custom host data needs to point to `Store` to be stored
1444    //   here
1445    //
1446    // This `Rc` cycle means that we would never actually reclaim any memory or
1447    // deallocate any instances. To break this cycle we use a weak pointer here
1448    // which points back to `Store`. A `Caller` should only ever be usable
1449    // when the original `Store` is alive, however, so this should always be an
1450    // upgrade-able pointer. Alternative solutions or other ideas to break this
1451    // cycle would be most welcome!
1452    store: &'a Weak<StoreInner>,
1453    caller_vmctx: *mut VMContext,
1454}
1455
1456impl Caller<'_> {
1457    /// Looks up an export from the caller's module by the `name` given.
1458    ///
1459    /// Note that this function is only implemented for the `Extern::Memory`
1460    /// type currently. No other exported structure can be acquired through this
1461    /// just yet, but this may be implemented in the future!
1462    ///
1463    /// # Return
1464    ///
1465    /// If a memory export with the `name` provided was found, then it is
1466    /// returned as a `Memory`. There are a number of situations, however, where
1467    /// the memory may not be available:
1468    ///
1469    /// * The caller instance may not have an export named `name`
1470    /// * The export named `name` may not be an exported memory
1471    /// * There may not be a caller available, for example if `Func` was called
1472    ///   directly from host code.
1473    ///
1474    /// It's recommended to take care when calling this API and gracefully
1475    /// handling a `None` return value.
1476    pub fn get_export(&self, name: &str) -> Option<Extern> {
1477        unsafe {
1478            if self.caller_vmctx.is_null() {
1479                return None;
1480            }
1481            let instance = InstanceHandle::from_vmctx(self.caller_vmctx);
1482            let export = match instance.lookup(name) {
1483                Some(Export::Memory(m)) => m,
1484                _ => return None,
1485            };
1486            // Our `Weak` pointer is used only to break a cycle where `Store`
1487            // stores instance handles which have this weak pointer as their
1488            // custom host data. This function should only be invoke-able while
1489            // the `Store` is active, so this upgrade should always succeed.
1490            debug_assert!(self.store.upgrade().is_some());
1491            let handle =
1492                Store::from_inner(self.store.upgrade()?).existing_instance_handle(instance);
1493            let mem = Memory::from_wasmtime_memory(export, handle);
1494            Some(Extern::Memory(mem))
1495        }
1496    }
1497
1498    /// Get a handle to this caller's store.
1499    pub fn store(&self) -> Store {
1500        // See comment above the `store` member for why this unwrap is OK.
1501        Store::upgrade(&self.store).unwrap()
1502    }
1503}
1504
1505#[inline(never)]
1506#[cold]
1507unsafe fn raise_cross_store_trap() -> ! {
1508    #[derive(Debug)]
1509    struct CrossStoreError;
1510
1511    impl std::error::Error for CrossStoreError {}
1512
1513    impl fmt::Display for CrossStoreError {
1514        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1515            write!(
1516                f,
1517                "host function attempted to return cross-`Store` \
1518                 value to Wasm",
1519            )
1520        }
1521    }
1522
1523    raise_user_trap(Box::new(CrossStoreError));
1524}
1525
1526macro_rules! impl_into_func {
1527    ($(
1528        ($($args:ident)*)
1529    )*) => ($(
1530        // Implement for functions without a leading `&Caller` parameter,
1531        // delegating to the implementation below which does have the leading
1532        // `Caller` parameter.
1533        impl<F, $($args,)* R> IntoFunc<($($args,)*), R> for F
1534        where
1535            F: Fn($($args),*) -> R + 'static,
1536            $($args: WasmTy,)*
1537            R: WasmRet,
1538        {
1539            #[allow(non_snake_case)]
1540            fn into_func(self, store: &Store) -> Func {
1541                Func::wrap(store, move |_: Caller<'_>, $($args:$args),*| {
1542                    self($($args),*)
1543                })
1544            }
1545        }
1546
1547        #[allow(non_snake_case)]
1548        impl<F, $($args,)* R> IntoFunc<(Caller<'_>, $($args,)*), R> for F
1549        where
1550            F: Fn(Caller<'_>, $($args),*) -> R + 'static,
1551            $($args: WasmTy,)*
1552            R: WasmRet,
1553        {
1554            fn into_func(self, store: &Store) -> Func {
1555                /// This shim is called by Wasm code, constructs a `Caller`,
1556                /// calls the wrapped host function, and returns the translated
1557                /// result back to Wasm.
1558                ///
1559                /// Note that this shim's ABI must *exactly* match that expected
1560                /// by Cranelift, since Cranelift is generating raw function
1561                /// calls directly to this function.
1562                unsafe extern "C" fn wasm_to_host_shim<F, $($args,)* R>(
1563                    vmctx: *mut VMContext,
1564                    caller_vmctx: *mut VMContext,
1565                    $( $args: $args::Abi, )*
1566                ) -> R::Abi
1567                where
1568                    F: Fn(Caller<'_>, $( $args ),*) -> R + 'static,
1569                    $( $args: WasmTy, )*
1570                    R: WasmRet,
1571                {
1572                    let state = (*vmctx).host_state();
1573                    // Double-check ourselves in debug mode, but we control
1574                    // the `Any` here so an unsafe downcast should also
1575                    // work.
1576                    debug_assert!(state.is::<(F, Weak<StoreInner>)>());
1577                    let (func, store) = &*(state as *const _ as *const (F, Weak<StoreInner>));
1578                    let weak_store = WeakStore(store);
1579
1580                    let ret = {
1581                        panic::catch_unwind(AssertUnwindSafe(|| {
1582                            func(
1583                                Caller { store, caller_vmctx },
1584                                $( $args::from_abi($args, weak_store), )*
1585                            )
1586                        }))
1587                    };
1588                    match ret {
1589                        Err(panic) => wasmtime_runtime::resume_panic(panic),
1590                        Ok(ret) => {
1591                            // Because the wrapped function is not `unsafe`, we
1592                            // can't assume it returned a value that is
1593                            // compatible with this store.
1594                            if !ret.compatible_with_store(weak_store) {
1595                                raise_cross_store_trap();
1596                            }
1597
1598                            ret.into_abi_for_ret(weak_store)
1599                        }
1600                    }
1601                }
1602
1603                /// This trampoline allows host code to indirectly call the
1604                /// wrapped function (e.g. via `Func::call` on a `funcref` that
1605                /// happens to reference our wrapped function).
1606                ///
1607                /// It reads the arguments out of the incoming `args` array,
1608                /// calls the given function pointer, and then stores the result
1609                /// back into the `args` array.
1610                unsafe extern "C" fn host_trampoline<$($args,)* R>(
1611                    callee_vmctx: *mut VMContext,
1612                    caller_vmctx: *mut VMContext,
1613                    ptr: *const VMFunctionBody,
1614                    args: *mut u128,
1615                )
1616                where
1617                    $($args: WasmTy,)*
1618                    R: WasmRet,
1619                {
1620                    let ptr = mem::transmute::<
1621                        *const VMFunctionBody,
1622                        unsafe extern "C" fn(
1623                            *mut VMContext,
1624                            *mut VMContext,
1625                            $( $args::Abi, )*
1626                        ) -> R::Abi,
1627                    >(ptr);
1628
1629                    let mut _next = args as *const u128;
1630                    $( let $args = $args::load_from_args(&mut _next); )*
1631                    let ret = ptr(callee_vmctx, caller_vmctx, $( $args ),*);
1632                    R::store_to_args(ret, args);
1633                }
1634
1635                let mut _args = Vec::new();
1636                $($args::push(&mut _args);)*
1637                let mut ret = Vec::new();
1638                R::push(&mut ret);
1639                let ty = FuncType::new(_args.into(), ret.into());
1640
1641                let store_weak = store.weak();
1642                let trampoline = host_trampoline::<$($args,)* R>;
1643                let (instance, export) = unsafe {
1644                    crate::trampoline::generate_raw_func_export(
1645                        &ty,
1646                        std::slice::from_raw_parts_mut(
1647                            wasm_to_host_shim::<F, $($args,)* R> as *mut _,
1648                            0,
1649                        ),
1650                        trampoline,
1651                        store,
1652                        Box::new((self, store_weak)),
1653                    )
1654                    .expect("failed to generate export")
1655                };
1656
1657                Func {
1658                    instance,
1659                    export,
1660                    trampoline,
1661                }
1662            }
1663        }
1664    )*)
1665}
1666
1667impl_into_func! {
1668    ()
1669    (A1)
1670    (A1 A2)
1671    (A1 A2 A3)
1672    (A1 A2 A3 A4)
1673    (A1 A2 A3 A4 A5)
1674    (A1 A2 A3 A4 A5 A6)
1675    (A1 A2 A3 A4 A5 A6 A7)
1676    (A1 A2 A3 A4 A5 A6 A7 A8)
1677    (A1 A2 A3 A4 A5 A6 A7 A8 A9)
1678    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10)
1679    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11)
1680    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12)
1681    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13)
1682    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14)
1683    (A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12 A13 A14 A15)
1684}
1685
1686#[test]
1687fn wasm_ty_roundtrip() -> Result<(), anyhow::Error> {
1688    use crate::*;
1689    let store = Store::default();
1690    let debug = Func::wrap(&store, |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
1691        assert_eq!(a, -1);
1692        assert_eq!(b, 1);
1693        assert_eq!(c, 2.0);
1694        assert_eq!(d, -3);
1695        assert_eq!(e, 3);
1696        assert_eq!(f, 4.0);
1697    });
1698    let module = Module::new(
1699        store.engine(),
1700        r#"
1701             (module
1702                 (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
1703                 (func (export "foo") (param i32 i32 f32 i64 i64 f64)
1704                    (if (i32.ne (local.get 0) (i32.const -1))
1705                        (then unreachable)
1706                    )
1707                    (if (i32.ne (local.get 1) (i32.const 1))
1708                        (then unreachable)
1709                    )
1710                    (if (f32.ne (local.get 2) (f32.const 2))
1711                        (then unreachable)
1712                    )
1713                    (if (i64.ne (local.get 3) (i64.const -3))
1714                        (then unreachable)
1715                    )
1716                    (if (i64.ne (local.get 4) (i64.const 3))
1717                        (then unreachable)
1718                    )
1719                    (if (f64.ne (local.get 5) (f64.const 4))
1720                        (then unreachable)
1721                    )
1722                    local.get 0
1723                    local.get 1
1724                    local.get 2
1725                    local.get 3
1726                    local.get 4
1727                    local.get 5
1728                    call $debug
1729                )
1730            )
1731         "#,
1732    )?;
1733    let instance = Instance::new(&store, &module, &[debug.into()])?;
1734    let foo = instance
1735        .get_func("foo")
1736        .unwrap()
1737        .get6::<i32, u32, f32, i64, u64, f64, ()>()?;
1738    foo(-1, 1, 2.0, -3, 3, 4.0)?;
1739    Ok(())
1740}