190ac295eSAlex Crichton use crate::{WasmtimeCaller, WasmtimeStoreData, wasm_trap_t};
27a1b7cdfSAlex Crichton use crate::{
390ac295eSAlex Crichton WasmtimeStoreContext, WasmtimeStoreContextMut, wasm_extern_t, wasm_functype_t, wasm_store_t,
490ac295eSAlex Crichton wasm_val_t, wasm_val_vec_t, wasmtime_error_t, wasmtime_extern_t, wasmtime_val_t,
590ac295eSAlex Crichton wasmtime_val_union,
67a1b7cdfSAlex Crichton };
72afaac51SAlex Crichton use std::any::Any;
86ef09359SAlex Crichton use std::ffi::c_void;
9c7367355SAlex Crichton use std::mem::{self, MaybeUninit};
106ef09359SAlex Crichton use std::panic::{self, AssertUnwindSafe};
116ef09359SAlex Crichton use std::ptr;
126ef09359SAlex Crichton use std::str;
139187f2d9SAlex Crichton use wasmtime::{
14dc029724SNick Fitzgerald AsContext, AsContextMut, Error, Extern, Func, Result, RootScope, StoreContext, StoreContextMut,
15dc029724SNick Fitzgerald Trap, Val, ValRaw,
169187f2d9SAlex Crichton };
179187f2d9SAlex Crichton
186ef09359SAlex Crichton #[derive(Clone)]
196ef09359SAlex Crichton #[repr(transparent)]
206ef09359SAlex Crichton pub struct wasm_func_t {
216ef09359SAlex Crichton ext: wasm_extern_t,
226ef09359SAlex Crichton }
236ef09359SAlex Crichton
246ef09359SAlex Crichton wasmtime_c_api_macros::declare_ref!(wasm_func_t);
256ef09359SAlex Crichton
26f94db655SPeter Huene pub type wasm_func_callback_t = extern "C" fn(
27f94db655SPeter Huene args: *const wasm_val_vec_t,
28f94db655SPeter Huene results: *mut wasm_val_vec_t,
29f94db655SPeter Huene ) -> Option<Box<wasm_trap_t>>;
306ef09359SAlex Crichton
316ef09359SAlex Crichton pub type wasm_func_callback_with_env_t = extern "C" fn(
326ef09359SAlex Crichton env: *mut std::ffi::c_void,
33f94db655SPeter Huene args: *const wasm_val_vec_t,
34f94db655SPeter Huene results: *mut wasm_val_vec_t,
356ef09359SAlex Crichton ) -> Option<Box<wasm_trap_t>>;
366ef09359SAlex Crichton
376ef09359SAlex Crichton impl wasm_func_t {
try_from(e: &wasm_extern_t) -> Option<&wasm_func_t>386ef09359SAlex Crichton pub(crate) fn try_from(e: &wasm_extern_t) -> Option<&wasm_func_t> {
396ef09359SAlex Crichton match &e.which {
40cca558cdSAlex Crichton Extern::Func(_) => Some(unsafe { &*(e as *const _ as *const _) }),
416ef09359SAlex Crichton _ => None,
426ef09359SAlex Crichton }
436ef09359SAlex Crichton }
446ef09359SAlex Crichton
func(&self) -> Func457a1b7cdfSAlex Crichton pub(crate) fn func(&self) -> Func {
467a1b7cdfSAlex Crichton match self.ext.which {
47cca558cdSAlex Crichton Extern::Func(f) => f,
486ef09359SAlex Crichton _ => unsafe { std::hint::unreachable_unchecked() },
496ef09359SAlex Crichton }
506ef09359SAlex Crichton }
516ef09359SAlex Crichton }
526ef09359SAlex Crichton
create_function( store: &mut wasm_store_t, ty: &wasm_functype_t, func: impl Fn(*const wasm_val_vec_t, *mut wasm_val_vec_t) -> Option<Box<wasm_trap_t>> + Send + Sync + 'static, ) -> Box<wasm_func_t>537a1b7cdfSAlex Crichton unsafe fn create_function(
547a1b7cdfSAlex Crichton store: &mut wasm_store_t,
556ef09359SAlex Crichton ty: &wasm_functype_t,
567a1b7cdfSAlex Crichton func: impl Fn(*const wasm_val_vec_t, *mut wasm_val_vec_t) -> Option<Box<wasm_trap_t>>
577a1b7cdfSAlex Crichton + Send
587a1b7cdfSAlex Crichton + Sync
59f94db655SPeter Huene + 'static,
606ef09359SAlex Crichton ) -> Box<wasm_func_t> {
618652011fSNick Fitzgerald let ty = ty.ty().ty(store.store.context().engine());
627a1b7cdfSAlex Crichton let func = Func::new(
637a1b7cdfSAlex Crichton store.store.context_mut(),
647a1b7cdfSAlex Crichton ty,
657a1b7cdfSAlex Crichton move |_caller, params, results| {
66f94db655SPeter Huene let params: wasm_val_vec_t = params
676ef09359SAlex Crichton .iter()
684cdf8b7cSNick Fitzgerald .cloned()
696ef09359SAlex Crichton .map(|p| wasm_val_t::from_val(p))
70f94db655SPeter Huene .collect::<Vec<_>>()
71f94db655SPeter Huene .into();
72f94db655SPeter Huene let mut out_results: wasm_val_vec_t = vec![wasm_val_t::default(); results.len()].into();
737a1b7cdfSAlex Crichton let out = func(¶ms, &mut out_results);
746ef09359SAlex Crichton if let Some(trap) = out {
752afaac51SAlex Crichton return Err(trap.error);
766ef09359SAlex Crichton }
77f94db655SPeter Huene
78f94db655SPeter Huene let out_results = out_results.as_slice();
796ef09359SAlex Crichton for i in 0..results.len() {
806ef09359SAlex Crichton results[i] = out_results[i].val();
816ef09359SAlex Crichton }
826ef09359SAlex Crichton Ok(())
837a1b7cdfSAlex Crichton },
847a1b7cdfSAlex Crichton );
857a1b7cdfSAlex Crichton Box::new(wasm_func_t {
867a1b7cdfSAlex Crichton ext: wasm_extern_t {
877a1b7cdfSAlex Crichton store: store.store.clone(),
887a1b7cdfSAlex Crichton which: func.into(),
897a1b7cdfSAlex Crichton },
907a1b7cdfSAlex Crichton })
916ef09359SAlex Crichton }
926ef09359SAlex Crichton
93ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_new( store: &mut wasm_store_t, ty: &wasm_functype_t, callback: wasm_func_callback_t, ) -> Box<wasm_func_t>947a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasm_func_new(
957a1b7cdfSAlex Crichton store: &mut wasm_store_t,
966ef09359SAlex Crichton ty: &wasm_functype_t,
976ef09359SAlex Crichton callback: wasm_func_callback_t,
986ef09359SAlex Crichton ) -> Box<wasm_func_t> {
997a1b7cdfSAlex Crichton create_function(store, ty, move |params, results| callback(params, results))
1006ef09359SAlex Crichton }
1016ef09359SAlex Crichton
102ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_new_with_env( store: &mut wasm_store_t, ty: &wasm_functype_t, callback: wasm_func_callback_with_env_t, data: *mut c_void, finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>, ) -> Box<wasm_func_t>1037a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasm_func_new_with_env(
1047a1b7cdfSAlex Crichton store: &mut wasm_store_t,
1056ef09359SAlex Crichton ty: &wasm_functype_t,
1066ef09359SAlex Crichton callback: wasm_func_callback_with_env_t,
1077a1b7cdfSAlex Crichton data: *mut c_void,
1086ef09359SAlex Crichton finalizer: Option<extern "C" fn(arg1: *mut std::ffi::c_void)>,
1096ef09359SAlex Crichton ) -> Box<wasm_func_t> {
1107a1b7cdfSAlex Crichton let finalizer = crate::ForeignData { data, finalizer };
1117a1b7cdfSAlex Crichton create_function(store, ty, move |params, results| {
1128bec98daSAlex Crichton let _ = &finalizer; // move entire finalizer into this closure
1137a1b7cdfSAlex Crichton callback(finalizer.data, params, results)
1146ef09359SAlex Crichton })
1156ef09359SAlex Crichton }
1166ef09359SAlex Crichton
117bcf35449SAlex Crichton /// Places the `args` into `dst` and additionally reserves space in `dst` for `results_size`
118bcf35449SAlex Crichton /// returns. The params/results slices are then returned separately.
translate_args<'a>( dst: &'a mut Vec<Val>, args: impl ExactSizeIterator<Item = Val>, results_size: usize, ) -> (&'a [Val], &'a mut [Val])11937cf8e1eSTyler Rockwood pub(crate) fn translate_args<'a>(
120bcf35449SAlex Crichton dst: &'a mut Vec<Val>,
121bcf35449SAlex Crichton args: impl ExactSizeIterator<Item = Val>,
122bcf35449SAlex Crichton results_size: usize,
123bcf35449SAlex Crichton ) -> (&'a [Val], &'a mut [Val]) {
124bcf35449SAlex Crichton debug_assert!(dst.is_empty());
125bcf35449SAlex Crichton let num_args = args.len();
126bcf35449SAlex Crichton dst.reserve(args.len() + results_size);
127bcf35449SAlex Crichton dst.extend(args);
128ff93bce0SNick Fitzgerald dst.extend((0..results_size).map(|_| Val::null_func_ref()));
129bcf35449SAlex Crichton let (a, b) = dst.split_at_mut(num_args);
130bcf35449SAlex Crichton (a, b)
131bcf35449SAlex Crichton }
132bcf35449SAlex Crichton
133ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_call( func: &mut wasm_func_t, args: *const wasm_val_vec_t, results: *mut wasm_val_vec_t, ) -> *mut wasm_trap_t1346ef09359SAlex Crichton pub unsafe extern "C" fn wasm_func_call(
1357a1b7cdfSAlex Crichton func: &mut wasm_func_t,
136f94db655SPeter Huene args: *const wasm_val_vec_t,
137f94db655SPeter Huene results: *mut wasm_val_vec_t,
1386ef09359SAlex Crichton ) -> *mut wasm_trap_t {
1397a1b7cdfSAlex Crichton let f = func.func();
1407a1b7cdfSAlex Crichton let results = (*results).as_uninit_slice();
1417a1b7cdfSAlex Crichton let args = (*args).as_slice();
142bcf35449SAlex Crichton let mut dst = Vec::new();
143bcf35449SAlex Crichton let (wt_params, wt_results) =
144bcf35449SAlex Crichton translate_args(&mut dst, args.iter().map(|i| i.val()), results.len());
1456ef09359SAlex Crichton
1466ef09359SAlex Crichton // We're calling arbitrary code here most of the time, and we in general
1476ef09359SAlex Crichton // want to try to insulate callers against bugs in wasmtime/wasi/etc if we
1486ef09359SAlex Crichton // can. As a result we catch panics here and transform them to traps to
1496ef09359SAlex Crichton // allow the caller to have any insulation possible against Rust panics.
1507a1b7cdfSAlex Crichton let result = panic::catch_unwind(AssertUnwindSafe(|| {
151bcf35449SAlex Crichton f.call(func.ext.store.context_mut(), wt_params, wt_results)
1527a1b7cdfSAlex Crichton }));
1536ef09359SAlex Crichton match result {
154bcf35449SAlex Crichton Ok(Ok(())) => {
155bcf35449SAlex Crichton for (slot, val) in results.iter_mut().zip(wt_results.iter().cloned()) {
156d07fdca7SNick Fitzgerald crate::initialize(slot, wasm_val_t::from_val(val));
1576ef09359SAlex Crichton }
1587a1b7cdfSAlex Crichton ptr::null_mut()
1596ef09359SAlex Crichton }
1602afaac51SAlex Crichton Ok(Err(err)) => Box::into_raw(Box::new(wasm_trap_t::new(err))),
1616ef09359SAlex Crichton Err(panic) => {
1622afaac51SAlex Crichton let err = error_from_panic(panic);
1632afaac51SAlex Crichton let trap = Box::new(wasm_trap_t::new(err));
1647a1b7cdfSAlex Crichton Box::into_raw(trap)
1656ef09359SAlex Crichton }
1666ef09359SAlex Crichton }
1676ef09359SAlex Crichton }
1686ef09359SAlex Crichton
error_from_panic(panic: Box<dyn Any + Send>) -> Error1692afaac51SAlex Crichton fn error_from_panic(panic: Box<dyn Any + Send>) -> Error {
1702afaac51SAlex Crichton if let Some(msg) = panic.downcast_ref::<String>() {
1712afaac51SAlex Crichton Error::msg(msg.clone())
1722afaac51SAlex Crichton } else if let Some(msg) = panic.downcast_ref::<&'static str>() {
1732afaac51SAlex Crichton Error::msg(*msg)
1742afaac51SAlex Crichton } else {
1752afaac51SAlex Crichton Error::msg("rust panic happened")
1762afaac51SAlex Crichton }
1772afaac51SAlex Crichton }
1782afaac51SAlex Crichton
179ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_type(f: &wasm_func_t) -> Box<wasm_functype_t>1807a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasm_func_type(f: &wasm_func_t) -> Box<wasm_functype_t> {
1817a1b7cdfSAlex Crichton Box::new(wasm_functype_t::new(f.func().ty(f.ext.store.context())))
1826ef09359SAlex Crichton }
1836ef09359SAlex Crichton
184ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_param_arity(f: &wasm_func_t) -> usize1857a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasm_func_param_arity(f: &wasm_func_t) -> usize {
1867a1b7cdfSAlex Crichton f.func().ty(f.ext.store.context()).params().len()
1876ef09359SAlex Crichton }
1886ef09359SAlex Crichton
189ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_result_arity(f: &wasm_func_t) -> usize1907a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasm_func_result_arity(f: &wasm_func_t) -> usize {
1917a1b7cdfSAlex Crichton f.func().ty(f.ext.store.context()).results().len()
1926ef09359SAlex Crichton }
1936ef09359SAlex Crichton
194ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_as_extern(f: &mut wasm_func_t) -> &mut wasm_extern_t1956ef09359SAlex Crichton pub extern "C" fn wasm_func_as_extern(f: &mut wasm_func_t) -> &mut wasm_extern_t {
1966ef09359SAlex Crichton &mut (*f).ext
1976ef09359SAlex Crichton }
1986ef09359SAlex Crichton
199ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasm_func_as_extern_const(f: &wasm_func_t) -> &wasm_extern_t2007a1b7cdfSAlex Crichton pub extern "C" fn wasm_func_as_extern_const(f: &wasm_func_t) -> &wasm_extern_t {
2017a1b7cdfSAlex Crichton &(*f).ext
2027a1b7cdfSAlex Crichton }
2037a1b7cdfSAlex Crichton
2047a1b7cdfSAlex Crichton #[repr(C)]
2057a1b7cdfSAlex Crichton pub struct wasmtime_caller_t<'a> {
206420fc3d1SNick Fitzgerald pub(crate) caller: WasmtimeCaller<'a>,
2076ef09359SAlex Crichton }
208a9455a8eSNick Fitzgerald
2099187f2d9SAlex Crichton impl AsContext for wasmtime_caller_t<'_> {
2109187f2d9SAlex Crichton type Data = WasmtimeStoreData;
2119187f2d9SAlex Crichton
as_context(&self) -> StoreContext<'_, WasmtimeStoreData>2129187f2d9SAlex Crichton fn as_context(&self) -> StoreContext<'_, WasmtimeStoreData> {
2139187f2d9SAlex Crichton self.caller.as_context()
2149187f2d9SAlex Crichton }
2159187f2d9SAlex Crichton }
2169187f2d9SAlex Crichton
2179187f2d9SAlex Crichton impl AsContextMut for wasmtime_caller_t<'_> {
as_context_mut(&mut self) -> StoreContextMut<'_, WasmtimeStoreData>2189187f2d9SAlex Crichton fn as_context_mut(&mut self) -> StoreContextMut<'_, WasmtimeStoreData> {
2199187f2d9SAlex Crichton self.caller.as_context_mut()
2209187f2d9SAlex Crichton }
2219187f2d9SAlex Crichton }
2229187f2d9SAlex Crichton
22365378422SAlex Crichton pub type wasmtime_func_callback_t = extern "C" fn(
2247a1b7cdfSAlex Crichton *mut c_void,
2257a1b7cdfSAlex Crichton *mut wasmtime_caller_t,
2267a1b7cdfSAlex Crichton *const wasmtime_val_t,
2277a1b7cdfSAlex Crichton usize,
2287a1b7cdfSAlex Crichton *mut wasmtime_val_t,
2297a1b7cdfSAlex Crichton usize,
23065378422SAlex Crichton ) -> Option<Box<wasm_trap_t>>;
23165378422SAlex Crichton
232f4b90209SAlex Crichton pub type wasmtime_func_unchecked_callback_t = extern "C" fn(
233f4b90209SAlex Crichton *mut c_void,
234f4b90209SAlex Crichton *mut wasmtime_caller_t,
235f4b90209SAlex Crichton *mut ValRaw,
236f4b90209SAlex Crichton usize,
237f4b90209SAlex Crichton ) -> Option<Box<wasm_trap_t>>;
238bfdbd10aSAlex Crichton
239ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_new( store: WasmtimeStoreContextMut<'_>, ty: &wasm_functype_t, callback: wasmtime_func_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, func: &mut Func, )24065378422SAlex Crichton pub unsafe extern "C" fn wasmtime_func_new(
241420fc3d1SNick Fitzgerald store: WasmtimeStoreContextMut<'_>,
24265378422SAlex Crichton ty: &wasm_functype_t,
24365378422SAlex Crichton callback: wasmtime_func_callback_t,
2447a1b7cdfSAlex Crichton data: *mut c_void,
2457a1b7cdfSAlex Crichton finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
2467a1b7cdfSAlex Crichton func: &mut Func,
247a9455a8eSNick Fitzgerald ) {
2488652011fSNick Fitzgerald let ty = ty.ty().ty(store.engine());
24965378422SAlex Crichton let cb = c_callback_to_rust_fn(callback, data, finalizer);
25065378422SAlex Crichton let f = Func::new(store, ty, cb);
25165378422SAlex Crichton *func = f;
25265378422SAlex Crichton }
25365378422SAlex Crichton
c_callback_to_rust_fn( callback: wasmtime_func_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, ) -> impl Fn(WasmtimeCaller<'_>, &[Val], &mut [Val]) -> Result<()>25465378422SAlex Crichton pub(crate) unsafe fn c_callback_to_rust_fn(
25565378422SAlex Crichton callback: wasmtime_func_callback_t,
25665378422SAlex Crichton data: *mut c_void,
25765378422SAlex Crichton finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
258420fc3d1SNick Fitzgerald ) -> impl Fn(WasmtimeCaller<'_>, &[Val], &mut [Val]) -> Result<()> {
25965378422SAlex Crichton let foreign = crate::ForeignData { data, finalizer };
260c7367355SAlex Crichton move |mut caller, params, results| {
2618bec98daSAlex Crichton let _ = &foreign; // move entire foreign into this closure
2627b5176baSAlex Crichton
263c7367355SAlex Crichton // Convert `params/results` to `wasmtime_val_t`. Use the previous
264c7367355SAlex Crichton // storage in `hostcall_val_storage` to help avoid allocations all the
265c7367355SAlex Crichton // time.
266c7367355SAlex Crichton let mut vals = mem::take(&mut caller.data_mut().hostcall_val_storage);
267c7367355SAlex Crichton debug_assert!(vals.is_empty());
268c7367355SAlex Crichton vals.reserve(params.len() + results.len());
269bd2ea901SNick Fitzgerald vals.extend(
270bd2ea901SNick Fitzgerald params
271bd2ea901SNick Fitzgerald .iter()
272bd2ea901SNick Fitzgerald .cloned()
2739187f2d9SAlex Crichton .map(|p| wasmtime_val_t::from_val_unscoped(&mut caller, p)),
274bd2ea901SNick Fitzgerald );
275c7367355SAlex Crichton vals.extend((0..results.len()).map(|_| wasmtime_val_t {
2767a1b7cdfSAlex Crichton kind: crate::WASMTIME_I32,
2777a1b7cdfSAlex Crichton of: wasmtime_val_union { i32: 0 },
278c7367355SAlex Crichton }));
279c7367355SAlex Crichton let (params, out_results) = vals.split_at_mut(params.len());
280c7367355SAlex Crichton
281c7367355SAlex Crichton // Invoke the C function pointer, getting the results.
2827a1b7cdfSAlex Crichton let mut caller = wasmtime_caller_t { caller };
2837a1b7cdfSAlex Crichton let out = callback(
2847a1b7cdfSAlex Crichton foreign.data,
2857a1b7cdfSAlex Crichton &mut caller,
2867a1b7cdfSAlex Crichton params.as_ptr(),
2877a1b7cdfSAlex Crichton params.len(),
2887a1b7cdfSAlex Crichton out_results.as_mut_ptr(),
2897a1b7cdfSAlex Crichton out_results.len(),
2907a1b7cdfSAlex Crichton );
2917a1b7cdfSAlex Crichton if let Some(trap) = out {
2922afaac51SAlex Crichton return Err(trap.error);
2937a1b7cdfSAlex Crichton }
2947a1b7cdfSAlex Crichton
295c7367355SAlex Crichton // Translate the `wasmtime_val_t` results into the `results` space
2967a1b7cdfSAlex Crichton for (i, result) in out_results.iter().enumerate() {
2979187f2d9SAlex Crichton results[i] = result.to_val_unscoped(&mut caller);
2987a1b7cdfSAlex Crichton }
299c7367355SAlex Crichton
300c7367355SAlex Crichton // Move our `vals` storage back into the store now that we no longer
301c7367355SAlex Crichton // need it. This'll get picked up by the next hostcall and reuse our
302c7367355SAlex Crichton // same storage.
303c7367355SAlex Crichton vals.truncate(0);
304c7367355SAlex Crichton caller.caller.data_mut().hostcall_val_storage = vals;
3057a1b7cdfSAlex Crichton Ok(())
30665378422SAlex Crichton }
307a9455a8eSNick Fitzgerald }
308a9455a8eSNick Fitzgerald
309ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_new_unchecked( store: WasmtimeStoreContextMut<'_>, ty: &wasm_functype_t, callback: wasmtime_func_unchecked_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, func: &mut Func, )310bfdbd10aSAlex Crichton pub unsafe extern "C" fn wasmtime_func_new_unchecked(
311420fc3d1SNick Fitzgerald store: WasmtimeStoreContextMut<'_>,
312bfdbd10aSAlex Crichton ty: &wasm_functype_t,
313bfdbd10aSAlex Crichton callback: wasmtime_func_unchecked_callback_t,
314bfdbd10aSAlex Crichton data: *mut c_void,
315bfdbd10aSAlex Crichton finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
316bfdbd10aSAlex Crichton func: &mut Func,
317bfdbd10aSAlex Crichton ) {
3188652011fSNick Fitzgerald let ty = ty.ty().ty(store.engine());
319bfdbd10aSAlex Crichton let cb = c_unchecked_callback_to_rust_fn(callback, data, finalizer);
320bfdbd10aSAlex Crichton *func = Func::new_unchecked(store, ty, cb);
321bfdbd10aSAlex Crichton }
322bfdbd10aSAlex Crichton
c_unchecked_callback_to_rust_fn( callback: wasmtime_func_unchecked_callback_t, data: *mut c_void, finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>, ) -> impl Fn(WasmtimeCaller<'_>, &mut [MaybeUninit<ValRaw>]) -> Result<()>323bfdbd10aSAlex Crichton pub(crate) unsafe fn c_unchecked_callback_to_rust_fn(
324bfdbd10aSAlex Crichton callback: wasmtime_func_unchecked_callback_t,
325bfdbd10aSAlex Crichton data: *mut c_void,
326bfdbd10aSAlex Crichton finalizer: Option<extern "C" fn(*mut std::ffi::c_void)>,
3278c349a3dSAlex Crichton ) -> impl Fn(WasmtimeCaller<'_>, &mut [MaybeUninit<ValRaw>]) -> Result<()> {
328bfdbd10aSAlex Crichton let foreign = crate::ForeignData { data, finalizer };
329bfdbd10aSAlex Crichton move |caller, values| {
3308bec98daSAlex Crichton let _ = &foreign; // move entire foreign into this closure
331bfdbd10aSAlex Crichton let mut caller = wasmtime_caller_t { caller };
3328c349a3dSAlex Crichton match callback(
3338c349a3dSAlex Crichton foreign.data,
3348c349a3dSAlex Crichton &mut caller,
3358c349a3dSAlex Crichton values.as_mut_ptr().cast(),
3368c349a3dSAlex Crichton values.len(),
3378c349a3dSAlex Crichton ) {
338bfdbd10aSAlex Crichton None => Ok(()),
3392afaac51SAlex Crichton Some(trap) => Err(trap.error),
340bfdbd10aSAlex Crichton }
341bfdbd10aSAlex Crichton }
342bfdbd10aSAlex Crichton }
343bfdbd10aSAlex Crichton
344ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_call( mut store: WasmtimeStoreContextMut<'_>, func: &Func, args: *const wasmtime_val_t, nargs: usize, results: *mut MaybeUninit<wasmtime_val_t>, nresults: usize, trap_ret: &mut *mut wasm_trap_t, ) -> Option<Box<wasmtime_error_t>>3457a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasmtime_func_call(
346420fc3d1SNick Fitzgerald mut store: WasmtimeStoreContextMut<'_>,
3477a1b7cdfSAlex Crichton func: &Func,
3487a1b7cdfSAlex Crichton args: *const wasmtime_val_t,
3497a1b7cdfSAlex Crichton nargs: usize,
3507a1b7cdfSAlex Crichton results: *mut MaybeUninit<wasmtime_val_t>,
3517a1b7cdfSAlex Crichton nresults: usize,
3527a1b7cdfSAlex Crichton trap_ret: &mut *mut wasm_trap_t,
3537a1b7cdfSAlex Crichton ) -> Option<Box<wasmtime_error_t>> {
3549187f2d9SAlex Crichton let mut scope = RootScope::new(&mut store);
3559187f2d9SAlex Crichton let mut params = mem::take(&mut scope.as_context_mut().data_mut().wasm_val_storage);
356bcf35449SAlex Crichton let (wt_params, wt_results) = translate_args(
357bcf35449SAlex Crichton &mut params,
358bcf35449SAlex Crichton crate::slice_from_raw_parts(args, nargs)
3597a1b7cdfSAlex Crichton .iter()
3609187f2d9SAlex Crichton .map(|i| i.to_val(&mut scope)),
361bcf35449SAlex Crichton nresults,
362bcf35449SAlex Crichton );
3637a1b7cdfSAlex Crichton
3647a1b7cdfSAlex Crichton // We're calling arbitrary code here most of the time, and we in general
3657a1b7cdfSAlex Crichton // want to try to insulate callers against bugs in wasmtime/wasi/etc if we
3667a1b7cdfSAlex Crichton // can. As a result we catch panics here and transform them to traps to
3677a1b7cdfSAlex Crichton // allow the caller to have any insulation possible against Rust panics.
368bcf35449SAlex Crichton let result = panic::catch_unwind(AssertUnwindSafe(|| {
3699187f2d9SAlex Crichton func.call(&mut scope, wt_params, wt_results)
370bcf35449SAlex Crichton }));
3717a1b7cdfSAlex Crichton match result {
372bcf35449SAlex Crichton Ok(Ok(())) => {
3737a1b7cdfSAlex Crichton let results = crate::slice_from_raw_parts_mut(results, nresults);
374bcf35449SAlex Crichton for (slot, val) in results.iter_mut().zip(wt_results.iter()) {
3750c0153c1SNick Fitzgerald crate::initialize(slot, wasmtime_val_t::from_val(&mut scope, *val));
3767a1b7cdfSAlex Crichton }
377bcf35449SAlex Crichton params.truncate(0);
3789187f2d9SAlex Crichton scope.as_context_mut().data_mut().wasm_val_storage = params;
379a9455a8eSNick Fitzgerald None
380a9455a8eSNick Fitzgerald }
3819c73a448SAlex Crichton Ok(Err(trap)) => store_err(trap, trap_ret),
3822afaac51SAlex Crichton Err(panic) => {
3832afaac51SAlex Crichton let err = error_from_panic(panic);
3842afaac51SAlex Crichton *trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(err)));
3857a1b7cdfSAlex Crichton None
3867a1b7cdfSAlex Crichton }
3877a1b7cdfSAlex Crichton }
3887a1b7cdfSAlex Crichton }
3897a1b7cdfSAlex Crichton
390ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_call_unchecked( store: WasmtimeStoreContextMut<'_>, func: &Func, args_and_results: *mut ValRaw, args_and_results_len: usize, trap_ret: &mut *mut wasm_trap_t, ) -> Option<Box<wasmtime_error_t>>391bfdbd10aSAlex Crichton pub unsafe extern "C" fn wasmtime_func_call_unchecked(
392420fc3d1SNick Fitzgerald store: WasmtimeStoreContextMut<'_>,
393bfdbd10aSAlex Crichton func: &Func,
394bfdbd10aSAlex Crichton args_and_results: *mut ValRaw,
395913efdf2SNick Fitzgerald args_and_results_len: usize,
3969c73a448SAlex Crichton trap_ret: &mut *mut wasm_trap_t,
3979c73a448SAlex Crichton ) -> Option<Box<wasmtime_error_t>> {
3988995bcc4SAlex Crichton let slice = std::ptr::slice_from_raw_parts_mut(args_and_results, args_and_results_len);
3998995bcc4SAlex Crichton match func.call_unchecked(store, slice) {
4009c73a448SAlex Crichton Ok(()) => None,
4019c73a448SAlex Crichton Err(trap) => store_err(trap, trap_ret),
4029c73a448SAlex Crichton }
4039c73a448SAlex Crichton }
4049c73a448SAlex Crichton
store_err(err: Error, trap_ret: &mut *mut wasm_trap_t) -> Option<Box<wasmtime_error_t>>4059c73a448SAlex Crichton fn store_err(err: Error, trap_ret: &mut *mut wasm_trap_t) -> Option<Box<wasmtime_error_t>> {
406*0dbb6f3dSChris Fallin if err.is::<Trap>() || err.is::<wasmtime::ThrownException>() {
4079c73a448SAlex Crichton *trap_ret = Box::into_raw(Box::new(wasm_trap_t::new(err)));
4089c73a448SAlex Crichton None
4099c73a448SAlex Crichton } else {
4109c73a448SAlex Crichton Some(Box::new(wasmtime_error_t::from(err)))
411bfdbd10aSAlex Crichton }
412bfdbd10aSAlex Crichton }
413bfdbd10aSAlex Crichton
414ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_type( store: WasmtimeStoreContext<'_>, func: &Func, ) -> Box<wasm_functype_t>4157a1b7cdfSAlex Crichton pub extern "C" fn wasmtime_func_type(
416420fc3d1SNick Fitzgerald store: WasmtimeStoreContext<'_>,
4177a1b7cdfSAlex Crichton func: &Func,
4187a1b7cdfSAlex Crichton ) -> Box<wasm_functype_t> {
4197a1b7cdfSAlex Crichton Box::new(wasm_functype_t::new(func.ty(store)))
4207a1b7cdfSAlex Crichton }
4217a1b7cdfSAlex Crichton
422ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_caller_context<'a>( caller: &'a mut wasmtime_caller_t, ) -> WasmtimeStoreContextMut<'a>4237a1b7cdfSAlex Crichton pub extern "C" fn wasmtime_caller_context<'a>(
4247a1b7cdfSAlex Crichton caller: &'a mut wasmtime_caller_t,
425420fc3d1SNick Fitzgerald ) -> WasmtimeStoreContextMut<'a> {
4267a1b7cdfSAlex Crichton caller.caller.as_context_mut()
4277a1b7cdfSAlex Crichton }
4287a1b7cdfSAlex Crichton
429ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_caller_export_get( caller: &mut wasmtime_caller_t, name: *const u8, name_len: usize, item: &mut MaybeUninit<wasmtime_extern_t>, ) -> bool4307a1b7cdfSAlex Crichton pub unsafe extern "C" fn wasmtime_caller_export_get(
4317a1b7cdfSAlex Crichton caller: &mut wasmtime_caller_t,
4327a1b7cdfSAlex Crichton name: *const u8,
4337a1b7cdfSAlex Crichton name_len: usize,
4347a1b7cdfSAlex Crichton item: &mut MaybeUninit<wasmtime_extern_t>,
4357a1b7cdfSAlex Crichton ) -> bool {
4367a1b7cdfSAlex Crichton let name = match str::from_utf8(crate::slice_from_raw_parts(name, name_len)) {
4377a1b7cdfSAlex Crichton Ok(name) => name,
4387a1b7cdfSAlex Crichton Err(_) => return false,
4397a1b7cdfSAlex Crichton };
4407a1b7cdfSAlex Crichton let which = match caller.caller.get_export(name) {
4417a1b7cdfSAlex Crichton Some(item) => item,
4427a1b7cdfSAlex Crichton None => return false,
4437a1b7cdfSAlex Crichton };
4447a1b7cdfSAlex Crichton crate::initialize(item, which.into());
4457a1b7cdfSAlex Crichton true
446a9455a8eSNick Fitzgerald }
447bfdbd10aSAlex Crichton
448ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_from_raw( store: WasmtimeStoreContextMut<'_>, raw: *mut c_void, func: &mut Func, )449bfdbd10aSAlex Crichton pub unsafe extern "C" fn wasmtime_func_from_raw(
450420fc3d1SNick Fitzgerald store: WasmtimeStoreContextMut<'_>,
451ec92f8e4SAlex Crichton raw: *mut c_void,
452bfdbd10aSAlex Crichton func: &mut Func,
453bfdbd10aSAlex Crichton ) {
454bfdbd10aSAlex Crichton *func = Func::from_raw(store, raw).unwrap();
455bfdbd10aSAlex Crichton }
456bfdbd10aSAlex Crichton
457ae84e6edSAlex Crichton #[unsafe(no_mangle)]
wasmtime_func_to_raw( store: WasmtimeStoreContextMut<'_>, func: &Func, ) -> *mut c_void458ec92f8e4SAlex Crichton pub unsafe extern "C" fn wasmtime_func_to_raw(
459420fc3d1SNick Fitzgerald store: WasmtimeStoreContextMut<'_>,
460ec92f8e4SAlex Crichton func: &Func,
461ec92f8e4SAlex Crichton ) -> *mut c_void {
462bfdbd10aSAlex Crichton func.to_raw(store)
463bfdbd10aSAlex Crichton }
464