mirror of
https://github.com/fluencelabs/marine.git
synced 2025-03-15 05:50:49 +00:00
getting rid of wasmer's Type, Value and function-related types
This commit is contained in:
parent
d9f9288e1e
commit
7fdb10ba5f
@ -15,3 +15,5 @@ wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" }
|
||||
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] }
|
||||
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" }
|
||||
|
||||
tuple_list = "0.1.0"
|
@ -1,13 +1,93 @@
|
||||
//pub mod errors;
|
||||
//pub mod it_memory_traits;
|
||||
//pub mod wasm_type_list;
|
||||
|
||||
//pub use wasm_type_list::WasmTypeList;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Display;
|
||||
//use std::fmt::Display;
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
use wasmer_core::types::FuncSig;
|
||||
use it_memory_traits::{SequentialMemoryView};
|
||||
//use wasmer_it::IValue;
|
||||
|
||||
pub struct Value {}
|
||||
//use wasmer_core::types::FuncSig;
|
||||
use wasmer_core::error::CallResult;
|
||||
use wasmer_core::typed_func::WasmTypeList;
|
||||
use wasmer_core::types::WasmExternType;
|
||||
//use wasmer_core::typed_func::WasmTypeList;
|
||||
//use wasmer_core::types::FuncSig as Wasme;
|
||||
//pub use tuple_list::Tuple;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum WValue {
|
||||
/// The `i32` type.
|
||||
I32(i32),
|
||||
/// The `i64` type.
|
||||
I64(i64),
|
||||
/// The `f32` type.
|
||||
F32(f32),
|
||||
/// The `f64` type.
|
||||
F64(f64),
|
||||
// /// The `v128` type.
|
||||
//V128(u128),
|
||||
}
|
||||
|
||||
impl From<i32> for WValue {
|
||||
fn from(value: i32) -> Self {
|
||||
WValue::I32(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for WValue {
|
||||
fn from(value: i64) -> Self {
|
||||
WValue::I64(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for WValue {
|
||||
fn from(value: f32) -> Self {
|
||||
WValue::F32(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for WValue {
|
||||
fn from(value: f64) -> Self {
|
||||
WValue::F64(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum WType {
|
||||
/// The `i32` type.
|
||||
I32,
|
||||
/// The `i64` type.
|
||||
I64,
|
||||
/// The `f32` type.
|
||||
F32,
|
||||
/// The `f64` type.
|
||||
F64,
|
||||
// /// The `v128` type.
|
||||
// V128,
|
||||
}
|
||||
|
||||
impl WValue {
|
||||
pub fn to_u128(&self) -> u128 {
|
||||
match *self {
|
||||
Self::I32(x) => x as u128,
|
||||
Self::I64(x) => x as u128,
|
||||
Self::F32(x) => f32::to_bits(x) as u128,
|
||||
Self::F64(x) => f64::to_bits(x) as u128,
|
||||
//Self::V128(x) => x,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for WType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WasmBackendError {
|
||||
@ -31,7 +111,8 @@ pub trait WasmBackend: Clone + 'static {
|
||||
type I: Instance<Self>;
|
||||
type Wasi: WasiImplementation<Self>;
|
||||
type Namespace: Namespace<Self>;
|
||||
type ExportContext: ExportContext<Self>;
|
||||
type ExportContext: for<'c> ExportContext<'c, Self>;
|
||||
type ExportedDynFunc: ExportedDynFunc<Self>;
|
||||
|
||||
fn compile(wasm: &[u8]) -> WasmBackendResult<Self::M>;
|
||||
}
|
||||
@ -61,15 +142,17 @@ pub trait Instance<WB: WasmBackend> {
|
||||
}
|
||||
|
||||
pub trait Exports<WB: WasmBackend> {
|
||||
fn get<'a, T: wasmer_core::export::Exportable<'a>>(
|
||||
fn get_func_no_args_no_rets<'a>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
) -> wasmer_core::error::ResolveResult<T>;
|
||||
) -> wasmer_core::error::ResolveResult<
|
||||
Box<dyn Fn() -> wasmer_core::error::RuntimeResult<()> + 'a>,
|
||||
>;
|
||||
|
||||
fn get_func_no_args<'a, Rets: wasmer_core::typed_func::WasmTypeList + 'a>(
|
||||
fn get_dyn_func<'a>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
) -> wasmer_core::error::ResolveResult<Box<dyn Fn() -> wasmer_core::error::RuntimeResult<Rets> + 'a>>;
|
||||
) -> wasmer_core::error::ResolveResult<<WB as WasmBackend>::ExportedDynFunc>;
|
||||
}
|
||||
|
||||
pub enum Export<M: MemoryExport, F: FunctionExport> {
|
||||
@ -125,13 +208,9 @@ pub trait Memory<WB: WasmBackend> {
|
||||
}
|
||||
|
||||
pub trait DynamicFunc<'a, WB: WasmBackend> {
|
||||
fn new<'c, F>(sig: std::sync::Arc<FuncSig>, func: F) -> Self
|
||||
fn new<'c, F>(sig: FuncSig, func: F) -> Self
|
||||
where
|
||||
F: Fn(
|
||||
&mut <WB as WasmBackend>::ExportContext,
|
||||
&[wasmer_core::types::Value],
|
||||
) -> Vec<wasmer_core::types::Value>
|
||||
+ 'static;
|
||||
F: Fn(&mut <WB as WasmBackend>::ExportContext, &[WValue]) -> Vec<WValue> + 'static;
|
||||
}
|
||||
|
||||
pub trait Namespace<WB: WasmBackend>: LikeNamespace<WB> {
|
||||
@ -142,14 +221,46 @@ pub trait Namespace<WB: WasmBackend>: LikeNamespace<WB> {
|
||||
|
||||
pub trait LikeNamespace<WB: WasmBackend> {}
|
||||
|
||||
pub trait ExportContext<WB: WasmBackend> {
|
||||
pub trait ExportContext<'c, WB: WasmBackend> {
|
||||
fn memory(&self, memory_index: u32) -> <WB as WasmBackend>::WITMemory;
|
||||
|
||||
unsafe fn get_export_func_by_name<'a, Args, Rets>(
|
||||
&mut self,
|
||||
unsafe fn get_export_func_by_name<Args, Rets>(
|
||||
&'c mut self,
|
||||
name: &str,
|
||||
) -> Result<wasmer_runtime::Func<'a, Args, Rets>, wasmer_runtime::error::ResolveError>
|
||||
) -> Result<Box<dyn FnMut(Args) -> Result<Rets, wasmer_runtime::error::RuntimeError> + 'c>, wasmer_runtime::error::ResolveError>
|
||||
where
|
||||
Args: wasmer_core::typed_func::WasmTypeList,
|
||||
Rets: wasmer_core::typed_func::WasmTypeList;
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList;
|
||||
}
|
||||
|
||||
pub trait ExportedDynFunc<WB: WasmBackend> {
|
||||
fn signature(&self) -> &FuncSig;
|
||||
|
||||
fn call(&self, args: &[WValue]) -> CallResult<Vec<WValue>>;
|
||||
}
|
||||
|
||||
pub struct FuncSig {
|
||||
params: Cow<'static, [WType]>,
|
||||
returns: Cow<'static, [WType]>,
|
||||
}
|
||||
|
||||
impl FuncSig {
|
||||
pub fn new<Params, Returns>(params: Params, returns: Returns) -> Self
|
||||
where
|
||||
Params: Into<Cow<'static, [WType]>>,
|
||||
Returns: Into<Cow<'static, [WType]>>,
|
||||
{
|
||||
Self {
|
||||
params: params.into(),
|
||||
returns: returns.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn params(&self) -> impl Iterator<Item = &WType> {
|
||||
self.params.iter()
|
||||
}
|
||||
|
||||
pub fn returns(&self) -> impl Iterator<Item = &WType> {
|
||||
self.returns.iter()
|
||||
}
|
||||
}
|
||||
|
272
crates/wasm-backend-traits/src/wasm_type_list.rs
Normal file
272
crates/wasm-backend-traits/src/wasm_type_list.rs
Normal file
@ -0,0 +1,272 @@
|
||||
//use wasmer_core::types::NativeWasmType;
|
||||
use crate::WType;
|
||||
use crate::WValue;
|
||||
|
||||
|
||||
/// Represents a native wasm type.
|
||||
pub unsafe trait NativeWasmType: Copy + Into<WValue>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// Type for this `NativeWasmType`.
|
||||
const TYPE: WType;
|
||||
|
||||
/// Convert from u64 bites to self.
|
||||
fn from_binary(bits: u64) -> Self;
|
||||
|
||||
/// Convert self to u64 binary representation.
|
||||
fn to_binary(self) -> u64;
|
||||
}
|
||||
|
||||
unsafe impl NativeWasmType for i32 {
|
||||
const TYPE: WType = WType::I32;
|
||||
|
||||
fn from_binary(bits: u64) -> Self {
|
||||
bits as _
|
||||
}
|
||||
|
||||
fn to_binary(self) -> u64 {
|
||||
self as _
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl NativeWasmType for i64 {
|
||||
const TYPE: WType = WType::I64;
|
||||
|
||||
fn from_binary(bits: u64) -> Self {
|
||||
bits as _
|
||||
}
|
||||
|
||||
fn to_binary(self) -> u64 {
|
||||
self as _
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl NativeWasmType for f32 {
|
||||
const TYPE: WType = WType::F32;
|
||||
|
||||
fn from_binary(bits: u64) -> Self {
|
||||
f32::from_bits(bits as u32)
|
||||
}
|
||||
|
||||
fn to_binary(self) -> u64 {
|
||||
self.to_bits() as _
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl NativeWasmType for f64 {
|
||||
const TYPE: WType = WType::F64;
|
||||
|
||||
fn from_binary(bits: u64) -> Self {
|
||||
f64::from_bits(bits)
|
||||
}
|
||||
|
||||
fn to_binary(self) -> u64 {
|
||||
self.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub unsafe trait WasmExternType: Copy
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// Native wasm type for this `WasmExternType`.
|
||||
type Native: NativeWasmType;
|
||||
|
||||
/// Convert from given `Native` type to self.
|
||||
fn from_native(native: Self::Native) -> Self;
|
||||
|
||||
/// Convert self to `Native` type.
|
||||
fn to_native(self) -> Self::Native;
|
||||
}
|
||||
|
||||
/// Represents a list of WebAssembly values.
|
||||
pub trait WasmTypeList {
|
||||
/// CStruct type.
|
||||
type CStruct;
|
||||
|
||||
/// Array of return values.
|
||||
type RetArray: AsMut<[u64]>;
|
||||
|
||||
const NTypes: usize;
|
||||
const Types: [WType];
|
||||
|
||||
/// Construct `Self` based on an array of returned values.
|
||||
fn from_ret_array(array: Self::RetArray) -> Self;
|
||||
|
||||
/// Generates an empty array that will hold the returned values of
|
||||
/// the WebAssembly function.
|
||||
fn empty_ret_array() -> Self::RetArray;
|
||||
|
||||
/// Transforms C values into Rust values.
|
||||
fn from_c_struct(c_struct: Self::CStruct) -> Self;
|
||||
|
||||
/// Transforms Rust values into C values.
|
||||
fn into_c_struct(self) -> Self::CStruct;
|
||||
|
||||
/// Get types of the current values.
|
||||
fn types() -> &'static [WType];
|
||||
|
||||
/*
|
||||
/// This method is used to distribute the values onto a function,
|
||||
/// e.g. `(1, 2).call(func, …)`. This form is unlikely to be used
|
||||
/// directly in the code, see the `Func::call` implementation.
|
||||
unsafe fn call<Rets>(
|
||||
self,
|
||||
f: std::ptr::NonNull<wasmer_core::vm::Func>,
|
||||
wasm: wasmer_core::typed_func::Wasm,
|
||||
ctx: *mut wasmer_core::vm::Ctx,
|
||||
) -> Result<Rets, wasmer_core::error::RuntimeError>
|
||||
where
|
||||
Rets: WasmTypeList;*/
|
||||
}
|
||||
|
||||
|
||||
macro_rules! impl_traits {
|
||||
( [$repr:ident] $struct_name:ident, $( $x:ident ),* ) => {
|
||||
/// Struct for typed funcs.
|
||||
#[repr($repr)]
|
||||
pub struct $struct_name< $( $x ),* > ( $( <$x as WasmExternType>::Native ),* )
|
||||
where
|
||||
$( $x: WasmExternType ),*;
|
||||
|
||||
#[allow(unused_parens)]
|
||||
impl< $( $x ),* > WasmTypeList for ( $( $x ),* )
|
||||
where
|
||||
$( $x: WasmExternType ),*
|
||||
{
|
||||
type CStruct = $struct_name<$( $x ),*>;
|
||||
|
||||
type RetArray = [u64; count_idents!( $( $x ),* )];
|
||||
|
||||
const NTypes: usize = count_idents!( $( $x ),* );
|
||||
const Types: [WType] = [$( $x::Native::TYPE ),*];
|
||||
|
||||
fn from_ret_array(array: Self::RetArray) -> Self {
|
||||
#[allow(non_snake_case)]
|
||||
let [ $( $x ),* ] = array;
|
||||
|
||||
( $( WasmExternType::from_native(NativeWasmType::from_binary($x)) ),* )
|
||||
}
|
||||
|
||||
fn empty_ret_array() -> Self::RetArray {
|
||||
[0; count_idents!( $( $x ),* )]
|
||||
}
|
||||
|
||||
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
||||
#[allow(non_snake_case)]
|
||||
let $struct_name ( $( $x ),* ) = c_struct;
|
||||
|
||||
( $( WasmExternType::from_native($x) ),* )
|
||||
}
|
||||
|
||||
#[allow(unused_parens, non_snake_case)]
|
||||
fn into_c_struct(self) -> Self::CStruct {
|
||||
let ( $( $x ),* ) = self;
|
||||
|
||||
$struct_name ( $( WasmExternType::to_native($x) ),* )
|
||||
}
|
||||
|
||||
fn types() -> &'static [WType] {
|
||||
&Self::Types
|
||||
}
|
||||
|
||||
/*
|
||||
#[allow(unused_parens, non_snake_case)]
|
||||
unsafe fn call<Rets>(
|
||||
self,
|
||||
f: NonNull<vm::Func>,
|
||||
wasm: Wasm,
|
||||
ctx: *mut vm::Ctx,
|
||||
) -> Result<Rets, RuntimeError>
|
||||
where
|
||||
Rets: WasmTypeList
|
||||
{
|
||||
let ( $( $x ),* ) = self;
|
||||
let args = [ $( $x.to_native().to_binary()),* ];
|
||||
let mut rets = Rets::empty_ret_array();
|
||||
let mut error_out = None;
|
||||
|
||||
if (wasm.invoke)(
|
||||
wasm.trampoline,
|
||||
ctx,
|
||||
f,
|
||||
args.as_ptr(),
|
||||
rets.as_mut().as_mut_ptr(),
|
||||
&mut error_out,
|
||||
wasm.invoke_env
|
||||
) {
|
||||
Ok(Rets::from_ret_array(rets))
|
||||
} else {
|
||||
Err(error_out.map_or_else(|| RuntimeError::InvokeError(InvokeError::FailedWithNoError), Into::into))
|
||||
}
|
||||
}*/
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! count_idents {
|
||||
( $($idents:ident),* ) => {{
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
enum Idents { $($idents,)* __CountIdentsLast }
|
||||
const COUNT: usize = Idents::__CountIdentsLast as usize;
|
||||
COUNT
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! wasm_extern_type {
|
||||
($type:ty => $native_type:ty) => {
|
||||
unsafe impl WasmExternType for $type {
|
||||
type Native = $native_type;
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
native as _
|
||||
}
|
||||
|
||||
fn to_native(self) -> Self::Native {
|
||||
self as _
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wasm_extern_type!(i8 => i32);
|
||||
wasm_extern_type!(u8 => i32);
|
||||
wasm_extern_type!(i16 => i32);
|
||||
wasm_extern_type!(u16 => i32);
|
||||
wasm_extern_type!(i32 => i32);
|
||||
wasm_extern_type!(u32 => i32);
|
||||
wasm_extern_type!(i64 => i64);
|
||||
wasm_extern_type!(u64 => i64);
|
||||
wasm_extern_type!(f32 => f32);
|
||||
wasm_extern_type!(f64 => f64);
|
||||
|
||||
impl_traits!([C] S0,);
|
||||
impl_traits!([transparent] S1, A);
|
||||
impl_traits!([C] S2, A, B);
|
||||
impl_traits!([C] S3, A, B, C);
|
||||
impl_traits!([C] S4, A, B, C, D);
|
||||
impl_traits!([C] S5, A, B, C, D, E);
|
||||
impl_traits!([C] S6, A, B, C, D, E, F);
|
||||
impl_traits!([C] S7, A, B, C, D, E, F, G);
|
||||
impl_traits!([C] S8, A, B, C, D, E, F, G, H);
|
||||
impl_traits!([C] S9, A, B, C, D, E, F, G, H, I);
|
||||
impl_traits!([C] S10, A, B, C, D, E, F, G, H, I, J);
|
||||
impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K);
|
||||
impl_traits!([C] S12, A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
impl_traits!([C] S13, A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
impl_traits!([C] S14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
impl_traits!([C] S15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
impl_traits!([C] S16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
impl_traits!([C] S17, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
impl_traits!([C] S18, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
impl_traits!([C] S19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
impl_traits!([C] S20, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
|
||||
impl_traits!([C] S21, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
|
||||
impl_traits!([C] S22, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
|
||||
impl_traits!([C] S23, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
|
||||
impl_traits!([C] S24, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
|
||||
impl_traits!([C] S25, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
|
||||
impl_traits!([C] S26, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
|
||||
|
@ -1,7 +1,6 @@
|
||||
use std::marker::PhantomData;
|
||||
//use std::marker::PhantomData;
|
||||
use marine_wasm_backend_traits::{
|
||||
DynamicFunc, Export, ExportContext, LikeNamespace, Memory, Namespace, Value, WasmBackend,
|
||||
};
|
||||
use marine_wasm_backend_traits::{DynamicFunc, Export, ExportContext, ExportedDynFunc, LikeNamespace, Memory, Namespace, WValue, WasmBackend};
|
||||
use marine_wasm_backend_traits::WasmBackendResult;
|
||||
use marine_wasm_backend_traits::WasmBackendError;
|
||||
use marine_wasm_backend_traits::Module;
|
||||
@ -11,27 +10,40 @@ use marine_wasm_backend_traits::FunctionExport;
|
||||
use marine_wasm_backend_traits::MemoryExport;
|
||||
use marine_wasm_backend_traits::Exports;
|
||||
use marine_wasm_backend_traits::WasiImplementation;
|
||||
use marine_wasm_backend_traits::FuncSig;
|
||||
use marine_wasm_backend_traits::Tuple;
|
||||
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::NonNull;
|
||||
use std::slice::Windows;
|
||||
use std::sync::Arc;
|
||||
use wasmer_core::backend::SigRegistry;
|
||||
use wasmer_core::error::{ResolveError, ResolveResult};
|
||||
use wasmer_core::error::{CallResult, ResolveError, ResolveResult, RuntimeError};
|
||||
use wasmer_core::fault::raw::longjmp;
|
||||
use wasmer_core::Func;
|
||||
use wasmer_core::{DynFunc, Func};
|
||||
use wasmer_core::module::ExportIndex;
|
||||
use wasmer_core::typed_func::WasmTypeList;
|
||||
//use wasmer_core::prelude::vm::Ctx;
|
||||
use wasmer_core::types::{FuncSig, LocalOrImport, WasmExternType};
|
||||
use wasmer_core::prelude::Type;
|
||||
use wasmer_core::prelude::vm::Ctx;
|
||||
use wasmer_core::typed_func::Wasm;
|
||||
use wasmer_core::types::{LocalOrImport, WasmExternType};
|
||||
use wasmer_core::types::FuncSig as WasmerFuncSig;
|
||||
use wasmer_core::typed_func::WasmTypeList as WasmerWasmTypeList;
|
||||
use wasmer_wasi::state::WasiState;
|
||||
use wasmer_it::IValue;
|
||||
|
||||
mod memory_access;
|
||||
mod memory;
|
||||
mod type_converters;
|
||||
mod wasm_type_list;
|
||||
|
||||
//use wasmer_it::interpreter::wasm::structures::{SequentialMemoryView, SequentialReader, SequentialWriter};
|
||||
use crate::memory::WITMemoryView;
|
||||
use crate::memory::WITMemory;
|
||||
use crate::memory_access::{WasmerSequentialReader, WasmerSequentialWriter};
|
||||
use crate::type_converters::{general_wval_to_wval, wval_to_general_wval};
|
||||
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WasmerBackend /*<'a>*/ {
|
||||
@ -53,6 +65,7 @@ impl WasmBackend for WasmerBackend /*<'b>*/ {
|
||||
type DynamicFunc = WasmerDynamicFunc;
|
||||
type Namespace = WasmerNamespace;
|
||||
type ExportContext = WasmerExportContext<'static>;
|
||||
type ExportedDynFunc = WasmerExportedDynFunc<'static>;
|
||||
|
||||
fn compile(wasm: &[u8]) -> WasmBackendResult<WasmerModule> {
|
||||
wasmer_runtime::compile(wasm)
|
||||
@ -231,30 +244,31 @@ impl WasiImplementation<WasmerBackend> for WasmerWasiImplementation {
|
||||
}
|
||||
|
||||
impl Exports<WasmerBackend> for WasmerInstance {
|
||||
fn get<'a, T: wasmer_core::export::Exportable<'a>>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
) -> wasmer_core::error::ResolveResult<T> {
|
||||
self.instance.exports.get(name)
|
||||
}
|
||||
|
||||
fn get_func_no_args<'a, Rets: WasmTypeList + 'a>(
|
||||
fn get_func_no_args_no_rets<'a>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
) -> wasmer_core::error::ResolveResult<
|
||||
Box<dyn Fn() -> wasmer_core::error::RuntimeResult<Rets> + 'a>,
|
||||
Box<dyn Fn() -> wasmer_core::error::RuntimeResult<()> + 'a>,
|
||||
> {
|
||||
self.instance.exports.get::<Func<'a>>(name).map(|func| {
|
||||
let func: Box<dyn Fn() -> wasmer_core::error::RuntimeResult<()> + 'a> =
|
||||
Box::new(move || -> wasmer_core::error::RuntimeResult<()> { func.call() });
|
||||
func
|
||||
})
|
||||
}
|
||||
|
||||
fn get_dyn_func<'a>(
|
||||
&'a self,
|
||||
name: &str,
|
||||
) -> ResolveResult<<WasmerBackend as WasmBackend>::ExportedDynFunc> {
|
||||
self.instance
|
||||
.exports
|
||||
.get::<Func<'a, (), Rets>>(name)
|
||||
.map(|func| {
|
||||
let func: Box<dyn Fn() -> wasmer_core::error::RuntimeResult<Rets> + 'a> =
|
||||
Box::new(
|
||||
move || -> wasmer_core::error::RuntimeResult<Rets> {
|
||||
func.call()
|
||||
},
|
||||
);
|
||||
func
|
||||
.get::<DynFunc<'_>>(name)
|
||||
.map(|func| unsafe {
|
||||
WasmerExportedDynFunc {
|
||||
sig: FuncSigConverter(func.signature()).into(),
|
||||
func: std::mem::transmute::<DynFunc<'_>, DynFunc<'static>>(func),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -320,16 +334,12 @@ pub struct WasmerDynamicFunc {
|
||||
}
|
||||
|
||||
impl<'a> DynamicFunc<'a, WasmerBackend> for WasmerDynamicFunc {
|
||||
fn new<F>(sig: Arc<FuncSig>, func: F) -> Self
|
||||
fn new<F>(sig: FuncSig, func: F) -> Self
|
||||
where
|
||||
F: Fn(
|
||||
&mut WasmerExportContext<'static>,
|
||||
&[wasmer_core::prelude::Value],
|
||||
) -> Vec<wasmer_core::prelude::Value>
|
||||
+ 'static,
|
||||
F: Fn(&mut WasmerExportContext<'static>, &[WValue]) -> Vec<WValue> + 'static,
|
||||
{
|
||||
let func = wasmer_core::typed_func::DynamicFunc::new(
|
||||
sig,
|
||||
std::sync::Arc::new(FuncSigConverter(&sig).into()),
|
||||
move |ctx: &mut wasmer_core::vm::Ctx, args: &[wasmer_core::prelude::Value]| unsafe {
|
||||
let mut ctx = WasmerExportContext {
|
||||
ctx: std::mem::transmute::<
|
||||
@ -338,7 +348,11 @@ impl<'a> DynamicFunc<'a, WasmerBackend> for WasmerDynamicFunc {
|
||||
>(ctx),
|
||||
};
|
||||
|
||||
func(&mut ctx, args)
|
||||
let args = args.iter().map(wval_to_general_wval).collect::<Vec<_>>();
|
||||
func(&mut ctx, &args)
|
||||
.iter()
|
||||
.map(general_wval_to_wval)
|
||||
.collect()
|
||||
},
|
||||
);
|
||||
|
||||
@ -374,18 +388,18 @@ pub struct WasmerExportContext<'c> {
|
||||
ctx: &'c mut wasmer_core::vm::Ctx,
|
||||
}
|
||||
|
||||
impl<'c> ExportContext<WasmerBackend> for WasmerExportContext<'c> {
|
||||
impl<'c> ExportContext<'c, WasmerBackend> for WasmerExportContext<'static> {
|
||||
fn memory(&self, memory_index: u32) -> <WasmerBackend as WasmBackend>::WITMemory {
|
||||
WITMemory(self.ctx.memory(memory_index).clone())
|
||||
}
|
||||
|
||||
unsafe fn get_export_func_by_name<'a, Args, Rets>(
|
||||
&mut self,
|
||||
unsafe fn get_export_func_by_name<Args, Rets>(
|
||||
&'c mut self,
|
||||
name: &str,
|
||||
) -> Result<Func<'a, Args, Rets>, ResolveError>
|
||||
) -> Result<Box<dyn FnMut(Args) -> Result<Rets, RuntimeError> + 'c>, ResolveError>
|
||||
where
|
||||
Args: wasmer_core::typed_func::WasmTypeList,
|
||||
Rets: wasmer_core::typed_func::WasmTypeList,
|
||||
Args: Tuple,
|
||||
Rets: Tuple,
|
||||
{
|
||||
let ctx = &mut self.ctx;
|
||||
let module_inner = &(*ctx.module);
|
||||
@ -417,12 +431,14 @@ impl<'c> ExportContext<WasmerBackend> for WasmerExportContext<'c> {
|
||||
let export_func_signature = &module_inner.info.signatures[export_func_signature_idx];
|
||||
let export_func_signature_ref = SigRegistry.lookup_signature_ref(export_func_signature);
|
||||
|
||||
if export_func_signature_ref.params() != Args::types()
|
||||
|| export_func_signature_ref.returns() != Rets::types()
|
||||
let arg_types = <Args::CStruct as wasmer_core::typed_func::WasmTypeList>::types();
|
||||
let ret_types = <Rets::CStruct as wasmer_core::typed_func::WasmTypeList>::types();
|
||||
if export_func_signature_ref.params() != arg_types//Args::types()
|
||||
|| export_func_signature_ref.returns() != ret_types//Rets::types()
|
||||
{
|
||||
return Err(ResolveError::Signature {
|
||||
expected: (*export_func_signature).clone(),
|
||||
found: Args::types().to_vec(),
|
||||
found: /*Helper::<Args>::types()*/ret_types.to_vec(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -443,9 +459,78 @@ impl<'c> ExportContext<WasmerBackend> for WasmerExportContext<'c> {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let typed_func: Func<'_, Args, Rets, wasmer_core::typed_func::Wasm> =
|
||||
Func::from_raw_parts(func_wasm_inner, export_func_ptr, None, (*ctx) as _);
|
||||
|
||||
Ok(typed_func)
|
||||
let result = Box::new(
|
||||
move |args: Args| -> Result<Rets, RuntimeError> {
|
||||
args.into_c_struct()
|
||||
.call::<Rets::CStruct>(export_func_ptr, func_wasm_inner, *ctx)
|
||||
.map(|rets: Rets| rets.0)
|
||||
}
|
||||
);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WasmerExportedDynFunc<'a> {
|
||||
func: DynFunc<'a>,
|
||||
sig: FuncSig,
|
||||
}
|
||||
|
||||
impl<'a> ExportedDynFunc<WasmerBackend> for WasmerExportedDynFunc<'a> {
|
||||
fn signature(&self) -> &FuncSig {
|
||||
&self.sig
|
||||
}
|
||||
|
||||
fn call(&self, args: &[WValue]) -> CallResult<Vec<WValue>> {
|
||||
use crate::type_converters::general_wval_to_wval;
|
||||
use crate::type_converters::wval_to_general_wval;
|
||||
self.func
|
||||
.call(
|
||||
&args
|
||||
.iter()
|
||||
.map(general_wval_to_wval)
|
||||
.collect::<Vec<wasmer_runtime::Value>>(),
|
||||
)
|
||||
.map(|rets| rets.iter().map(wval_to_general_wval).collect())
|
||||
}
|
||||
}
|
||||
|
||||
struct FuncSigConverter<'a, T>(&'a T);
|
||||
|
||||
impl<'a> From<FuncSigConverter<'a, FuncSig>> for WasmerFuncSig {
|
||||
fn from(sig: FuncSigConverter<'a, FuncSig>) -> Self {
|
||||
let params = sig
|
||||
.0
|
||||
.params()
|
||||
.map(type_converters::general_wtype_to_wtype)
|
||||
.collect::<Vec<_>>();
|
||||
let returns = sig
|
||||
.0
|
||||
.returns()
|
||||
.map(type_converters::general_wtype_to_wtype)
|
||||
.collect::<Vec<_>>();
|
||||
Self::new(params, returns)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<FuncSigConverter<'a, WasmerFuncSig>> for FuncSig {
|
||||
fn from(sig: FuncSigConverter<'a, WasmerFuncSig>) -> Self {
|
||||
let params = sig
|
||||
.0
|
||||
.params()
|
||||
.iter()
|
||||
.map(type_converters::wtype_to_general_wtype)
|
||||
.collect::<Vec<_>>();
|
||||
let returns = sig
|
||||
.0
|
||||
.returns()
|
||||
.iter()
|
||||
.map(type_converters::wtype_to_general_wtype)
|
||||
.collect::<Vec<_>>();
|
||||
Self::new(params, returns)
|
||||
}
|
||||
}
|
||||
|
65
crates/wasmer-backend/src/type_converters.rs
Normal file
65
crates/wasmer-backend/src/type_converters.rs
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// Contains converters of types and values between Wasmer and wasmer_interface_types.
|
||||
use wasmer_runtime::Value as WValue;
|
||||
use wasmer_runtime::types::Type as WType;
|
||||
|
||||
use marine_wasm_backend_traits::WValue as GeneralWValue;
|
||||
use marine_wasm_backend_traits::WType as GeneralWType;
|
||||
|
||||
pub(super) fn wtype_to_general_wtype(ty: &WType) -> GeneralWType {
|
||||
match ty {
|
||||
WType::I32 => GeneralWType::I32,
|
||||
WType::I64 => GeneralWType::I64,
|
||||
WType::F32 => GeneralWType::F32,
|
||||
WType::F64 => GeneralWType::F64,
|
||||
WType::V128 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn general_wtype_to_wtype(ty: &GeneralWType) -> WType {
|
||||
match ty {
|
||||
GeneralWType::I32 => WType::I32,
|
||||
GeneralWType::I64 => WType::I64,
|
||||
GeneralWType::F32 => WType::F32,
|
||||
GeneralWType::F64 => WType::F64,
|
||||
ty => {
|
||||
eprintln!("trying to convert {:?}", ty);
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn general_wval_to_wval(value: &GeneralWValue) -> WValue {
|
||||
match value {
|
||||
GeneralWValue::I32(v) => WValue::I32(*v),
|
||||
GeneralWValue::I64(v) => WValue::I64(*v),
|
||||
GeneralWValue::F32(v) => WValue::F32(*v),
|
||||
GeneralWValue::F64(v) => WValue::F64(*v),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn wval_to_general_wval(value: &WValue) -> GeneralWValue {
|
||||
match value {
|
||||
WValue::I32(v) => GeneralWValue::I32(*v),
|
||||
WValue::I64(v) => GeneralWValue::I64(*v),
|
||||
WValue::F32(v) => GeneralWValue::F32(*v),
|
||||
WValue::F64(v) => GeneralWValue::F64(*v),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
448
crates/wasmer-backend/src/wasm_type_list.rs
Normal file
448
crates/wasmer-backend/src/wasm_type_list.rs
Normal file
@ -0,0 +1,448 @@
|
||||
use std::ptr::NonNull;
|
||||
use wasmer_core::error::RuntimeError;
|
||||
use wasmer_core::typed_func::{Wasm};
|
||||
use wasmer_core::types::{NativeWasmType, Type};
|
||||
use wasmer_core::vm::Ctx;
|
||||
use marine_wasm_backend_traits::WType;
|
||||
use marine_wasm_backend_traits::WValue;
|
||||
use marine_wasm_backend_traits::Tuple;
|
||||
use marine_wasm_backend_traits::WasmTypeList;
|
||||
|
||||
|
||||
struct Helper<T: WasmTypeList> (T);
|
||||
|
||||
|
||||
|
||||
impl<T: WasmTypeList> wasmer_core::typed_func::WasmTypeList for Helper<T> {
|
||||
type CStruct = T::CStruct;
|
||||
type RetArray = T::RetArray;
|
||||
|
||||
fn from_ret_array(array: Self::RetArray) -> Self {
|
||||
Self(T::from_ret_array(array))
|
||||
}
|
||||
|
||||
fn empty_ret_array() -> Self::RetArray {
|
||||
T::empty_ret_array()
|
||||
}
|
||||
|
||||
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
||||
Self(T::from_c_struct(c_struct))
|
||||
}
|
||||
|
||||
fn into_c_struct(self) -> Self::CStruct {
|
||||
self.into_c_struct()
|
||||
}
|
||||
|
||||
fn types() -> &'static [Type] {
|
||||
T::types() /// how to convert?
|
||||
}
|
||||
|
||||
unsafe fn call<Rets>(self,
|
||||
f: NonNull<wasmer_core::prelude::vm::Func>,
|
||||
wasm: Wasm,
|
||||
ctx: *mut Ctx
|
||||
) -> Result<Rets, RuntimeError> where Rets: wasmer_core::typed_func::WasmTypeList {
|
||||
// how to implement?
|
||||
}
|
||||
}
|
||||
/*
|
||||
const fn gen_types(wtypes: &'static [WType]) -> &'static [Type] {
|
||||
let types = [Type::I32; wtypes.len()];
|
||||
&types
|
||||
}
|
||||
|
||||
macro_rules! impl_traits {
|
||||
( [$repr:ident] $struct_name:ident, $( $x:ident ),* ) => {
|
||||
/// Struct for typed funcs.
|
||||
#[repr($repr)]
|
||||
pub struct $struct_name< $( $x ),* > ( $( <$x as WasmExternType>::Native ),* )
|
||||
where
|
||||
$( $x: WasmExternType ),*;
|
||||
|
||||
#[allow(unused_parens)]
|
||||
impl< $( $x ),* > wasmer_core::typed_func::WasmTypeList for Helper<( $( $x ),* )>
|
||||
where
|
||||
$( $x: WasmExternType ),*
|
||||
{
|
||||
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_native(NativeWasmType::from_binary($x)) ),* )
|
||||
}
|
||||
|
||||
fn empty_ret_array() -> Self::RetArray {
|
||||
[0; count_idents!( $( $x ),* )]
|
||||
}
|
||||
|
||||
fn from_c_struct(c_struct: Self::CStruct) -> Self {
|
||||
#[allow(non_snake_case)]
|
||||
let $struct_name ( $( $x ),* ) = c_struct;
|
||||
|
||||
( $( WasmExternType::from_native($x) ),* )
|
||||
}
|
||||
|
||||
#[allow(unused_parens, non_snake_case)]
|
||||
fn into_c_struct(self) -> Self::CStruct {
|
||||
let ( $( $x ),* ) = self;
|
||||
|
||||
$struct_name ( $( WasmExternType::to_native($x) ),* )
|
||||
}
|
||||
|
||||
fn types() -> &'static [Type] {
|
||||
&[$( $x::Native::WTYPE ),*]
|
||||
}
|
||||
|
||||
/*
|
||||
#[allow(unused_parens, non_snake_case)]
|
||||
unsafe fn call<Rets>(
|
||||
self,
|
||||
f: NonNull<vm::Func>,
|
||||
wasm: Wasm,
|
||||
ctx: *mut vm::Ctx,
|
||||
) -> Result<Rets, RuntimeError>
|
||||
where
|
||||
Rets: WasmTypeList
|
||||
{
|
||||
let ( $( $x ),* ) = self;
|
||||
let args = [ $( $x.to_native().to_binary()),* ];
|
||||
let mut rets = Rets::empty_ret_array();
|
||||
let mut error_out = None;
|
||||
|
||||
if (wasm.invoke)(
|
||||
wasm.trampoline,
|
||||
ctx,
|
||||
f,
|
||||
args.as_ptr(),
|
||||
rets.as_mut().as_mut_ptr(),
|
||||
&mut error_out,
|
||||
wasm.invoke_env
|
||||
) {
|
||||
Ok(Rets::from_ret_array(rets))
|
||||
} else {
|
||||
Err(error_out.map_or_else(|| RuntimeError::InvokeError(InvokeError::FailedWithNoError), Into::into))
|
||||
}
|
||||
}*/
|
||||
}
|
||||
/*
|
||||
#[allow(unused_parens)]
|
||||
impl< $( $x, )* Rets, Trap, FN > HostFunction<ExplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn(&mut vm::Ctx $( , $x )*) -> Trap + 'static + Send,
|
||||
{
|
||||
#[allow(non_snake_case)]
|
||||
fn to_raw(self) -> (NonNull<vm::Func>, Option<NonNull<vm::FuncEnv>>) {
|
||||
// The `wrap` function is a wrapper around the
|
||||
// imported function. It manages the argument passed
|
||||
// to the imported function (in this case, the
|
||||
// `vmctx` along with the regular WebAssembly
|
||||
// arguments), and it manages the trapping.
|
||||
//
|
||||
// It is also required for the LLVM backend to be
|
||||
// able to unwind through this function.
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
vmctx: &vm::Ctx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn(&mut vm::Ctx, $( $x, )*) -> Trap,
|
||||
{
|
||||
// Get the pointer to this `wrap` function.
|
||||
let self_pointer = wrap::<$( $x, )* Rets, Trap, FN> as *const vm::Func;
|
||||
|
||||
// Get the collection of imported functions.
|
||||
let vm_imported_functions = unsafe { &(*vmctx.import_backing).vm_functions };
|
||||
|
||||
// Retrieve the `vm::FuncCtx`.
|
||||
let mut func_ctx: NonNull<vm::FuncCtx> = vm_imported_functions
|
||||
.iter()
|
||||
.find_map(|(_, imported_func)| {
|
||||
if imported_func.func == self_pointer {
|
||||
Some(imported_func.func_ctx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.expect("Import backing is not well-formed, cannot find `func_ctx`.");
|
||||
let func_ctx = unsafe { func_ctx.as_mut() };
|
||||
|
||||
// Extract `vm::Ctx` from `vm::FuncCtx`. The
|
||||
// pointer is always non-null.
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
|
||||
// Extract `vm::FuncEnv` from `vm::FuncCtx`.
|
||||
let func_env = func_ctx.func_env;
|
||||
|
||||
let func: &FN = match func_env {
|
||||
// The imported function is a regular
|
||||
// function, a closure without a captured
|
||||
// environment, or a closure with a captured
|
||||
// environment.
|
||||
Some(func_env) => unsafe {
|
||||
let func: NonNull<FN> = func_env.cast();
|
||||
|
||||
&*func.as_ptr()
|
||||
},
|
||||
|
||||
// This branch is supposed to be unreachable.
|
||||
None => unreachable!()
|
||||
};
|
||||
|
||||
// Catch unwind in case of errors.
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
func(vmctx $( , WasmExternType::from_native($x) )* ).report()
|
||||
// ^^^^^ The imported function
|
||||
// expects `vm::Ctx` as first
|
||||
// argument; provide it.
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
RuntimeError::User(b as Box<dyn Any + Send>)
|
||||
},
|
||||
// TODO(blocking): this line is wrong!
|
||||
Err(err) => RuntimeError::User(err),
|
||||
};
|
||||
|
||||
// At this point, there is an error that needs to
|
||||
// be trapped.
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the captured environment of the imported
|
||||
// function if any.
|
||||
let func_env: Option<NonNull<vm::FuncEnv>> =
|
||||
// `FN` is a function pointer, or a closure
|
||||
// _without_ a captured environment.
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
NonNull::new(&self as *const _ as *mut vm::FuncEnv)
|
||||
}
|
||||
// `FN` is a closure _with_ a captured
|
||||
// environment.
|
||||
else {
|
||||
NonNull::new(Box::into_raw(Box::new(self))).map(NonNull::cast)
|
||||
};
|
||||
|
||||
(
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap(),
|
||||
func_env
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_parens)]
|
||||
impl< $( $x, )* Rets, Trap, FN > HostFunction<ImplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn($( $x, )*) -> Trap + 'static + Send,
|
||||
{
|
||||
#[allow(non_snake_case)]
|
||||
fn to_raw(self) -> (NonNull<vm::Func>, Option<NonNull<vm::FuncEnv>>) {
|
||||
// The `wrap` function is a wrapper around the
|
||||
// imported function. It manages the argument passed
|
||||
// to the imported function (in this case, only the
|
||||
// regular WebAssembly arguments), and it manages the
|
||||
// trapping.
|
||||
//
|
||||
// It is also required for the LLVM backend to be
|
||||
// able to unwind through this function.
|
||||
extern fn wrap<$( $x, )* Rets, Trap, FN>(
|
||||
vmctx: &vm::Ctx $( , $x: <$x as WasmExternType>::Native )*
|
||||
) -> Rets::CStruct
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
Trap: TrapEarly<Rets>,
|
||||
FN: Fn($( $x, )*) -> Trap,
|
||||
{
|
||||
// Get the pointer to this `wrap` function.
|
||||
let self_pointer = wrap::<$( $x, )* Rets, Trap, FN> as *const vm::Func;
|
||||
|
||||
// Get the collection of imported functions.
|
||||
let vm_imported_functions = unsafe { &(*vmctx.import_backing).vm_functions };
|
||||
|
||||
// Retrieve the `vm::FuncCtx`.
|
||||
let mut func_ctx: NonNull<vm::FuncCtx> = vm_imported_functions
|
||||
.iter()
|
||||
.find_map(|(_, imported_func)| {
|
||||
if imported_func.func == self_pointer {
|
||||
Some(imported_func.func_ctx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.expect("Import backing is not well-formed, cannot find `func_ctx`.");
|
||||
let func_ctx = unsafe { func_ctx.as_mut() };
|
||||
|
||||
// Extract `vm::Ctx` from `vm::FuncCtx`. The
|
||||
// pointer is always non-null.
|
||||
let vmctx = unsafe { func_ctx.vmctx.as_mut() };
|
||||
|
||||
// Extract `vm::FuncEnv` from `vm::FuncCtx`.
|
||||
let func_env = func_ctx.func_env;
|
||||
|
||||
let func: &FN = match func_env {
|
||||
// The imported function is a regular
|
||||
// function, a closure without a captured
|
||||
// environment, or a closure with a captured
|
||||
// environment.
|
||||
Some(func_env) => unsafe {
|
||||
let func: NonNull<FN> = func_env.cast();
|
||||
|
||||
&*func.as_ptr()
|
||||
},
|
||||
|
||||
// This branch is supposed to be unreachable.
|
||||
None => unreachable!()
|
||||
};
|
||||
|
||||
// Catch unwind in case of errors.
|
||||
let err = match panic::catch_unwind(
|
||||
panic::AssertUnwindSafe(
|
||||
|| {
|
||||
func($( WasmExternType::from_native($x), )* ).report()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Ok(Ok(returns)) => return returns.into_c_struct(),
|
||||
Ok(Err(err)) => {
|
||||
let b: Box<_> = err.into();
|
||||
RuntimeError::User(b as Box<dyn Any + Send>)
|
||||
},
|
||||
// TODO(blocking): this line is wrong!
|
||||
Err(err) => RuntimeError::User(err),
|
||||
};
|
||||
|
||||
// At this point, there is an error that needs to
|
||||
// be trapped.
|
||||
unsafe {
|
||||
(&*vmctx.module).runnable_module.do_early_trap(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the captured environment of the imported
|
||||
// function if any.
|
||||
let func_env: Option<NonNull<vm::FuncEnv>> =
|
||||
// `FN` is a function pointer, or a closure
|
||||
// _without_ a captured environment.
|
||||
if mem::size_of::<Self>() == 0 {
|
||||
NonNull::new(&self as *const _ as *mut vm::FuncEnv)
|
||||
}
|
||||
// `FN` is a closure _with_ a captured
|
||||
// environment.
|
||||
else {
|
||||
NonNull::new(Box::into_raw(Box::new(self))).map(NonNull::cast)
|
||||
};
|
||||
|
||||
(
|
||||
NonNull::new(wrap::<$( $x, )* Rets, Trap, Self> as *mut vm::Func).unwrap(),
|
||||
func_env
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_parens)]
|
||||
impl<'a $( , $x )*, Rets> Func<'a, ( $( $x ),* ), Rets, Wasm>
|
||||
where
|
||||
$( $x: WasmExternType, )*
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
/// Call the typed func and return results.
|
||||
#[allow(non_snake_case, clippy::too_many_arguments)]
|
||||
pub fn call(&self, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
|
||||
#[allow(unused_parens)]
|
||||
unsafe {
|
||||
<( $( $x ),* ) as WasmTypeList>::call(
|
||||
( $( $x ),* ),
|
||||
self.func,
|
||||
self.inner,
|
||||
self.vmctx
|
||||
)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! count_idents {
|
||||
( $($idents:ident),* ) => {{
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
enum Idents { $($idents,)* __CountIdentsLast }
|
||||
const COUNT: usize = Idents::__CountIdentsLast as usize;
|
||||
COUNT
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! wasm_extern_type {
|
||||
($type:ty => $native_type:ty) => {
|
||||
unsafe impl WasmExternType for $type {
|
||||
type Native = $native_type;
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
native as _
|
||||
}
|
||||
|
||||
fn to_native(self) -> Self::Native {
|
||||
self as _
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
wasm_extern_type!(i8 => i32);
|
||||
wasm_extern_type!(u8 => i32);
|
||||
wasm_extern_type!(i16 => i32);
|
||||
wasm_extern_type!(u16 => i32);
|
||||
wasm_extern_type!(i32 => i32);
|
||||
wasm_extern_type!(u32 => i32);
|
||||
wasm_extern_type!(i64 => i64);
|
||||
wasm_extern_type!(u64 => i64);
|
||||
wasm_extern_type!(f32 => f32);
|
||||
wasm_extern_type!(f64 => f64);
|
||||
|
||||
impl_traits!([C] S0,);
|
||||
impl_traits!([transparent] S1, A);
|
||||
impl_traits!([C] S2, A, B);
|
||||
impl_traits!([C] S3, A, B, C);
|
||||
impl_traits!([C] S4, A, B, C, D);
|
||||
impl_traits!([C] S5, A, B, C, D, E);
|
||||
impl_traits!([C] S6, A, B, C, D, E, F);
|
||||
impl_traits!([C] S7, A, B, C, D, E, F, G);
|
||||
impl_traits!([C] S8, A, B, C, D, E, F, G, H);
|
||||
impl_traits!([C] S9, A, B, C, D, E, F, G, H, I);
|
||||
impl_traits!([C] S10, A, B, C, D, E, F, G, H, I, J);
|
||||
impl_traits!([C] S11, A, B, C, D, E, F, G, H, I, J, K);
|
||||
impl_traits!([C] S12, A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
impl_traits!([C] S13, A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
impl_traits!([C] S14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
impl_traits!([C] S15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
impl_traits!([C] S16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
impl_traits!([C] S17, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
impl_traits!([C] S18, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
impl_traits!([C] S19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
impl_traits!([C] S20, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
|
||||
impl_traits!([C] S21, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
|
||||
impl_traits!([C] S22, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
|
||||
impl_traits!([C] S23, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
|
||||
impl_traits!([C] S24, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
|
||||
impl_traits!([C] S25, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
|
||||
impl_traits!([C] S26, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
|
||||
|
||||
*/
|
@ -31,8 +31,8 @@ use crate::HostImportDescriptor;
|
||||
//use wasmer_core::Func;
|
||||
//use wasmer_core::vm::Ctx;
|
||||
//use wasmer_core::typed_func::DynamicFunc;
|
||||
use wasmer_core::types::Value as WValue;
|
||||
use wasmer_core::types::FuncSig;
|
||||
//use wasmer_core::types::Value as WValue;
|
||||
//use wasmer_core::types::FuncSig;
|
||||
use it_lilo::lifter::ILifter;
|
||||
use it_lilo::lowerer::ILowerer;
|
||||
use it_memory_traits::Memory as ITMemory;
|
||||
@ -40,7 +40,7 @@ use it_memory_traits::Memory as ITMemory;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use marine_wasm_backend_traits::WasmBackend;
|
||||
use marine_wasm_backend_traits::{FuncSig, WasmBackend};
|
||||
use marine_wasm_backend_traits::DynamicFunc;
|
||||
use marine_wasm_backend_traits::ExportContext;
|
||||
|
||||
@ -159,10 +159,7 @@ pub(crate) fn create_host_import_func<WB: WasmBackend>(
|
||||
}
|
||||
};
|
||||
|
||||
<WB as WasmBackend>::DynamicFunc::new(
|
||||
std::sync::Arc::new(FuncSig::new(raw_args, raw_output)),
|
||||
func,
|
||||
)
|
||||
<WB as WasmBackend>::DynamicFunc::new(FuncSig::new(raw_args, raw_output), func)
|
||||
}
|
||||
|
||||
fn default_error_handler(err: &HostImportError) -> Option<crate::IValue> {
|
||||
|
@ -26,8 +26,11 @@ use wasmer_core::Func;
|
||||
pub use errors::HostImportError;
|
||||
pub(crate) use imports::create_host_import_func;
|
||||
|
||||
pub(self) use wasmer_core::types::Value as WValue;
|
||||
pub(self) use wasmer_core::types::Type as WType;
|
||||
//pub(self) use wasmer_core::types::Value as WValue;
|
||||
//pub(self) use wasmer_core::types::Type as WType;
|
||||
|
||||
pub(self) use marine_wasm_backend_traits::WValue;
|
||||
pub(self) use marine_wasm_backend_traits::WType;
|
||||
|
||||
pub(self) type HostImportResult<T> = std::result::Result<T, HostImportError>;
|
||||
pub(self) type WasmModuleFunc<Args, Rets> = Box<RefCell<Option<Func<'static, Args, Rets>>>>;
|
||||
|
@ -46,6 +46,8 @@ use std::convert::TryInto;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::sync::Arc;
|
||||
use std::rc::Rc;
|
||||
//use wasmer_core::types::FuncSig;
|
||||
use marine_wasm_backend_traits::FuncSig;
|
||||
|
||||
type ITInterpreter<WB> = Interpreter<
|
||||
ITInstance<WB>,
|
||||
@ -148,7 +150,7 @@ impl<WB: WasmBackend> MModule<WB> {
|
||||
|
||||
// call _start to populate the WASI state of the module
|
||||
#[rustfmt::skip]
|
||||
if let Ok(start_func) = wasmer_instance.exports().get_func_no_args::<'_, ()>("_start") {
|
||||
if let Ok(start_func) = wasmer_instance.exports().get_func_no_args_no_rets("_start") {
|
||||
start_func()?;
|
||||
}
|
||||
|
||||
@ -326,15 +328,12 @@ impl<WB: WasmBackend> MModule<WB> {
|
||||
I1: Iterator<Item = &'a IType>,
|
||||
I2: Iterator<Item = &'b IType>,
|
||||
{
|
||||
use wasmer_core::types::FuncSig;
|
||||
//use wasmer_core::types::FuncSig;
|
||||
use super::type_converters::itype_to_wtype;
|
||||
|
||||
let inputs = inputs.map(itype_to_wtype).collect::<Vec<_>>();
|
||||
let outputs = outputs.map(itype_to_wtype).collect::<Vec<_>>();
|
||||
<WB as WasmBackend>::DynamicFunc::new(
|
||||
Arc::new(FuncSig::new(inputs, outputs)),
|
||||
raw_import,
|
||||
)
|
||||
<WB as WasmBackend>::DynamicFunc::new(FuncSig::new(inputs, outputs), raw_import)
|
||||
}
|
||||
|
||||
// creates a closure that is represent a IT module import
|
||||
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ops::Deref;
|
||||
use wasmer_it::interpreter::wasm;
|
||||
use wasmer_core::memory::{Memory, MemoryView};
|
||||
use wasmer_core::vm::LocalMemory;
|
||||
use crate::module::WasmerSequentialReader;
|
||||
|
||||
use crate::module::WasmerSequentialWriter;
|
||||
|
||||
use it_memory_traits::{MemoryAccessError};
|
||||
|
||||
pub(crate) struct WITMemoryView<'a>(pub(crate) MemoryView<'a, u8>);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct WITMemory(pub(super) Memory);
|
||||
impl std::ops::Deref for WITMemory {
|
||||
type Target = Memory;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl WITMemoryView<'_> {
|
||||
fn check_bounds(
|
||||
&self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
memory_size: usize,
|
||||
) -> Result<(), MemoryAccessError> {
|
||||
if offset + size >= memory_size {
|
||||
Err(MemoryAccessError::OutOfBounds {
|
||||
offset,
|
||||
size,
|
||||
memory_size,
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'v> wasm::structures::SequentialMemoryView<'v> for WITMemoryView<'s> {
|
||||
type SR = WasmerSequentialReader<'v>;
|
||||
type SW = WasmerSequentialWriter<'v>;
|
||||
|
||||
fn sequential_writer(
|
||||
&'v self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> Result<Self::SW, MemoryAccessError> {
|
||||
let view = &self.0;
|
||||
let slice = view.deref();
|
||||
|
||||
self.check_bounds(offset, size, slice.len())?;
|
||||
|
||||
let writer = WasmerSequentialWriter {
|
||||
offset,
|
||||
slice,
|
||||
current_offset: Cell::new(offset),
|
||||
};
|
||||
|
||||
Ok(writer)
|
||||
}
|
||||
|
||||
fn sequential_reader(
|
||||
&'v self,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> Result<Self::SR, MemoryAccessError> {
|
||||
let view = &self.0;
|
||||
let slice: &[Cell<u8>] = view.deref();
|
||||
|
||||
self.check_bounds(offset, size, slice.len())?;
|
||||
|
||||
let reader = WasmerSequentialReader {
|
||||
memory: slice,
|
||||
offset: Cell::new(offset),
|
||||
};
|
||||
|
||||
Ok(reader)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> wasm::structures::Memory<WITMemoryView<'a>> for WITMemory {
|
||||
fn view(&self) -> WITMemoryView<'a> {
|
||||
let LocalMemory { base, .. } = unsafe { *self.0.vm_local_memory() };
|
||||
let length = self.0.size().bytes().0 / std::mem::size_of::<u8>();
|
||||
|
||||
unsafe { WITMemoryView(MemoryView::new(base as _, length as u32)) }
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
use std::cell::Cell;
|
||||
use it_memory_traits::{SequentialReader, SequentialWriter};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! value_der {
|
||||
($self:expr, $offset:expr, @seq_start $($ids:tt),* @seq_end) => {
|
||||
[$($self.memory[$offset + $ids].get()),+]
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 1) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0 @seq_end);
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 2) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1 @seq_end);
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 4) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3 @seq_end);
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 8) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7 @seq_end);
|
||||
};
|
||||
|
||||
($self:expr, $offset:expr, 16) => {
|
||||
crate::value_der!($self, $offset, @seq_start 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 @seq_end);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! read_ty {
|
||||
($func_name:ident, $ty:ty, 1) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 1));
|
||||
|
||||
self.offset.set(offset + 1);
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 2) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 2));
|
||||
|
||||
self.offset.set(offset + 2);
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 4) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 4));
|
||||
|
||||
self.offset.set(offset + 4);
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 8) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 8));
|
||||
|
||||
self.offset.set(offset + 8);
|
||||
result
|
||||
}
|
||||
};
|
||||
|
||||
($func_name:ident, $ty:ty, 16) => {
|
||||
fn $func_name(&self) -> $ty {
|
||||
let offset = self.offset.get();
|
||||
let result = <$ty>::from_le_bytes(crate::value_der!(self, offset, 16));
|
||||
|
||||
self.offset.set(offset + 16);
|
||||
result
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) struct WasmerSequentialReader<'s> {
|
||||
pub memory: &'s [Cell<u8>],
|
||||
pub offset: Cell<usize>,
|
||||
}
|
||||
|
||||
pub(crate) struct WasmerSequentialWriter<'s> {
|
||||
pub offset: usize,
|
||||
pub slice: &'s [Cell<u8>],
|
||||
pub current_offset: Cell<usize>,
|
||||
}
|
||||
|
||||
impl SequentialReader for WasmerSequentialReader<'_> {
|
||||
fn read_byte(&self) -> u8 {
|
||||
let offset = self.offset.get();
|
||||
let result = self.memory[offset].get();
|
||||
self.offset.set(offset + 1);
|
||||
result
|
||||
}
|
||||
|
||||
// needed because clippy suggests using an iterator which looks worse
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
fn read_bytes<const COUNT: usize>(&self) -> [u8; COUNT] {
|
||||
let offset = self.offset.get();
|
||||
let mut result = [0u8; COUNT];
|
||||
for index in 0..COUNT {
|
||||
result[index] = self.memory[offset + index].get();
|
||||
}
|
||||
|
||||
self.offset.set(offset + COUNT);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl SequentialWriter for WasmerSequentialWriter<'_> {
|
||||
fn start_offset(&self) -> usize {
|
||||
self.offset
|
||||
}
|
||||
|
||||
fn write_u8(&self, value: u8) {
|
||||
let offset = self.current_offset.get();
|
||||
self.slice[offset].set(value);
|
||||
self.current_offset.set(offset + 1);
|
||||
}
|
||||
|
||||
fn write_u32(&self, value: u32) {
|
||||
self.write_bytes(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
fn write_bytes(&self, bytes: &[u8]) {
|
||||
for byte in bytes {
|
||||
self.write_u8(*byte)
|
||||
}
|
||||
}
|
||||
}
|
@ -46,8 +46,10 @@ pub struct MFunctionSignature {
|
||||
}
|
||||
|
||||
pub(crate) use marine_module::MModule;
|
||||
pub(self) use wasmer_core::types::Type as WType;
|
||||
pub(self) use wasmer_core::types::Value as WValue;
|
||||
//pub(self) use wasmer_core::types::Type as WType;
|
||||
//pub(self) use wasmer_core::types::Value as WValue;
|
||||
//pub(self) use marine_wasm_backend_traits::WType;
|
||||
pub(self) use marine_wasm_backend_traits::WValue;
|
||||
|
||||
// types that often used together
|
||||
pub(crate) mod wit_prelude {
|
||||
|
@ -15,7 +15,10 @@
|
||||
*/
|
||||
|
||||
/// Contains converters of types and values between Wasmer and wasmer_interface_types.
|
||||
use super::{WType, WValue, IType, IValue};
|
||||
use super::{IType, IValue};
|
||||
|
||||
use marine_wasm_backend_traits::WType;
|
||||
use marine_wasm_backend_traits::WValue;
|
||||
|
||||
pub(super) fn wtype_to_itype(ty: &WType) -> IType {
|
||||
match ty {
|
||||
@ -23,7 +26,7 @@ pub(super) fn wtype_to_itype(ty: &WType) -> IType {
|
||||
WType::I64 => IType::I64,
|
||||
WType::F32 => IType::F32,
|
||||
WType::F64 => IType::F64,
|
||||
WType::V128 => unimplemented!(),
|
||||
//WType::V128 => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +67,6 @@ pub(super) fn wval_to_ival(value: &WValue) -> IValue {
|
||||
WValue::I64(v) => IValue::I64(*v),
|
||||
WValue::F32(v) => IValue::F32(*v),
|
||||
WValue::F64(v) => IValue::F64(*v),
|
||||
_ => unimplemented!(),
|
||||
//_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
use super::marine_module::MModule;
|
||||
use super::{IType, IFunctionArg, IValue, WValue};
|
||||
use super::{IType, IFunctionArg, IValue};
|
||||
use super::marine_module::Callable;
|
||||
use crate::MResult;
|
||||
|
||||
use marine_wasm_backend_traits::WasmBackend;
|
||||
use marine_wasm_backend_traits::{WasmBackend, WValue};
|
||||
use marine_wasm_backend_traits::ExportedDynFunc;
|
||||
|
||||
use wasmer_it::interpreter::wasm;
|
||||
use wasmer_core::instance::DynFunc;
|
||||
|
||||
// use std::sync::Arc;
|
||||
use std::rc::Rc;
|
||||
@ -30,7 +30,7 @@ use std::rc::Rc;
|
||||
#[derive(Clone)]
|
||||
enum WITFunctionInner<WB: WasmBackend> {
|
||||
Export {
|
||||
func: Rc<DynFunc<'static>>,
|
||||
func: Rc<<WB as WasmBackend>::ExportedDynFunc>,
|
||||
},
|
||||
Import {
|
||||
// TODO: use dyn Callable here
|
||||
@ -49,24 +49,22 @@ pub(super) struct WITFunction<WB: WasmBackend> {
|
||||
|
||||
impl<WB: WasmBackend> WITFunction<WB> {
|
||||
/// Creates functions from a "usual" (not IT) module export.
|
||||
pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult<Self> {
|
||||
pub(super) fn from_export(
|
||||
dyn_func: <WB as WasmBackend>::ExportedDynFunc,
|
||||
name: String,
|
||||
) -> MResult<Self> {
|
||||
use super::type_converters::wtype_to_itype;
|
||||
|
||||
let signature = dyn_func.signature();
|
||||
let arguments = signature
|
||||
.params()
|
||||
.iter()
|
||||
.map(|wtype| IFunctionArg {
|
||||
// here it's considered as an anonymous arguments
|
||||
name: String::new(),
|
||||
ty: wtype_to_itype(wtype),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let outputs = signature
|
||||
.returns()
|
||||
.iter()
|
||||
.map(wtype_to_itype)
|
||||
.collect::<Vec<_>>();
|
||||
let outputs = signature.returns().map(wtype_to_itype).collect::<Vec<_>>();
|
||||
|
||||
let inner = WITFunctionInner::Export {
|
||||
func: Rc::new(dyn_func),
|
||||
@ -128,14 +126,20 @@ impl<WB: WasmBackend> wasm::structures::LocalImport for WITFunction<WB> {
|
||||
}
|
||||
|
||||
fn call(&self, arguments: &[IValue]) -> std::result::Result<Vec<IValue>, ()> {
|
||||
use super::type_converters::{ival_to_wval, wval_to_ival};
|
||||
|
||||
use super::type_converters::wval_to_ival;
|
||||
use super::type_converters::ival_to_wval;
|
||||
match &self.inner {
|
||||
WITFunctionInner::Export { func, .. } => func
|
||||
.as_ref()
|
||||
.call(&arguments.iter().map(ival_to_wval).collect::<Vec<WValue>>())
|
||||
.map(|result| result.iter().map(wval_to_ival).collect())
|
||||
.map_err(|_| ()),
|
||||
.call(
|
||||
arguments
|
||||
.iter()
|
||||
.map(ival_to_wval)
|
||||
.collect::<Vec<WValue>>()
|
||||
.as_slice(),
|
||||
)
|
||||
.map_err(|_| ())
|
||||
.map(|results| results.iter().map(wval_to_ival).collect()),
|
||||
WITFunctionInner::Import { callable, .. } => Rc::make_mut(&mut callable.clone())
|
||||
.call(arguments)
|
||||
.map_err(|_| ()),
|
||||
|
@ -78,24 +78,16 @@ impl<WB: WasmBackend> ITInstance<WB> {
|
||||
wasmer_instance: &<WB as WasmBackend>::I,
|
||||
it: &MITInterfaces<'_>,
|
||||
) -> MResult<HashMap<usize, WITFunction<WB>>> {
|
||||
use wasmer_core::DynFunc;
|
||||
|
||||
let module_exports = &wasmer_instance.exports();
|
||||
|
||||
it.exports()
|
||||
.enumerate()
|
||||
.map(|(export_id, export)| {
|
||||
let export_func = module_exports.get(export.name)?;
|
||||
unsafe {
|
||||
// TODO: refactor this with new Wasmer API when it is ready
|
||||
// here it is safe because dyn func is never lives WITInstance
|
||||
let export_func =
|
||||
std::mem::transmute::<DynFunc<'_>, DynFunc<'static>>(export_func);
|
||||
let export_func = module_exports.get_dyn_func(export.name)?;
|
||||
Ok((
|
||||
export_id,
|
||||
WITFunction::from_export(export_func, export.name.to_string())?,
|
||||
))
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user