Skip to content

Commit 7915db9

Browse files
committed
Add experimental function wrapper macro for linking
1 parent 1cf95dc commit 7915db9

File tree

6 files changed

+84
-13
lines changed

6 files changed

+84
-13
lines changed

examples/wasm_link.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn main() {
1212

1313
let mut module = rt.load_module(module).map_err(|(_, e)| e).unwrap();
1414
module
15-
.link_function::<(), u64>("time", "millis", Some(millis))
15+
.link_function::<(), u64>("time", "millis", millis_wrap)
1616
.unwrap();
1717
let func = module.find_function::<(), u64>("seconds").unwrap();
1818
println!("{}ms in seconds is {:?}s.", MILLIS, func.call());
@@ -21,11 +21,7 @@ fn main() {
2121

2222
const MILLIS: u64 = 500_000;
2323

24-
unsafe extern "C" fn millis(
25-
_rt: ffi::IM3Runtime,
26-
sp: *mut u64,
27-
_mem: *mut std::ffi::c_void,
28-
) -> *const std::ffi::c_void {
29-
*sp = MILLIS;
30-
ffi::m3Err_none as _
24+
wasm3::make_func_wrapper!(millis_wrap: millis() -> u64);
25+
fn millis() -> u64 {
26+
MILLIS
3127
}

src/function.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ use crate::error::{Error, Result};
66
use crate::runtime::Runtime;
77
use crate::{WasmArgs, WasmType};
88

9+
// redefine of ffi::RawCall without the Option<T> around it
10+
pub type RawCall = unsafe extern "C" fn(
11+
runtime: ffi::IM3Runtime,
12+
_sp: *mut u64,
13+
_mem: *mut libc::c_void,
14+
) -> *const libc::c_void;
15+
916
#[derive(Debug)]
1017
pub struct Function<'env, 'rt, ARGS, RET> {
1118
raw: ffi::IM3Function,

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ pub mod module;
77
pub mod runtime;
88
mod ty;
99
pub use self::ty::{WasmArg, WasmArgs, WasmType};
10+
mod macros;
11+
pub use self::macros::*;
1012

1113
#[inline]
1214
pub fn print_m3_info() {

src/macros.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//! Public macros
2+
3+
#[macro_export]
4+
macro_rules! make_func_wrapper {
5+
// ptype is an ident because we still want to match on it later -- \/ rtype too -- \/
6+
( $wrapper_name:ident: $original:ident( $( $pname:ident: $ptype:ident ),* $( , )? ) $( -> $rtype:ident )?) => {
7+
unsafe extern "C" fn $wrapper_name(
8+
_rt: ffi::IM3Runtime,
9+
_sp: *mut u64,
10+
_mem: *mut std::ffi::c_void,
11+
) -> *const std::ffi::c_void {
12+
let ssp = _sp;
13+
$(
14+
let $pname = $crate::read_stack_param!(_sp -> $ptype);
15+
let _sp = _sp.add(1);
16+
)*
17+
let ret = $original( $( $pname ),* );
18+
$(
19+
$crate::put_stack_return!(ssp <- ret as $rtype);
20+
)?
21+
ffi::m3Err_none as _
22+
}
23+
};
24+
}
25+
26+
#[doc(hidden)]
27+
#[macro_export]
28+
macro_rules! read_stack_param {
29+
($sp:ident -> u64) => {
30+
*$sp
31+
};
32+
($sp:ident -> u32) => {
33+
(*$sp & 0xFFFF_FFFF) as u32;
34+
};
35+
($sp:ident -> f64) => {
36+
f64::from_ne_bytes((*$sp).to_ne_bytes())
37+
};
38+
($sp:ident -> f32) => {
39+
f64::from_ne_bytes($crate::read_stack_param!($sp -> u32).to_ne_bytes())
40+
};
41+
($sp:ident -> $type:ty) => {
42+
compile_error!(concat!("unknown function argument type ", stringify!($type)))
43+
};
44+
}
45+
46+
#[doc(hidden)]
47+
#[macro_export]
48+
macro_rules! put_stack_return {
49+
($sp:ident <- $ident:ident as u64) => {
50+
*$sp = $ident;
51+
};
52+
($sp:ident -> u32) => {
53+
*$sp = $ident as u64;
54+
};
55+
($sp:ident -> f64) => {
56+
*$sp = u64::from_ne_bytes($ident.to_ne_bytes());
57+
};
58+
($sp:ident -> f32) => {
59+
f64::from_ne_bytes($crate::read_stack_param!($sp -> u32).to_ne_bytes())
60+
*$sp = u32::from_ne_bytes($ident.to_ne_bytes()) as u64;
61+
};
62+
($sp:ident -> ()) => {};
63+
($sp:ident -> $type:ty) => {
64+
compile_error!(concat!("unknown function argument type ", stringify!($type)))
65+
};
66+
}

src/module.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::slice;
44

55
use crate::environment::Environment;
66
use crate::error::{Error, Result};
7-
use crate::function::Function;
7+
use crate::function::{Function, RawCall};
88
use crate::runtime::Runtime;
99

1010
pub struct ParsedModule<'env> {
@@ -61,7 +61,7 @@ impl<'env, 'rt> Module<'env, 'rt> {
6161
&mut self,
6262
module_name: &str,
6363
function_name: &str,
64-
f: ffi::M3RawCall,
64+
f: RawCall,
6565
) -> Result<()>
6666
where
6767
ARGS: crate::WasmArgs,
@@ -76,15 +76,15 @@ impl<'env, 'rt> Module<'env, 'rt> {
7676
}
7777
}
7878

79-
unsafe fn link_func_impl(&self, m3_func: ffi::IM3Function, func: ffi::M3RawCall) {
79+
unsafe fn link_func_impl(&self, m3_func: ffi::IM3Function, func: RawCall) {
8080
let page = ffi::AcquireCodePageWithCapacity(self.rt.as_ptr(), 2);
8181
if page.is_null() {
8282
panic!("oom")
8383
} else {
8484
(*m3_func).compiled = ffi::GetPagePC(page);
8585
(*m3_func).module = self.raw;
8686
ffi::EmitWord_impl(page, ffi::op_CallRawFunction as _);
87-
ffi::EmitWord_impl(page, func.map(|f| f as _).unwrap_or_else(ptr::null_mut));
87+
ffi::EmitWord_impl(page, func as _);
8888

8989
ffi::ReleaseCodePage(self.rt.as_ptr(), page);
9090
}

src/runtime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'env> Runtime<'env> {
3333
module: ParsedModule<'env>,
3434
) -> core::result::Result<Module<'env, 'rt>, (ParsedModule<'env>, Error)> {
3535
if let Err(err) =
36-
unsafe { Error::from_ffi_res(ffi::m3_LoadModule(self.raw, module.as_ptr())) }
36+
Error::from_ffi_res(unsafe { ffi::m3_LoadModule(self.raw, module.as_ptr()) })
3737
{
3838
Err((module, err))
3939
} else {

0 commit comments

Comments
 (0)