diff --git a/crates/wasm-backend-traits/Cargo.toml b/crates/wasm-backend-traits/Cargo.toml index 8f55d4e1..55a90fad 100644 --- a/crates/wasm-backend-traits/Cargo.toml +++ b/crates/wasm-backend-traits/Cargo.toml @@ -14,4 +14,6 @@ wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" } 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" } \ No newline at end of file +wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" } + +tuple_list = "0.1.0" \ No newline at end of file diff --git a/crates/wasm-backend-traits/src/lib.rs b/crates/wasm-backend-traits/src/lib.rs index d7c51dbc..331a4328 100644 --- a/crates/wasm-backend-traits/src/lib.rs +++ b/crates/wasm-backend-traits/src/lib.rs @@ -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 for WValue { + fn from(value: i32) -> Self { + WValue::I32(value) + } +} + +impl From for WValue { + fn from(value: i64) -> Self { + WValue::I64(value) + } +} + +impl From for WValue { + fn from(value: f32) -> Self { + WValue::F32(value) + } +} + +impl From 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; type Wasi: WasiImplementation; type Namespace: Namespace; - type ExportContext: ExportContext; + type ExportContext: for<'c> ExportContext<'c, Self>; + type ExportedDynFunc: ExportedDynFunc; fn compile(wasm: &[u8]) -> WasmBackendResult; } @@ -61,15 +142,17 @@ pub trait Instance { } pub trait Exports { - 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; + ) -> wasmer_core::error::ResolveResult< + Box 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 wasmer_core::error::RuntimeResult + 'a>>; + ) -> wasmer_core::error::ResolveResult<::ExportedDynFunc>; } pub enum Export { @@ -125,13 +208,9 @@ pub trait Memory { } pub trait DynamicFunc<'a, WB: WasmBackend> { - fn new<'c, F>(sig: std::sync::Arc, func: F) -> Self + fn new<'c, F>(sig: FuncSig, func: F) -> Self where - F: Fn( - &mut ::ExportContext, - &[wasmer_core::types::Value], - ) -> Vec - + 'static; + F: Fn(&mut ::ExportContext, &[WValue]) -> Vec + 'static; } pub trait Namespace: LikeNamespace { @@ -142,14 +221,46 @@ pub trait Namespace: LikeNamespace { pub trait LikeNamespace {} -pub trait ExportContext { +pub trait ExportContext<'c, WB: WasmBackend> { fn memory(&self, memory_index: u32) -> ::WITMemory; - unsafe fn get_export_func_by_name<'a, Args, Rets>( - &mut self, + unsafe fn get_export_func_by_name( + &'c mut self, name: &str, - ) -> Result, wasmer_runtime::error::ResolveError> + ) -> Result Result + '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 { + fn signature(&self) -> &FuncSig; + + fn call(&self, args: &[WValue]) -> CallResult>; +} + +pub struct FuncSig { + params: Cow<'static, [WType]>, + returns: Cow<'static, [WType]>, +} + +impl FuncSig { + pub fn new(params: Params, returns: Returns) -> Self + where + Params: Into>, + Returns: Into>, + { + Self { + params: params.into(), + returns: returns.into(), + } + } + + pub fn params(&self) -> impl Iterator { + self.params.iter() + } + + pub fn returns(&self) -> impl Iterator { + self.returns.iter() + } } diff --git a/crates/wasm-backend-traits/src/wasm_type_list.rs b/crates/wasm-backend-traits/src/wasm_type_list.rs new file mode 100644 index 00000000..b8638aa2 --- /dev/null +++ b/crates/wasm-backend-traits/src/wasm_type_list.rs @@ -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 + 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( + self, + f: std::ptr::NonNull, + wasm: wasmer_core::typed_func::Wasm, + ctx: *mut wasmer_core::vm::Ctx, + ) -> Result + 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( + self, + f: NonNull, + wasm: Wasm, + ctx: *mut vm::Ctx, + ) -> Result + 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); + diff --git a/crates/wasmer-backend/src/lib.rs b/crates/wasmer-backend/src/lib.rs index 88adc6ed..d6b7c0b6 100644 --- a/crates/wasmer-backend/src/lib.rs +++ b/crates/wasmer-backend/src/lib.rs @@ -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 { wasmer_runtime::compile(wasm) @@ -231,30 +244,31 @@ impl WasiImplementation for WasmerWasiImplementation { } impl Exports for WasmerInstance { - fn get<'a, T: wasmer_core::export::Exportable<'a>>( - &'a self, - name: &str, - ) -> wasmer_core::error::ResolveResult { - 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 wasmer_core::error::RuntimeResult + 'a>, + Box wasmer_core::error::RuntimeResult<()> + 'a>, > { + self.instance.exports.get::>(name).map(|func| { + let func: Box 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<::ExportedDynFunc> { self.instance .exports - .get::>(name) - .map(|func| { - let func: Box wasmer_core::error::RuntimeResult + 'a> = - Box::new( - move || -> wasmer_core::error::RuntimeResult { - func.call() - }, - ); - func + .get::>(name) + .map(|func| unsafe { + WasmerExportedDynFunc { + sig: FuncSigConverter(func.signature()).into(), + func: std::mem::transmute::, DynFunc<'static>>(func), + } }) } } @@ -320,16 +334,12 @@ pub struct WasmerDynamicFunc { } impl<'a> DynamicFunc<'a, WasmerBackend> for WasmerDynamicFunc { - fn new(sig: Arc, func: F) -> Self + fn new(sig: FuncSig, func: F) -> Self where - F: Fn( - &mut WasmerExportContext<'static>, - &[wasmer_core::prelude::Value], - ) -> Vec - + 'static, + F: Fn(&mut WasmerExportContext<'static>, &[WValue]) -> Vec + '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::>(); + 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 for WasmerExportContext<'c> { +impl<'c> ExportContext<'c, WasmerBackend> for WasmerExportContext<'static> { fn memory(&self, memory_index: u32) -> ::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( + &'c mut self, name: &str, - ) -> Result, ResolveError> + ) -> Result Result + '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 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 = ::types(); + let ret_types = ::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::::types()*/ret_types.to_vec(), }); } @@ -443,9 +459,78 @@ impl<'c> ExportContext 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 { + args.into_c_struct() + .call::(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 for WasmerExportedDynFunc<'a> { + fn signature(&self) -> &FuncSig { + &self.sig + } + + fn call(&self, args: &[WValue]) -> CallResult> { + 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::>(), + ) + .map(|rets| rets.iter().map(wval_to_general_wval).collect()) + } +} + +struct FuncSigConverter<'a, T>(&'a T); + +impl<'a> From> for WasmerFuncSig { + fn from(sig: FuncSigConverter<'a, FuncSig>) -> Self { + let params = sig + .0 + .params() + .map(type_converters::general_wtype_to_wtype) + .collect::>(); + let returns = sig + .0 + .returns() + .map(type_converters::general_wtype_to_wtype) + .collect::>(); + Self::new(params, returns) + } +} + +impl<'a> From> for FuncSig { + fn from(sig: FuncSigConverter<'a, WasmerFuncSig>) -> Self { + let params = sig + .0 + .params() + .iter() + .map(type_converters::wtype_to_general_wtype) + .collect::>(); + let returns = sig + .0 + .returns() + .iter() + .map(type_converters::wtype_to_general_wtype) + .collect::>(); + Self::new(params, returns) } } diff --git a/crates/wasmer-backend/src/type_converters.rs b/crates/wasmer-backend/src/type_converters.rs new file mode 100644 index 00000000..35139f0c --- /dev/null +++ b/crates/wasmer-backend/src/type_converters.rs @@ -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!(), + } +} diff --git a/crates/wasmer-backend/src/wasm_type_list.rs b/crates/wasmer-backend/src/wasm_type_list.rs new file mode 100644 index 00000000..51af0ffe --- /dev/null +++ b/crates/wasmer-backend/src/wasm_type_list.rs @@ -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); + + + +impl wasmer_core::typed_func::WasmTypeList for Helper { + 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(self, + f: NonNull, + wasm: Wasm, + ctx: *mut Ctx + ) -> Result 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( + self, + f: NonNull, + wasm: Wasm, + ctx: *mut vm::Ctx, + ) -> Result + 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 for FN + where + $( $x: WasmExternType, )* + Rets: WasmTypeList, + Trap: TrapEarly, + FN: Fn(&mut vm::Ctx $( , $x )*) -> Trap + 'static + Send, + { + #[allow(non_snake_case)] + fn to_raw(self) -> (NonNull, Option>) { + // 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, + 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_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 = 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) + }, + // 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> = + // `FN` is a function pointer, or a closure + // _without_ a captured environment. + if mem::size_of::() == 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 for FN + where + $( $x: WasmExternType, )* + Rets: WasmTypeList, + Trap: TrapEarly, + FN: Fn($( $x, )*) -> Trap + 'static + Send, + { + #[allow(non_snake_case)] + fn to_raw(self) -> (NonNull, Option>) { + // 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, + 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_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 = 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) + }, + // 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> = + // `FN` is a function pointer, or a closure + // _without_ a captured environment. + if mem::size_of::() == 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 { + #[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); + +*/ \ No newline at end of file diff --git a/runtime/src/host_imports/imports.rs b/runtime/src/host_imports/imports.rs index f753ac8c..d3308789 100644 --- a/runtime/src/host_imports/imports.rs +++ b/runtime/src/host_imports/imports.rs @@ -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( } }; - ::DynamicFunc::new( - std::sync::Arc::new(FuncSig::new(raw_args, raw_output)), - func, - ) + ::DynamicFunc::new(FuncSig::new(raw_args, raw_output), func) } fn default_error_handler(err: &HostImportError) -> Option { diff --git a/runtime/src/host_imports/mod.rs b/runtime/src/host_imports/mod.rs index 58590b55..1aec60c6 100644 --- a/runtime/src/host_imports/mod.rs +++ b/runtime/src/host_imports/mod.rs @@ -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 = std::result::Result; pub(self) type WasmModuleFunc = Box>>>; diff --git a/runtime/src/module/marine_module.rs b/runtime/src/module/marine_module.rs index 39ffd940..de7fe3a5 100644 --- a/runtime/src/module/marine_module.rs +++ b/runtime/src/module/marine_module.rs @@ -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 = Interpreter< ITInstance, @@ -148,7 +150,7 @@ impl MModule { // 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 MModule { I1: Iterator, I2: Iterator, { - 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::>(); let outputs = outputs.map(itype_to_wtype).collect::>(); - ::DynamicFunc::new( - Arc::new(FuncSig::new(inputs, outputs)), - raw_import, - ) + ::DynamicFunc::new(FuncSig::new(inputs, outputs), raw_import) } // creates a closure that is represent a IT module import diff --git a/runtime/src/module/memory.rs b/runtime/src/module/memory.rs deleted file mode 100644 index 88bb8c01..00000000 --- a/runtime/src/module/memory.rs +++ /dev/null @@ -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 { - 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 { - let view = &self.0; - let slice: &[Cell] = 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> 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::(); - - unsafe { WITMemoryView(MemoryView::new(base as _, length as u32)) } - } -} diff --git a/runtime/src/module/memory_access.rs b/runtime/src/module/memory_access.rs deleted file mode 100644 index 354d6a2b..00000000 --- a/runtime/src/module/memory_access.rs +++ /dev/null @@ -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], - pub offset: Cell, -} - -pub(crate) struct WasmerSequentialWriter<'s> { - pub offset: usize, - pub slice: &'s [Cell], - pub current_offset: Cell, -} - -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(&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) - } - } -} diff --git a/runtime/src/module/mod.rs b/runtime/src/module/mod.rs index 724fa375..cd22990d 100644 --- a/runtime/src/module/mod.rs +++ b/runtime/src/module/mod.rs @@ -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 { diff --git a/runtime/src/module/type_converters.rs b/runtime/src/module/type_converters.rs index 6c1a1730..e00afdb3 100644 --- a/runtime/src/module/type_converters.rs +++ b/runtime/src/module/type_converters.rs @@ -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!(), } } diff --git a/runtime/src/module/wit_function.rs b/runtime/src/module/wit_function.rs index 1b342b94..cb0df5fc 100644 --- a/runtime/src/module/wit_function.rs +++ b/runtime/src/module/wit_function.rs @@ -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 { Export { - func: Rc>, + func: Rc<::ExportedDynFunc>, }, Import { // TODO: use dyn Callable here @@ -49,24 +49,22 @@ pub(super) struct WITFunction { impl WITFunction { /// Creates functions from a "usual" (not IT) module export. - pub(super) fn from_export(dyn_func: DynFunc<'static>, name: String) -> MResult { + pub(super) fn from_export( + dyn_func: ::ExportedDynFunc, + name: String, + ) -> MResult { 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::>(); - let outputs = signature - .returns() - .iter() - .map(wtype_to_itype) - .collect::>(); + let outputs = signature.returns().map(wtype_to_itype).collect::>(); let inner = WITFunctionInner::Export { func: Rc::new(dyn_func), @@ -128,14 +126,20 @@ impl wasm::structures::LocalImport for WITFunction { } fn call(&self, arguments: &[IValue]) -> std::result::Result, ()> { - 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::>()) - .map(|result| result.iter().map(wval_to_ival).collect()) - .map_err(|_| ()), + .call( + arguments + .iter() + .map(ival_to_wval) + .collect::>() + .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(|_| ()), diff --git a/runtime/src/module/wit_instance.rs b/runtime/src/module/wit_instance.rs index abec2314..92bffdd1 100644 --- a/runtime/src/module/wit_instance.rs +++ b/runtime/src/module/wit_instance.rs @@ -78,24 +78,16 @@ impl ITInstance { wasmer_instance: &::I, it: &MITInterfaces<'_>, ) -> MResult>> { - 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<'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() }