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}