From 7915db91c4a7461cf827195e89124b9d91319727 Mon Sep 17 00:00:00 2001 From: Veykril Date: Mon, 27 Jan 2020 14:35:24 +0100 Subject: [PATCH] Add experimental function wrapper macro for linking --- examples/wasm_link.rs | 12 +++----- src/function.rs | 7 +++++ src/lib.rs | 2 ++ src/macros.rs | 66 +++++++++++++++++++++++++++++++++++++++++++ src/module.rs | 8 +++--- src/runtime.rs | 2 +- 6 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 src/macros.rs diff --git a/examples/wasm_link.rs b/examples/wasm_link.rs index 4ad8cbe..db8cd08 100644 --- a/examples/wasm_link.rs +++ b/examples/wasm_link.rs @@ -12,7 +12,7 @@ fn main() { let mut module = rt.load_module(module).map_err(|(_, e)| e).unwrap(); module - .link_function::<(), u64>("time", "millis", Some(millis)) + .link_function::<(), u64>("time", "millis", millis_wrap) .unwrap(); let func = module.find_function::<(), u64>("seconds").unwrap(); println!("{}ms in seconds is {:?}s.", MILLIS, func.call()); @@ -21,11 +21,7 @@ fn main() { const MILLIS: u64 = 500_000; -unsafe extern "C" fn millis( - _rt: ffi::IM3Runtime, - sp: *mut u64, - _mem: *mut std::ffi::c_void, -) -> *const std::ffi::c_void { - *sp = MILLIS; - ffi::m3Err_none as _ +wasm3::make_func_wrapper!(millis_wrap: millis() -> u64); +fn millis() -> u64 { + MILLIS } diff --git a/src/function.rs b/src/function.rs index 7a841e5..67d3064 100644 --- a/src/function.rs +++ b/src/function.rs @@ -6,6 +6,13 @@ use crate::error::{Error, Result}; use crate::runtime::Runtime; use crate::{WasmArgs, WasmType}; +// redefine of ffi::RawCall without the Option around it +pub type RawCall = unsafe extern "C" fn( + runtime: ffi::IM3Runtime, + _sp: *mut u64, + _mem: *mut libc::c_void, +) -> *const libc::c_void; + #[derive(Debug)] pub struct Function<'env, 'rt, ARGS, RET> { raw: ffi::IM3Function, diff --git a/src/lib.rs b/src/lib.rs index 446c595..e387e9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,8 @@ pub mod module; pub mod runtime; mod ty; pub use self::ty::{WasmArg, WasmArgs, WasmType}; +mod macros; +pub use self::macros::*; #[inline] pub fn print_m3_info() { diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..ea42108 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,66 @@ +//! Public macros + +#[macro_export] +macro_rules! make_func_wrapper { + // ptype is an ident because we still want to match on it later -- \/ rtype too -- \/ + ( $wrapper_name:ident: $original:ident( $( $pname:ident: $ptype:ident ),* $( , )? ) $( -> $rtype:ident )?) => { + unsafe extern "C" fn $wrapper_name( + _rt: ffi::IM3Runtime, + _sp: *mut u64, + _mem: *mut std::ffi::c_void, + ) -> *const std::ffi::c_void { + let ssp = _sp; + $( + let $pname = $crate::read_stack_param!(_sp -> $ptype); + let _sp = _sp.add(1); + )* + let ret = $original( $( $pname ),* ); + $( + $crate::put_stack_return!(ssp <- ret as $rtype); + )? + ffi::m3Err_none as _ + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! read_stack_param { + ($sp:ident -> u64) => { + *$sp + }; + ($sp:ident -> u32) => { + (*$sp & 0xFFFF_FFFF) as u32; + }; + ($sp:ident -> f64) => { + f64::from_ne_bytes((*$sp).to_ne_bytes()) + }; + ($sp:ident -> f32) => { + f64::from_ne_bytes($crate::read_stack_param!($sp -> u32).to_ne_bytes()) + }; + ($sp:ident -> $type:ty) => { + compile_error!(concat!("unknown function argument type ", stringify!($type))) + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! put_stack_return { + ($sp:ident <- $ident:ident as u64) => { + *$sp = $ident; + }; + ($sp:ident -> u32) => { + *$sp = $ident as u64; + }; + ($sp:ident -> f64) => { + *$sp = u64::from_ne_bytes($ident.to_ne_bytes()); + }; + ($sp:ident -> f32) => { + f64::from_ne_bytes($crate::read_stack_param!($sp -> u32).to_ne_bytes()) + *$sp = u32::from_ne_bytes($ident.to_ne_bytes()) as u64; + }; + ($sp:ident -> ()) => {}; + ($sp:ident -> $type:ty) => { + compile_error!(concat!("unknown function argument type ", stringify!($type))) + }; +} diff --git a/src/module.rs b/src/module.rs index fba4285..97839b5 100644 --- a/src/module.rs +++ b/src/module.rs @@ -4,7 +4,7 @@ use core::slice; use crate::environment::Environment; use crate::error::{Error, Result}; -use crate::function::Function; +use crate::function::{Function, RawCall}; use crate::runtime::Runtime; pub struct ParsedModule<'env> { @@ -61,7 +61,7 @@ impl<'env, 'rt> Module<'env, 'rt> { &mut self, module_name: &str, function_name: &str, - f: ffi::M3RawCall, + f: RawCall, ) -> Result<()> where ARGS: crate::WasmArgs, @@ -76,7 +76,7 @@ impl<'env, 'rt> Module<'env, 'rt> { } } - unsafe fn link_func_impl(&self, m3_func: ffi::IM3Function, func: ffi::M3RawCall) { + unsafe fn link_func_impl(&self, m3_func: ffi::IM3Function, func: RawCall) { let page = ffi::AcquireCodePageWithCapacity(self.rt.as_ptr(), 2); if page.is_null() { panic!("oom") @@ -84,7 +84,7 @@ impl<'env, 'rt> Module<'env, 'rt> { (*m3_func).compiled = ffi::GetPagePC(page); (*m3_func).module = self.raw; ffi::EmitWord_impl(page, ffi::op_CallRawFunction as _); - ffi::EmitWord_impl(page, func.map(|f| f as _).unwrap_or_else(ptr::null_mut)); + ffi::EmitWord_impl(page, func as _); ffi::ReleaseCodePage(self.rt.as_ptr(), page); } diff --git a/src/runtime.rs b/src/runtime.rs index b5df8ad..112d23e 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -33,7 +33,7 @@ impl<'env> Runtime<'env> { module: ParsedModule<'env>, ) -> core::result::Result, (ParsedModule<'env>, Error)> { if let Err(err) = - unsafe { Error::from_ffi_res(ffi::m3_LoadModule(self.raw, module.as_ptr())) } + Error::from_ffi_res(unsafe { ffi::m3_LoadModule(self.raw, module.as_ptr()) }) { Err((module, err)) } else {