getting rid of wasmer's Type, Value and function-related types

This commit is contained in:
Valery Antopol 2022-03-14 13:21:24 +04:00
parent d9f9288e1e
commit 7fdb10ba5f
15 changed files with 1096 additions and 358 deletions

View File

@ -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"

View File

@ -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()
}
}

View 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);

View File

@ -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)
}
}

View 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!(),
}
}

View 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);
*/

View File

@ -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> {

View File

@ -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>>>>;

View File

@ -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

View File

@ -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)) }
}
}

View File

@ -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)
}
}
}

View File

@ -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 {

View File

@ -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!(),
}
}

View File

@ -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(|_| ()),

View File

@ -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);
Ok((
export_id,
WITFunction::from_export(export_func, export.name.to_string())?,
))
}
let export_func = module_exports.get_dyn_func(export.name)?;
Ok((
export_id,
WITFunction::from_export(export_func, export.name.to_string())?,
))
})
.collect()
}