use crate::prelude::*;
use crate::runtime::vm::{
StoreBox, VMArrayCallHostFuncContext, VMContext, VMFuncRef, VMOpaqueContext,
};
use crate::type_registry::RegisteredType;
use crate::{FuncType, ValRaw};
use anyhow::Result;
use core::ptr;
struct TrampolineState<F> {
func: F,
#[allow(dead_code)]
sig: RegisteredType,
}
unsafe extern "C" fn array_call_shim<F>(
vmctx: *mut VMOpaqueContext,
caller_vmctx: *mut VMOpaqueContext,
values_vec: *mut ValRaw,
values_vec_len: usize,
) where
F: Fn(*mut VMContext, &mut [ValRaw]) -> Result<()> + 'static,
{
let result = crate::runtime::vm::catch_unwind_and_longjmp(|| {
let vmctx = VMArrayCallHostFuncContext::from_opaque(vmctx);
let state = (*vmctx).host_state();
debug_assert!(state.is::<TrampolineState<F>>());
let state = &*(state as *const _ as *const TrampolineState<F>);
let values_vec = core::slice::from_raw_parts_mut(values_vec, values_vec_len);
(state.func)(VMContext::from_opaque(caller_vmctx), values_vec)
});
match result {
Ok(()) => {}
Err(trap) => crate::trap::raise(trap.into()),
}
}
pub fn create_array_call_function<F>(
ft: &FuncType,
func: F,
) -> Result<StoreBox<VMArrayCallHostFuncContext>>
where
F: Fn(*mut VMContext, &mut [ValRaw]) -> Result<()> + Send + Sync + 'static,
{
let array_call = array_call_shim::<F>;
let sig = ft.clone().into_registered_type();
unsafe {
Ok(VMArrayCallHostFuncContext::new(
VMFuncRef {
array_call,
wasm_call: None,
type_index: sig.index(),
vmctx: ptr::null_mut(),
},
Box::new(TrampolineState { func, sig }),
))
}
}