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