mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-25 10:22:19 +00:00
Starting to set up protected call in clif-backend
This commit is contained in:
parent
705708cafe
commit
539db9f577
@ -14,3 +14,8 @@ hashbrown = "0.1"
|
|||||||
target-lexicon = "0.2.0"
|
target-lexicon = "0.2.0"
|
||||||
wasmparser = "0.23.0"
|
wasmparser = "0.23.0"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
nix = "0.12.0"
|
||||||
|
# We depend on libffi for now.
|
||||||
|
# This will be removed asap.
|
||||||
|
libffi = "0.6.4"
|
||||||
|
|
||||||
|
125
lib/clif-backend/src/call/mod.rs
Normal file
125
lib/clif-backend/src/call/mod.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
mod recovery;
|
||||||
|
mod sighandler;
|
||||||
|
|
||||||
|
use crate::call::recovery::call_protected;
|
||||||
|
use wasmer_runtime::{
|
||||||
|
backend::{Token, ProtectedCaller},
|
||||||
|
types::{FuncIndex, Value, Type, FuncSig, LocalOrImport},
|
||||||
|
module::ModuleInner,
|
||||||
|
error::{RuntimeResult},
|
||||||
|
export::Context,
|
||||||
|
vm::{self, ImportBacking},
|
||||||
|
};
|
||||||
|
use libffi::high::{arg as libffi_arg, call as libffi_call, CodePtr};
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
pub struct Caller {
|
||||||
|
func_export_set: HashSet<FuncIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Caller {
|
||||||
|
pub fn new(module: &ModuleInner) -> Self {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProtectedCaller for Caller {
|
||||||
|
fn call(
|
||||||
|
&self,
|
||||||
|
module: &ModuleInner,
|
||||||
|
func_index: FuncIndex,
|
||||||
|
params: &[Value],
|
||||||
|
returns: &mut [Value],
|
||||||
|
import_backing: &ImportBacking,
|
||||||
|
vmctx: *mut vm::Ctx,
|
||||||
|
_: Token,
|
||||||
|
) -> RuntimeResult<()> {
|
||||||
|
let (func_ptr, ctx, signature) = get_func_from_index(&module, import_backing, func_index);
|
||||||
|
|
||||||
|
let vmctx_ptr = match ctx {
|
||||||
|
Context::External(external_vmctx) => external_vmctx,
|
||||||
|
Context::Internal => vmctx,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(self.func_export_set.contains(&func_index));
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
returns.len() == signature.returns.len() && signature.returns.len() <= 1,
|
||||||
|
"multi-value returns not yet supported"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(signature.check_sig(params), "incorrect signature");
|
||||||
|
|
||||||
|
let libffi_args: Vec<_> = params
|
||||||
|
.iter()
|
||||||
|
.map(|val| match val {
|
||||||
|
Value::I32(ref x) => libffi_arg(x),
|
||||||
|
Value::I64(ref x) => libffi_arg(x),
|
||||||
|
Value::F32(ref x) => libffi_arg(x),
|
||||||
|
Value::F64(ref x) => libffi_arg(x),
|
||||||
|
})
|
||||||
|
.chain(iter::once(libffi_arg(&vmctx_ptr)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let code_ptr = CodePtr::from_ptr(func_ptr as _);
|
||||||
|
|
||||||
|
call_protected(|| {
|
||||||
|
// Only supports zero or one return values for now.
|
||||||
|
// To support multiple returns, we will have to
|
||||||
|
// generate trampolines instead of using libffi.
|
||||||
|
match signature.returns.first() {
|
||||||
|
Some(ty) => {
|
||||||
|
let val = match ty {
|
||||||
|
Type::I32 => Value::I32(unsafe { libffi_call(code_ptr, &libffi_args) }),
|
||||||
|
Type::I64 => Value::I64(unsafe { libffi_call(code_ptr, &libffi_args) }),
|
||||||
|
Type::F32 => Value::F32(unsafe { libffi_call(code_ptr, &libffi_args) }),
|
||||||
|
Type::F64 => Value::F64(unsafe { libffi_call(code_ptr, &libffi_args) }),
|
||||||
|
};
|
||||||
|
returns[0] = val;
|
||||||
|
},
|
||||||
|
// call with no returns
|
||||||
|
None => unsafe {
|
||||||
|
libffi_call::<()>(code_ptr, &libffi_args);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn get_func_from_index<'a>(
|
||||||
|
module: &'a ModuleInner,
|
||||||
|
import_backing: &ImportBacking,
|
||||||
|
func_index: FuncIndex,
|
||||||
|
) -> (*const vm::Func, Context, &'a FuncSig) {
|
||||||
|
let sig_index = *module
|
||||||
|
.func_assoc
|
||||||
|
.get(func_index)
|
||||||
|
.expect("broken invariant, incorrect func index");
|
||||||
|
|
||||||
|
let (func_ptr, ctx) = match func_index.local_or_import(module) {
|
||||||
|
LocalOrImport::Local(local_func_index) => {
|
||||||
|
(
|
||||||
|
module
|
||||||
|
.func_resolver
|
||||||
|
.get(&module, local_func_index)
|
||||||
|
.expect("broken invariant, func resolver not synced with module.exports")
|
||||||
|
.cast()
|
||||||
|
.as_ptr() as *const _,
|
||||||
|
Context::Internal,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
|
let imported_func = import_backing.imported_func(imported_func_index);
|
||||||
|
(
|
||||||
|
imported_func.func as *const _,
|
||||||
|
Context::External(imported_func.vmctx),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let signature = module.sig_registry.lookup_func_sig(sig_index);
|
||||||
|
|
||||||
|
(func_ptr, ctx, signature)
|
||||||
|
}
|
@ -4,10 +4,10 @@
|
|||||||
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
|
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
|
||||||
//! unless you have memory unsafety elsewhere in your code.
|
//! unless you have memory unsafety elsewhere in your code.
|
||||||
|
|
||||||
use crate::{
|
use wasmer_runtime::{
|
||||||
error::{RuntimeError, RuntimeResult},
|
error::{RuntimeError, RuntimeResult},
|
||||||
sighandler::install_sighandler,
|
|
||||||
};
|
};
|
||||||
|
use crate::call::sighandler::install_sighandler;
|
||||||
use nix::libc::siginfo_t;
|
use nix::libc::siginfo_t;
|
||||||
use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
|
use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! Please read more about this here: https://github.com/CraneStation/wasmtime/issues/15
|
//! Please read more about this here: https://github.com/CraneStation/wasmtime/issues/15
|
||||||
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
|
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
|
||||||
use crate::recovery;
|
use crate::call::recovery;
|
||||||
use nix::libc::{c_void, siginfo_t};
|
use nix::libc::{c_void, siginfo_t};
|
||||||
use nix::sys::signal::{
|
use nix::sys::signal::{
|
||||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
@ -5,6 +5,7 @@ mod module;
|
|||||||
mod module_env;
|
mod module_env;
|
||||||
mod relocation;
|
mod relocation;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
mod call;
|
||||||
|
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
isa,
|
isa,
|
||||||
|
@ -7,7 +7,6 @@ build = "build/mod.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hashbrown = "0.1"
|
hashbrown = "0.1"
|
||||||
libffi = "0.6.4"
|
|
||||||
nix = "0.12.0"
|
nix = "0.12.0"
|
||||||
page_size = "0.4.1"
|
page_size = "0.4.1"
|
||||||
errno = "0.2.4"
|
errno = "0.2.4"
|
||||||
|
@ -2,6 +2,7 @@ use crate::{
|
|||||||
error::CompileResult,
|
error::CompileResult,
|
||||||
error::RuntimeResult,
|
error::RuntimeResult,
|
||||||
module::ModuleInner,
|
module::ModuleInner,
|
||||||
|
backing::ImportBacking,
|
||||||
types::{FuncIndex, LocalFuncIndex, Value},
|
types::{FuncIndex, LocalFuncIndex, Value},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
@ -54,6 +55,7 @@ pub trait ProtectedCaller {
|
|||||||
func_index: FuncIndex,
|
func_index: FuncIndex,
|
||||||
params: &[Value],
|
params: &[Value],
|
||||||
returns: &mut [Value],
|
returns: &mut [Value],
|
||||||
|
import_backing: &ImportBacking,
|
||||||
vmctx: *mut vm::Ctx,
|
vmctx: *mut vm::Ctx,
|
||||||
_: Token,
|
_: Token,
|
||||||
) -> RuntimeResult<()>;
|
) -> RuntimeResult<()>;
|
||||||
@ -62,13 +64,9 @@ pub trait ProtectedCaller {
|
|||||||
pub trait FuncResolver {
|
pub trait FuncResolver {
|
||||||
/// This returns a pointer to the function designated by the `local_func_index`
|
/// This returns a pointer to the function designated by the `local_func_index`
|
||||||
/// parameter.
|
/// parameter.
|
||||||
///
|
|
||||||
/// The existance of the Token parameter ensures that this can only be called from
|
|
||||||
/// within the runtime crate.
|
|
||||||
fn get(
|
fn get(
|
||||||
&self,
|
&self,
|
||||||
module: &ModuleInner,
|
module: &ModuleInner,
|
||||||
local_func_index: LocalFuncIndex,
|
local_func_index: LocalFuncIndex,
|
||||||
_: Token,
|
|
||||||
) -> Option<NonNull<vm::Func>>;
|
) -> Option<NonNull<vm::Func>>;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::Token,
|
|
||||||
error::{LinkError, LinkResult},
|
error::{LinkError, LinkResult},
|
||||||
export::{Context, Export},
|
export::{Context, Export},
|
||||||
import::Imports,
|
import::Imports,
|
||||||
@ -179,17 +178,14 @@ impl LocalBacking {
|
|||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
let func_data = match func_index.local_or_import(module) {
|
let func_data = match func_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_func_index) => {
|
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
||||||
let token = Token::generate();
|
|
||||||
vm::ImportedFunc {
|
|
||||||
func: module
|
func: module
|
||||||
.func_resolver
|
.func_resolver
|
||||||
.get(module, local_func_index, token)
|
.get(module, local_func_index)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_ptr(),
|
.as_ptr(),
|
||||||
vmctx,
|
vmctx,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
imports.functions[imported_func_index].clone()
|
imports.functions[imported_func_index].clone()
|
||||||
}
|
}
|
||||||
@ -233,17 +229,14 @@ impl LocalBacking {
|
|||||||
let sig_id = vm::SigId(sig_index.index() as u32);
|
let sig_id = vm::SigId(sig_index.index() as u32);
|
||||||
|
|
||||||
let func_data = match func_index.local_or_import(module) {
|
let func_data = match func_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_func_index) => {
|
LocalOrImport::Local(local_func_index) => vm::ImportedFunc {
|
||||||
let token = Token::generate();
|
|
||||||
vm::ImportedFunc {
|
|
||||||
func: module
|
func: module
|
||||||
.func_resolver
|
.func_resolver
|
||||||
.get(module, local_func_index, token)
|
.get(module, local_func_index)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_ptr(),
|
.as_ptr(),
|
||||||
vmctx,
|
vmctx,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
imports.functions[imported_func_index].clone()
|
imports.functions[imported_func_index].clone()
|
||||||
}
|
}
|
||||||
@ -322,6 +315,10 @@ impl ImportBacking {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn imported_func(&self, func_index: ImportedFuncIndex) -> vm::ImportedFunc {
|
||||||
|
self.functions[func_index].clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imported_memory(&self, memory_index: ImportedMemoryIndex) -> vm::ImportedMemory {
|
pub fn imported_memory(&self, memory_index: ImportedMemoryIndex) -> vm::ImportedMemory {
|
||||||
self.memories[memory_index].clone()
|
self.memories[memory_index].clone()
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use crate::recovery::call_protected;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::Token,
|
backend::Token,
|
||||||
backing::{ImportBacking, LocalBacking},
|
backing::{ImportBacking, LocalBacking},
|
||||||
@ -10,13 +9,12 @@ use crate::{
|
|||||||
module::{ExportIndex, Module, ModuleInner},
|
module::{ExportIndex, Module, ModuleInner},
|
||||||
types::{
|
types::{
|
||||||
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, Memory, MemoryIndex, Table,
|
FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, Memory, MemoryIndex, Table,
|
||||||
TableIndex, Type, Value,
|
TableIndex, Value,
|
||||||
},
|
},
|
||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
use libffi::high::{arg as libffi_arg, call as libffi_call, CodePtr};
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{iter, mem};
|
use std::mem;
|
||||||
|
|
||||||
pub(crate) struct InstanceInner {
|
pub(crate) struct InstanceInner {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -122,7 +120,7 @@ impl Instance {
|
|||||||
let mut returns = vec![Value::I32(0); signature.returns.len()];
|
let mut returns = vec![Value::I32(0); signature.returns.len()];
|
||||||
|
|
||||||
let vmctx = match func_index.local_or_import(&self.module) {
|
let vmctx = match func_index.local_or_import(&self.module) {
|
||||||
LocalOrImport::Local(local_func_index) => &mut *self.inner.vmctx,
|
LocalOrImport::Local(_) => &mut *self.inner.vmctx,
|
||||||
LocalOrImport::Import(imported_func_index) => {
|
LocalOrImport::Import(imported_func_index) => {
|
||||||
self.inner.import_backing.functions[imported_func_index].vmctx
|
self.inner.import_backing.functions[imported_func_index].vmctx
|
||||||
}
|
}
|
||||||
@ -135,61 +133,12 @@ impl Instance {
|
|||||||
func_index,
|
func_index,
|
||||||
args,
|
args,
|
||||||
&mut returns,
|
&mut returns,
|
||||||
|
&self.inner.import_backing,
|
||||||
vmctx,
|
vmctx,
|
||||||
token,
|
token,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(returns)
|
Ok(returns)
|
||||||
|
|
||||||
// let (func_ref, ctx, signature) = self.inner.get_func_from_index(&self.module, func_index);
|
|
||||||
|
|
||||||
// let func_ptr = CodePtr::from_ptr(func_ref.inner() as _);
|
|
||||||
// let vmctx_ptr = match ctx {
|
|
||||||
// Context::External(vmctx) => vmctx,
|
|
||||||
// Context::Internal => &mut *self.inner.vmctx,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// assert!(
|
|
||||||
// signature.returns.len() <= 1,
|
|
||||||
// "multi-value returns not yet supported"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// if !signature.check_sig(args) {
|
|
||||||
// Err(CallError::Signature {
|
|
||||||
// expected: signature.clone(),
|
|
||||||
// found: args.iter().map(|val| val.ty()).collect(),
|
|
||||||
// })?
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let libffi_args: Vec<_> = args
|
|
||||||
// .iter()
|
|
||||||
// .map(|val| match val {
|
|
||||||
// Value::I32(ref x) => libffi_arg(x),
|
|
||||||
// Value::I64(ref x) => libffi_arg(x),
|
|
||||||
// Value::F32(ref x) => libffi_arg(x),
|
|
||||||
// Value::F64(ref x) => libffi_arg(x),
|
|
||||||
// })
|
|
||||||
// .chain(iter::once(libffi_arg(&vmctx_ptr)))
|
|
||||||
// .collect();
|
|
||||||
|
|
||||||
// Ok(call_protected(|| {
|
|
||||||
// signature
|
|
||||||
// .returns
|
|
||||||
// .first()
|
|
||||||
// .map(|ty| match ty {
|
|
||||||
// Type::I32 => Value::I32(unsafe { libffi_call(func_ptr, &libffi_args) }),
|
|
||||||
// Type::I64 => Value::I64(unsafe { libffi_call(func_ptr, &libffi_args) }),
|
|
||||||
// Type::F32 => Value::F32(unsafe { libffi_call(func_ptr, &libffi_args) }),
|
|
||||||
// Type::F64 => Value::F64(unsafe { libffi_call(func_ptr, &libffi_args) }),
|
|
||||||
// })
|
|
||||||
// .or_else(|| {
|
|
||||||
// // call with no returns
|
|
||||||
// unsafe {
|
|
||||||
// libffi_call::<()>(func_ptr, &libffi_args);
|
|
||||||
// }
|
|
||||||
// None
|
|
||||||
// })
|
|
||||||
// })?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,11 +202,10 @@ impl InstanceInner {
|
|||||||
|
|
||||||
let (func_ptr, ctx) = match func_index.local_or_import(module) {
|
let (func_ptr, ctx) = match func_index.local_or_import(module) {
|
||||||
LocalOrImport::Local(local_func_index) => {
|
LocalOrImport::Local(local_func_index) => {
|
||||||
let token = Token::generate();
|
|
||||||
(
|
(
|
||||||
module
|
module
|
||||||
.func_resolver
|
.func_resolver
|
||||||
.get(&module, local_func_index, token)
|
.get(&module, local_func_index)
|
||||||
.expect("broken invariant, func resolver not synced with module.exports")
|
.expect("broken invariant, func resolver not synced with module.exports")
|
||||||
.cast()
|
.cast()
|
||||||
.as_ptr() as *const _,
|
.as_ptr() as *const _,
|
||||||
@ -387,7 +335,7 @@ impl Namespace for Instance {
|
|||||||
|
|
||||||
// TODO Remove this later, only needed for compilation till emscripten is updated
|
// TODO Remove this later, only needed for compilation till emscripten is updated
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn memory_offset_addr(&self, index: usize, offset: usize) -> *const u8 {
|
pub fn memory_offset_addr(&self, _index: usize, _offset: usize) -> *const u8 {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,7 @@ pub mod instance;
|
|||||||
pub mod memory;
|
pub mod memory;
|
||||||
mod mmap;
|
mod mmap;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
mod recovery;
|
|
||||||
mod sig_registry;
|
mod sig_registry;
|
||||||
mod sighandler;
|
|
||||||
pub mod structures;
|
pub mod structures;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
@ -159,7 +159,7 @@ pub trait LocalImport {
|
|||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
macro_rules! define_map_index {
|
macro_rules! define_map_index {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct $ty (u32);
|
pub struct $ty (u32);
|
||||||
impl TypedIndex for $ty {
|
impl TypedIndex for $ty {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user