wasmtime_runtime/trampolines.rs
1//! Trampolines for calling into Wasm from the host and calling the host from
2//! Wasm.
3
4use crate::VMContext;
5use std::mem;
6
7/// Given a Wasm function pointer and a `vmctx`, prepare the `vmctx` for calling
8/// into that Wasm function, and return the host-to-Wasm entry trampoline.
9///
10/// Callers must never call Wasm function pointers directly. Callers must
11/// instead call this function and then enter Wasm through the returned
12/// host-to-Wasm trampoline.
13///
14/// # Unsafety
15///
16/// The `vmctx` argument must be valid.
17///
18/// The generic type `T` must be a function pointer type and `func` must be a
19/// pointer to a Wasm function of that signature.
20///
21/// After calling this function, you may not mess with the vmctx or any other
22/// Wasm state until after you've called the trampoline returned by this
23/// function.
24#[inline]
25pub unsafe fn prepare_host_to_wasm_trampoline<T>(vmctx: *mut VMContext, func: T) -> T {
26 assert_eq!(mem::size_of::<T>(), mem::size_of::<usize>());
27
28 // Save the callee in the `vmctx`. The trampoline will read this function
29 // pointer and tail call to it.
30 (*vmctx)
31 .instance_mut()
32 .set_callee(Some(mem::transmute_copy(&func)));
33
34 // Give callers the trampoline, transmuted into their desired function
35 // signature (the trampoline is variadic and works with all signatures).
36 mem::transmute_copy(&(host_to_wasm_trampoline as usize))
37}
38
39extern "C" {
40 fn host_to_wasm_trampoline();
41 pub(crate) fn wasm_to_host_trampoline();
42}
43
44cfg_if::cfg_if! {
45 if #[cfg(target_arch = "x86_64")] {
46 #[macro_use]
47 mod x86_64;
48 } else if #[cfg(target_arch = "aarch64")] {
49 #[macro_use]
50 mod aarch64;
51 } else if #[cfg(target_arch = "s390x")] {
52 #[macro_use]
53 mod s390x;
54 }else if #[cfg(target_arch = "riscv64")] {
55 #[macro_use]
56 mod riscv64;
57 } else {
58 compile_error!("unsupported architecture");
59 }
60}