d3b286cd0457418313aaee3dfb651e008074de6c
[mono.git] / mono / mini / aot-runtime-wasm.c
1 /**
2  * \file
3  * WASM AOT runtime
4  */
5
6 #include "config.h"
7
8 #include <sys/types.h>
9
10 #include "mini.h"
11 #include "interp/interp.h"
12
13 #ifdef TARGET_WASM
14
15 static void
16 wasm_restore_context (void)
17 {
18         g_error ("wasm_restore_context");
19 }
20
21 static void
22 wasm_call_filter (void)
23 {
24         g_error ("wasm_call_filter");
25 }
26
27 static void
28 wasm_throw_exception (void)
29 {
30         g_error ("wasm_throw_exception");
31 }
32
33 static void
34 wasm_rethrow_exception (void)
35 {
36         g_error ("wasm_rethrow_exception");
37 }
38
39 static void
40 wasm_throw_corlib_exception (void)
41 {
42         g_error ("wasm_throw_corlib_exception");
43 }
44
45 static char
46 type_to_c (MonoType *t)
47 {
48         if (t->byref)
49                 return 'I';
50
51 handle_enum:
52         switch (t->type) {
53         case MONO_TYPE_BOOLEAN:
54         case MONO_TYPE_CHAR:
55         case MONO_TYPE_I1:
56         case MONO_TYPE_U1:
57         case MONO_TYPE_I2:
58         case MONO_TYPE_U2:
59         case MONO_TYPE_I4:
60         case MONO_TYPE_U4:
61         case MONO_TYPE_I:
62         case MONO_TYPE_U:
63         case MONO_TYPE_PTR:
64         case MONO_TYPE_SZARRAY:
65         case MONO_TYPE_CLASS:
66         case MONO_TYPE_OBJECT:
67         case MONO_TYPE_STRING:
68                 return 'I';
69         case MONO_TYPE_R4:
70                 return 'F';
71         case MONO_TYPE_R8:
72                 return 'D';
73                 break;
74         case MONO_TYPE_I8:
75         case MONO_TYPE_U8:
76                 return 'L';
77         case MONO_TYPE_VOID:
78                 return 'V';
79         case MONO_TYPE_VALUETYPE:
80                 if (t->data.klass->enumtype) {
81                         t = mono_class_enum_basetype (t->data.klass);
82                         goto handle_enum;
83                 }
84
85                 return 'I';
86         case MONO_TYPE_GENERICINST:
87                 if (t->data.klass->valuetype)
88                         return 'S';
89                 return 'I';
90         default:
91                 g_warning ("CANT TRANSLATE %s", mono_type_full_name (t));
92                 return 'X';
93         }
94 }
95
96 #if SIZEOF_VOID_P == 4
97 #define FIDX(x) ((x) * 2)
98 #else
99 #define FIDX(x) (x)
100 #endif
101
102 static void
103 wasm_invoke_v (void *target_func, InterpMethodArguments *margs)
104 {
105         void (*func)(void) = target_func;
106         func ();
107 }
108
109 static void
110 wasm_invoke_vi (void *target_func, InterpMethodArguments *margs)
111 {
112         void (*func)(gpointer a) = target_func;
113         func (margs->iargs [0]);
114 }
115
116 static void
117 wasm_invoke_vii (void *target_func, InterpMethodArguments *margs)
118 {
119         void (*func)(gpointer a, gpointer b) = target_func;
120         func (margs->iargs [0], margs->iargs [1]);
121 }
122
123 static void
124 wasm_invoke_viii (void *target_func, InterpMethodArguments *margs)
125 {
126         void (*func)(gpointer a, gpointer b, gpointer c) = target_func;
127         func (margs->iargs [0], margs->iargs [1], margs->iargs [2]);
128 }
129
130 static void
131 wasm_invoke_viiii (void *target_func, InterpMethodArguments *margs)
132 {
133         void (*func)(gpointer a, gpointer b, gpointer c, gpointer d) = target_func;
134         func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3]);
135 }
136
137 static void
138 wasm_invoke_viiiii (void *target_func, InterpMethodArguments *margs)
139 {
140         void (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e) = target_func;
141         func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4]);
142 }
143
144 static void
145 wasm_invoke_viiiiii (void *target_func, InterpMethodArguments *margs)
146 {
147         void (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e, gpointer f) = target_func;
148         func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4], margs->iargs [5]);
149 }
150
151 static void
152 wasm_invoke_i (void *target_func, InterpMethodArguments *margs)
153 {
154         int (*func)(void) = target_func;
155         int res = func ();
156         *(int*)margs->retval = res;
157 }
158
159 static void
160 wasm_invoke_ii (void *target_func, InterpMethodArguments *margs)
161 {
162         int (*func)(gpointer a) = target_func;
163         int res = func (margs->iargs [0]);
164         *(int*)margs->retval = res;
165 }
166
167 static void
168 wasm_invoke_iii (void *target_func, InterpMethodArguments *margs)
169 {
170         int (*func)(gpointer a, gpointer b) = target_func;
171         int res = func (margs->iargs [0], margs->iargs [1]);
172         *(int*)margs->retval = res;
173 }
174
175 static void
176 wasm_invoke_iiii (void *target_func, InterpMethodArguments *margs)
177 {
178         int (*func)(gpointer a, gpointer b, gpointer c) = target_func;
179         int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2]);
180         *(int*)margs->retval = res;
181 }
182
183 static void
184 wasm_invoke_iiiii (void *target_func, InterpMethodArguments *margs)
185 {
186         int (*func)(gpointer a, gpointer b, gpointer c, gpointer d) = target_func;
187         int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3]);
188         *(int*)margs->retval = res;
189 }
190
191 static void
192 wasm_invoke_iiiiii (void *target_func, InterpMethodArguments *margs)
193 {
194         int (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e) = target_func;
195         int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4]);
196         *(int*)margs->retval = res;
197 }
198
199 typedef union {
200         gint64 l;
201         struct {
202                 gint32 lo;
203                 gint32 hi;
204         } pair;
205 } interp_pair;
206
207 static void
208 wasm_invoke_l (void *target_func, InterpMethodArguments *margs)
209 {
210         gint64 (*func)(void) = target_func;
211
212         gint64 res = func ();
213         *(gint64*)margs->retval = res;
214 }
215
216 static void
217 wasm_invoke_ll (void *target_func, InterpMethodArguments *margs)
218 {
219         gint64 (*func)(gint64 a) = target_func;
220
221         interp_pair p;
222         p.pair.lo = (gint32)margs->iargs [0];
223         p.pair.hi = (gint32)margs->iargs [1];
224
225         gint64 res = func (p.l);
226         *(gint64*)margs->retval = res;
227 }
228
229 static void
230 wasm_invoke_li (void *target_func, InterpMethodArguments *margs)
231 {
232         gint64 (*func)(gpointer a) = target_func;
233         gint64 res = func (margs->iargs [0]);
234         *(gint64*)margs->retval = res;
235 }
236
237 static void
238 wasm_invoke_lil (void *target_func, InterpMethodArguments *margs)
239 {
240         gint64 (*func)(gpointer a, gint64 b) = target_func;
241
242         interp_pair p;
243         p.pair.lo = (gint32)margs->iargs [1];
244         p.pair.hi = (gint32)margs->iargs [2];
245
246         gint64 res = func (margs->iargs [0], p.l);
247         *(gint64*)margs->retval = res;
248 }
249
250 static void
251 wasm_invoke_dd (void *target_func, InterpMethodArguments *margs)
252 {
253         double (*func)(double a) = target_func;
254
255         double res = func (margs->fargs [FIDX (0)]);
256         *(double*)margs->retval = res;
257 }
258
259 static void
260 wasm_invoke_ddd (void *target_func, InterpMethodArguments *margs)
261 {
262         double (*func)(double a, double b) = target_func;
263
264         double res = func (margs->fargs [FIDX (0)], margs->fargs [FIDX (1)]);
265         *(double*)margs->retval = res;
266 }
267
268
269         
270 static void
271 wasm_invoke_vif (void *target_func, InterpMethodArguments *margs)
272 {
273         void (*func)(gpointer a, float b) = target_func;
274
275         func (margs->iargs [0], 
276                 *(float*)&margs->fargs [FIDX (0)]);
277 }
278
279 static void
280 wasm_invoke_viff (void *target_func, InterpMethodArguments *margs)
281 {
282         void (*func)(gpointer a, float b, float c) = target_func;
283
284         func (margs->iargs [0],
285                 *(float*)&margs->fargs [FIDX (0)],
286                 *(float*)&margs->fargs [FIDX (1)]);
287 }
288
289 static void
290 wasm_invoke_viffff (void *target_func, InterpMethodArguments *margs)
291 {
292         void (*func)(gpointer a, float b, float c, float d, float e) = target_func;
293
294         func (margs->iargs [0],
295                 *(float*)&margs->fargs [FIDX (0)],
296                 *(float*)&margs->fargs [FIDX (1)],
297                 *(float*)&margs->fargs [FIDX (2)],
298                 *(float*)&margs->fargs [FIDX (3)]);
299 }
300
301 static void
302 wasm_invoke_vifffffi (void *target_func, InterpMethodArguments *margs)
303 {
304         void (*func)(gpointer a, float b, float c, float d, float e, float f, int g) = target_func;
305
306         func (margs->iargs [0],
307                 *(float*)&margs->fargs [FIDX (0)],
308                 *(float*)&margs->fargs [FIDX (1)],
309                 *(float*)&margs->fargs [FIDX (2)],
310                 *(float*)&margs->fargs [FIDX (3)],
311                 *(float*)&margs->fargs [FIDX (4)],
312                 *(float*)&margs->iargs [1]);
313 }
314
315 static void
316 wasm_invoke_ff (void *target_func, InterpMethodArguments *margs)
317 {
318         float (*func)(float a) = target_func;
319
320         float res = func (*(float*)&margs->fargs [FIDX (0)]);
321         *(float*)margs->retval = res;
322 }
323
324 static void
325 wasm_enter_icall_trampoline (void *target_func, InterpMethodArguments *margs)
326 {
327         static char cookie [8];
328         static int c_count;
329
330         MonoMethodSignature *sig = margs->sig;
331
332         c_count = sig->param_count + sig->hasthis + 1;
333         cookie [0] = type_to_c (sig->ret);
334         if (sig->hasthis)
335                 cookie [1] = 'I';
336         for (int i = 0; i < sig->param_count; ++i)
337                 cookie [1 + sig->hasthis + i ] = type_to_c (sig->params [i]);
338         cookie [c_count] = 0;
339
340         if (!strcmp ("V", cookie))
341                 wasm_invoke_v (target_func, margs);
342         else if (!strcmp ("VI", cookie))
343                 wasm_invoke_vi (target_func, margs);
344         else if (!strcmp ("VII", cookie))
345                 wasm_invoke_vii (target_func, margs);
346         else if (!strcmp ("VIII", cookie))
347                 wasm_invoke_viii (target_func, margs);
348         else if (!strcmp ("VIIII", cookie))
349                 wasm_invoke_viiii (target_func, margs);
350         else if (!strcmp ("VIIIII", cookie))
351                 wasm_invoke_viiiii (target_func, margs);
352         else if (!strcmp ("VIIIIII", cookie))
353                 wasm_invoke_viiiiii (target_func, margs);
354         else if (!strcmp ("I", cookie))
355                 wasm_invoke_i (target_func, margs);
356         else if (!strcmp ("II", cookie))
357                 wasm_invoke_ii (target_func, margs);
358         else if (!strcmp ("III", cookie))
359                 wasm_invoke_iii (target_func, margs);
360         else if (!strcmp ("IIII", cookie))
361                 wasm_invoke_iiii (target_func, margs);
362         else if (!strcmp ("IIIII", cookie))
363                 wasm_invoke_iiiii (target_func, margs);
364         else if (!strcmp ("IIIIII", cookie))
365                 wasm_invoke_iiiiii (target_func, margs);
366         else if (!strcmp ("L", cookie))
367                 wasm_invoke_l (target_func, margs);
368         else if (!strcmp ("LL", cookie))
369                 wasm_invoke_ll (target_func, margs);
370         else if (!strcmp ("LI", cookie))
371                 wasm_invoke_li (target_func, margs);
372         else if (!strcmp ("LIL", cookie))
373                 wasm_invoke_lil (target_func, margs);
374         else if (!strcmp ("DD", cookie))
375                 wasm_invoke_dd (target_func, margs);
376         else if (!strcmp ("DDD", cookie))
377                 wasm_invoke_ddd (target_func, margs);
378         else if (!strcmp ("VIF", cookie))
379                 wasm_invoke_vif (target_func, margs);
380         else if (!strcmp ("VIFF", cookie))
381                 wasm_invoke_viff (target_func, margs);
382         else if (!strcmp ("VIFFFF", cookie))
383                 wasm_invoke_viffff (target_func, margs);
384         else if (!strcmp ("VIFFFFFI", cookie))
385                 wasm_invoke_vifffffi (target_func, margs);
386         else if (!strcmp ("FF", cookie))
387                 wasm_invoke_ff (target_func, margs);
388         else {
389                 printf ("CANNOT HANDLE COOKIE %s\n", cookie);
390                 g_assert (0);
391         }
392 }
393
394 gpointer
395 mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
396 {
397         gpointer code = NULL;
398
399         if (!strcmp (name, "restore_context"))
400                 code = wasm_restore_context;
401         else if (!strcmp (name, "call_filter"))
402                 code = wasm_call_filter;
403         else if (!strcmp (name, "throw_exception"))
404                 code = wasm_throw_exception;
405         else if (!strcmp (name, "rethrow_exception"))
406                 code = wasm_rethrow_exception;
407         else if (!strcmp (name, "throw_corlib_exception"))
408                 code = wasm_throw_corlib_exception;
409         else if (!strcmp (name, "enter_icall_trampoline"))
410                 code = wasm_enter_icall_trampoline;
411
412         g_assert (code);
413
414         if (out_tinfo) {
415                 MonoTrampInfo *tinfo = g_new0 (MonoTrampInfo, 1);
416                 tinfo->code = code;
417                 tinfo->code_size = 1;
418                 tinfo->name = g_strdup (name);
419                 tinfo->ji = NULL;
420                 tinfo->unwind_ops = NULL;
421                 tinfo->uw_info = NULL;
422                 tinfo->uw_info_len = 0;
423                 tinfo->owns_uw_info = FALSE;
424
425                 *out_tinfo = tinfo;
426         }
427
428         return code;
429 }
430 #endif