use crate::prelude::*;
use crate::runtime::vm::{
Instance, StoreBox, VMArrayCallHostFuncContext, VMContext, VMOpaqueContext, VMStore,
};
use crate::store::InstanceId;
use crate::type_registry::RegisteredType;
use crate::{FuncType, ValRaw};
use core::ptr::NonNull;
struct TrampolineState<F> {
func: F,
_sig: RegisteredType,
}
unsafe extern "C" fn array_call_shim<F>(
vmctx: NonNull<VMOpaqueContext>,
caller_vmctx: NonNull<VMContext>,
values_vec: NonNull<ValRaw>,
values_vec_len: usize,
) -> bool
where
F: Fn(&mut dyn VMStore, InstanceId, &mut [ValRaw]) -> Result<()> + 'static,
{
unsafe {
Instance::enter_host_from_wasm(caller_vmctx, |store, instance| {
let state = {
let vmctx = VMArrayCallHostFuncContext::from_opaque(vmctx);
vmctx.as_ref().host_state()
};
let state = {
debug_assert!(state.is::<TrampolineState<F>>());
&*(state as *const _ as *const TrampolineState<F>)
};
let mut values_vec = NonNull::slice_from_raw_parts(values_vec, values_vec_len);
let values_vec = values_vec.as_mut();
(state.func)(store, instance, values_vec)
})
}
}
pub fn create_array_call_function<F>(
ft: &FuncType,
func: F,
) -> Result<StoreBox<VMArrayCallHostFuncContext>>
where
F: Fn(&mut dyn VMStore, InstanceId, &mut [ValRaw]) -> Result<()> + Send + Sync + 'static,
{
let array_call = array_call_shim::<F>;
let sig = ft.clone().into_registered_type();
unsafe {
Ok(VMArrayCallHostFuncContext::new(
array_call,
sig.index(),
Box::new(TrampolineState { func, _sig: sig }),
))
}
}