1use crate::{FromToNativeWasmType, RuntimeError, TypedFunction, WasmTypeList};
2use wasmer_types::RawValue;
3
4use crate::native_type::NativeWasmTypeInto;
5use crate::store::{AsStoreMut, AsStoreRef};
6use crate::sys::engine::NativeEngineExt;
7
8macro_rules! impl_native_traits {
9 ( $( $x:ident ),* ) => {
10 #[allow(unused_parens, non_snake_case)]
11 impl<$( $x , )* Rets> TypedFunction<( $( $x ),* ), Rets>
12 where
13 $( $x: FromToNativeWasmType, )*
14 Rets: WasmTypeList,
15 {
16 #[allow(unused_mut)]
18 #[allow(clippy::too_many_arguments)]
19 pub fn call(&self, store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
20 let anyfunc = unsafe {
21 *self.func.0
22 .handle
23 .get(store.as_store_ref().objects())
24 .anyfunc
25 .as_ptr()
26 .as_ref()
27 };
28 if $(!FromToNativeWasmType::is_from_store(&$x, store) ||)* false {
30 return Err(RuntimeError::new(
31 "cross-`Store` values are not supported",
32 ));
33 }
34 let mut params_list = [ $( $x.to_native().into_raw(store) ),* ];
37 let mut rets_list_array = Rets::empty_array();
38 let rets_list: &mut [RawValue] = rets_list_array.as_mut();
39 let using_rets_array;
40 let args_rets: &mut [RawValue] = if params_list.len() > rets_list.len() {
41 using_rets_array = false;
42 params_list.as_mut()
43 } else {
44 using_rets_array = true;
45 for (i, &arg) in params_list.iter().enumerate() {
46 rets_list[i] = arg;
47 }
48 rets_list.as_mut()
49 };
50
51 let mut r;
52 loop {
53 let storeref = store.as_store_ref();
54 let config = storeref.engine().tunables().vmconfig();
55 r = unsafe {
56 wasmer_vm::wasmer_call_trampoline(
57 store.as_store_ref().signal_handler(),
58 config,
59 anyfunc.vmctx,
60 anyfunc.call_trampoline,
61 anyfunc.func_ptr,
62 args_rets.as_mut_ptr() as *mut u8,
63 )
64 };
65 let store_mut = store.as_store_mut();
66 if let Some(callback) = store_mut.inner.on_called.take() {
67 match callback(store_mut) {
68 Ok(wasmer_types::OnCalledAction::InvokeAgain) => { continue; }
69 Ok(wasmer_types::OnCalledAction::Finish) => { break; }
70 Ok(wasmer_types::OnCalledAction::Trap(trap)) => { return Err(RuntimeError::user(trap)) },
71 Err(trap) => { return Err(RuntimeError::user(trap)) },
72 }
73 }
74 break;
75 }
76 r?;
77
78 let num_rets = rets_list.len();
79 if !using_rets_array && num_rets > 0 {
80 let src_pointer = params_list.as_ptr();
81 let rets_list = &mut rets_list_array.as_mut()[0] as *mut RawValue;
82 unsafe {
83 std::ptr::copy_nonoverlapping(src_pointer,
86 rets_list,
87 num_rets);
88 }
89 }
90 Ok(unsafe { Rets::from_array(store, rets_list_array) })
91 }
103
104 #[doc(hidden)]
105 #[allow(missing_docs)]
106 #[allow(unused_mut)]
107 #[allow(clippy::too_many_arguments)]
108 pub fn call_raw(&self, store: &mut impl AsStoreMut, mut params_list: Vec<RawValue> ) -> Result<Rets, RuntimeError> {
109 let anyfunc = unsafe {
110 *self.func.0
111 .handle
112 .get(store.as_store_ref().objects())
113 .anyfunc
114 .as_ptr()
115 .as_ref()
116 };
117 let mut rets_list_array = Rets::empty_array();
120 let rets_list: &mut [RawValue] = rets_list_array.as_mut();
121 let using_rets_array;
122 let args_rets: &mut [RawValue] = if params_list.len() > rets_list.len() {
123 using_rets_array = false;
124 params_list.as_mut()
125 } else {
126 using_rets_array = true;
127 for (i, &arg) in params_list.iter().enumerate() {
128 rets_list[i] = arg;
129 }
130 rets_list.as_mut()
131 };
132
133 let mut r;
134 loop {
135 let storeref = store.as_store_ref();
136 let config = storeref.engine().tunables().vmconfig();
137 r = unsafe {
138 wasmer_vm::wasmer_call_trampoline(
139 store.as_store_ref().signal_handler(),
140 config,
141 anyfunc.vmctx,
142 anyfunc.call_trampoline,
143 anyfunc.func_ptr,
144 args_rets.as_mut_ptr() as *mut u8,
145 )
146 };
147 let store_mut = store.as_store_mut();
148 if let Some(callback) = store_mut.inner.on_called.take() {
149 match callback(store_mut) {
151 Ok(wasmer_types::OnCalledAction::InvokeAgain) => { continue; }
152 Ok(wasmer_types::OnCalledAction::Finish) => { break; }
153 Ok(wasmer_types::OnCalledAction::Trap(trap)) => { return Err(RuntimeError::user(trap)) },
154 Err(trap) => { return Err(RuntimeError::user(trap)) },
155 }
156 }
157 break;
158 }
159 r?;
160
161 let num_rets = rets_list.len();
162 if !using_rets_array && num_rets > 0 {
163 let src_pointer = params_list.as_ptr();
164 let rets_list = &mut rets_list_array.as_mut()[0] as *mut RawValue;
165 unsafe {
166 std::ptr::copy_nonoverlapping(src_pointer,
169 rets_list,
170 num_rets);
171 }
172 }
173 Ok(unsafe { Rets::from_array(store, rets_list_array) })
174 }
186 }
187 };
188}
189
190impl_native_traits!();
191impl_native_traits!(A1);
192impl_native_traits!(A1, A2);
193impl_native_traits!(A1, A2, A3);
194impl_native_traits!(A1, A2, A3, A4);
195impl_native_traits!(A1, A2, A3, A4, A5);
196impl_native_traits!(A1, A2, A3, A4, A5, A6);
197impl_native_traits!(A1, A2, A3, A4, A5, A6, A7);
198impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8);
199impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9);
200impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
201impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
202impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
203impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
204impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
205impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
206impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
207impl_native_traits!(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
208impl_native_traits!(
209 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18
210);
211impl_native_traits!(
212 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19
213);
214impl_native_traits!(
215 A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20
216);