Add implementations for typed func errors to cranelift and llvm

This commit is contained in:
Lachlan Sneff
2019-04-09 15:53:01 -07:00
committed by Syrus
parent 7d09a2ee7e
commit cc656b26a9
9 changed files with 261 additions and 151 deletions

View File

@ -3,7 +3,8 @@ use crate::{
error::CompileResult,
error::RuntimeResult,
module::ModuleInner,
types::{FuncIndex, LocalFuncIndex, Value},
typed_func::Wasm,
types::{FuncIndex, LocalFuncIndex, SigIndex, Value},
vm,
};
@ -95,6 +96,8 @@ pub trait ProtectedCaller: Send + Sync {
_: Token,
) -> RuntimeResult<Vec<Value>>;
fn get_wasm_trampoline(&self, module: &ModuleInner, sig_index: SigIndex) -> Option<Wasm>;
fn get_early_trapper(&self) -> Box<dyn UserTrapper>;
}

View File

@ -13,7 +13,7 @@ use crate::{
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value},
vm,
};
use std::{mem, sync::Arc};
use std::{mem, ptr::NonNull, sync::Arc};
pub(crate) struct InstanceInner {
#[allow(dead_code)]
@ -145,20 +145,26 @@ impl Instance {
}
};
let func_wasm_inner = self
.module
.protected_caller
.get_wasm_trampoline(&self.module, sig_index)
.unwrap();
let func_ptr = match func_index.local_or_import(&self.module.info) {
LocalOrImport::Local(local_func_index) => self
.module
.func_resolver
.get(&self.module, local_func_index)
.unwrap()
.as_ptr(),
LocalOrImport::Import(import_func_index) => {
self.inner.import_backing.vm_functions[import_func_index].func
}
.unwrap(),
LocalOrImport::Import(import_func_index) => NonNull::new(
self.inner.import_backing.vm_functions[import_func_index].func as *mut _,
)
.unwrap(),
};
let typed_func: Func<Args, Rets, Wasm> =
unsafe { Func::from_raw_parts(trampoline, invoke, f as _, ctx, invoke_env) };
unsafe { Func::from_raw_parts(func_wasm_inner, func_ptr, ctx) };
Ok(typed_func)
} else {

View File

@ -23,7 +23,7 @@ mod sig_registry;
pub mod structures;
mod sys;
pub mod table;
mod typed_func;
pub mod typed_func;
pub mod types;
pub mod units;
pub mod vm;

View File

@ -4,10 +4,17 @@ use crate::{
export::{Context, Export, FuncPointer},
import::IsExport,
types::{FuncSig, Type, WasmExternType},
vm::Ctx,
vm::{self, Ctx},
};
use std::{
any::Any, cell::UnsafeCell, ffi::c_void, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc,
any::Any,
cell::UnsafeCell,
ffi::c_void,
fmt,
marker::PhantomData,
mem, panic,
ptr::{self, NonNull},
sync::Arc,
};
thread_local! {
@ -45,20 +52,36 @@ impl fmt::Display for WasmTrapInfo {
pub trait Kind {}
type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
type Invoke = extern "C" fn(
pub type Trampoline = unsafe extern "C" fn(*mut Ctx, NonNull<vm::Func>, *const u64, *mut u64);
pub type Invoke = unsafe extern "C" fn(
Trampoline,
*mut Ctx,
*const c_void,
NonNull<vm::Func>,
*const u64,
*mut u64,
&mut WasmTrapInfo,
*mut WasmTrapInfo,
Option<NonNull<c_void>>,
) -> bool;
#[derive(Copy, Clone)]
pub struct Wasm {
trampoline: Trampoline,
invoke: Invoke,
invoke_env: *mut c_void,
invoke_env: Option<NonNull<c_void>>,
}
impl Wasm {
pub unsafe fn from_raw_parts(
trampoline: Trampoline,
invoke: Invoke,
invoke_env: Option<NonNull<c_void>>,
) -> Self {
Self {
trampoline,
invoke,
invoke_env,
}
}
}
pub struct Host(());
@ -75,7 +98,7 @@ pub trait WasmTypeList {
fn types() -> &'static [Type];
unsafe fn call<Rets>(
self,
f: *const c_void,
f: NonNull<vm::Func>,
wasm: Wasm,
ctx: *mut Ctx,
) -> Result<Rets, WasmTrapInfo>
@ -88,7 +111,7 @@ where
Args: WasmTypeList,
Rets: WasmTypeList,
{
fn to_raw(&self) -> *const c_void;
fn to_raw(&self) -> NonNull<vm::Func>;
}
pub trait TrapEarly<Rets>
@ -128,7 +151,7 @@ where
pub struct Func<'a, Args = (), Rets = (), Inner: Kind = Wasm> {
inner: Inner,
f: *const c_void,
f: NonNull<vm::Func>,
ctx: *mut Ctx,
_phantom: PhantomData<(&'a (), Args, Rets)>,
}
@ -139,18 +162,12 @@ where
Rets: WasmTypeList,
{
pub(crate) unsafe fn from_raw_parts(
trampoline: Trampoline,
invoke: Invoke,
f: *const c_void,
inner: Wasm,
f: NonNull<vm::Func>,
ctx: *mut Ctx,
invoke_env: *mut c_void,
) -> Func<'a, Args, Rets, Wasm> {
Func {
inner: Wasm {
trampoline,
invoke,
invoke_env,
},
inner,
f,
ctx,
_phantom: PhantomData,
@ -214,7 +231,7 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
#[allow(non_snake_case)]
unsafe fn call<Rets: WasmTypeList>(
self,
f: *const c_void,
f: NonNull<vm::Func>,
wasm: Wasm,
ctx: *mut Ctx,
) -> Result<Rets, WasmTrapInfo> {
@ -233,6 +250,7 @@ impl<A: WasmExternType> WasmTypeList for (A,) {
args.as_ptr(),
rets.as_mut().as_mut_ptr(),
&mut trap,
wasm.invoke_env,
) {
Ok(Rets::from_ret_array(rets))
} else {
@ -263,6 +281,7 @@ macro_rules! impl_traits {
type CStruct = $struct_name<$( $x ),*>;
type RetArray = [u64; count_idents!( $( $x ),* )];
fn from_ret_array(array: Self::RetArray) -> Self {
#[allow(non_snake_case)]
let [ $( $x ),* ] = array;
( $( WasmExternType::from_bits($x) ),* )
}
@ -283,7 +302,7 @@ macro_rules! impl_traits {
&[$( $x::TYPE, )*]
}
#[allow(non_snake_case)]
unsafe fn call<Rets: WasmTypeList>(self, f: *const c_void, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, WasmTrapInfo> {
unsafe fn call<Rets: WasmTypeList>(self, f: NonNull<vm::Func>, wasm: Wasm, ctx: *mut Ctx) -> Result<Rets, WasmTrapInfo> {
// type Trampoline = extern "C" fn(*mut Ctx, *const c_void, *const u64, *mut u64);
// type Invoke = extern "C" fn(Trampoline, *mut Ctx, *const c_void, *const u64, *mut u64, &mut WasmTrapInfo) -> bool;
@ -293,7 +312,7 @@ macro_rules! impl_traits {
let mut rets = Rets::empty_ret_array();
let mut trap = WasmTrapInfo::Unknown;
if (wasm.invoke)(wasm.trampoline, ctx, f, args.as_ptr(), rets.as_mut().as_mut_ptr(), &mut trap) {
if (wasm.invoke)(wasm.trampoline, ctx, f, args.as_ptr(), rets.as_mut().as_mut_ptr(), &mut trap, wasm.invoke_env) {
Ok(Rets::from_ret_array(rets))
} else {
Err(trap)
@ -309,7 +328,7 @@ macro_rules! impl_traits {
impl< $( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap> ExternalFunction<($( $x ),*), Rets> for FN {
#[allow(non_snake_case)]
fn to_raw(&self) -> *const c_void {
fn to_raw(&self) -> NonNull<vm::Func> {
assert_eq!(mem::size_of::<Self>(), 0, "you cannot use a closure that captures state for `Func`.");
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
@ -333,7 +352,7 @@ macro_rules! impl_traits {
}
}
wrap::<$( $x, )* Rets, Trap, Self> as *const c_void
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap()
}
}
@ -384,7 +403,7 @@ where
Inner: Kind,
{
fn to_export(&self) -> Export {
let func = unsafe { FuncPointer::new(self.f as _) };
let func = unsafe { FuncPointer::new(self.f.as_ptr()) };
let ctx = Context::Internal;
let signature = Arc::new(FuncSig::new(Args::types(), Rets::types()));