Fix libmini targets and filters.
[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 static void
200 wasm_invoke_iiiiiiiii (void *target_func, InterpMethodArguments *margs)
201 {
202         int (*func)(gpointer a, gpointer b, gpointer c, gpointer d, gpointer e, gpointer f, gpointer g, gpointer h) = target_func;
203         int res = func (margs->iargs [0], margs->iargs [1], margs->iargs [2], margs->iargs [3], margs->iargs [4], margs->iargs [5], margs->iargs [6], margs->iargs [7]);
204         *(int*)margs->retval = res;
205 }
206
207
208 typedef union {
209         gint64 l;
210         struct {
211                 gint32 lo;
212                 gint32 hi;
213         } pair;
214 } interp_pair;
215
216 static void
217 wasm_invoke_l (void *target_func, InterpMethodArguments *margs)
218 {
219         gint64 (*func)(void) = target_func;
220
221         gint64 res = func ();
222         *(gint64*)margs->retval = res;
223 }
224
225 static void
226 wasm_invoke_ll (void *target_func, InterpMethodArguments *margs)
227 {
228         gint64 (*func)(gint64 a) = target_func;
229
230         interp_pair p;
231         p.pair.lo = (gint32)margs->iargs [0];
232         p.pair.hi = (gint32)margs->iargs [1];
233
234         gint64 res = func (p.l);
235         *(gint64*)margs->retval = res;
236 }
237
238 static void
239 wasm_invoke_li (void *target_func, InterpMethodArguments *margs)
240 {
241         gint64 (*func)(gpointer a) = target_func;
242         gint64 res = func (margs->iargs [0]);
243         *(gint64*)margs->retval = res;
244 }
245
246 static void
247 wasm_invoke_lil (void *target_func, InterpMethodArguments *margs)
248 {
249         gint64 (*func)(gpointer a, gint64 b) = target_func;
250
251         interp_pair p;
252         p.pair.lo = (gint32)margs->iargs [1];
253         p.pair.hi = (gint32)margs->iargs [2];
254
255         gint64 res = func (margs->iargs [0], p.l);
256         *(gint64*)margs->retval = res;
257 }
258
259 static void
260 wasm_invoke_dd (void *target_func, InterpMethodArguments *margs)
261 {
262         double (*func)(double a) = target_func;
263
264         double res = func (margs->fargs [FIDX (0)]);
265         *(double*)margs->retval = res;
266 }
267
268 static void
269 wasm_invoke_ddd (void *target_func, InterpMethodArguments *margs)
270 {
271         double (*func)(double a, double b) = target_func;
272
273         double res = func (margs->fargs [FIDX (0)], margs->fargs [FIDX (1)]);
274         *(double*)margs->retval = res;
275 }
276
277
278         
279 static void
280 wasm_invoke_vif (void *target_func, InterpMethodArguments *margs)
281 {
282         void (*func)(gpointer a, float b) = target_func;
283
284         func (margs->iargs [0], 
285                 *(float*)&margs->fargs [FIDX (0)]);
286 }
287
288 static void
289 wasm_invoke_viff (void *target_func, InterpMethodArguments *margs)
290 {
291         void (*func)(gpointer a, float b, float c) = target_func;
292
293         func (margs->iargs [0],
294                 *(float*)&margs->fargs [FIDX (0)],
295                 *(float*)&margs->fargs [FIDX (1)]);
296 }
297
298 static void
299 wasm_invoke_viffff (void *target_func, InterpMethodArguments *margs)
300 {
301         void (*func)(gpointer a, float b, float c, float d, float e) = target_func;
302
303         func (margs->iargs [0],
304                 *(float*)&margs->fargs [FIDX (0)],
305                 *(float*)&margs->fargs [FIDX (1)],
306                 *(float*)&margs->fargs [FIDX (2)],
307                 *(float*)&margs->fargs [FIDX (3)]);
308 }
309
310 static void
311 wasm_invoke_vifffffi (void *target_func, InterpMethodArguments *margs)
312 {
313         void (*func)(gpointer a, float b, float c, float d, float e, float f, int g) = target_func;
314
315         func (margs->iargs [0],
316                 *(float*)&margs->fargs [FIDX (0)],
317                 *(float*)&margs->fargs [FIDX (1)],
318                 *(float*)&margs->fargs [FIDX (2)],
319                 *(float*)&margs->fargs [FIDX (3)],
320                 *(float*)&margs->fargs [FIDX (4)],
321                 *(float*)&margs->iargs [1]);
322 }
323
324 static void
325 wasm_invoke_ff (void *target_func, InterpMethodArguments *margs)
326 {
327         float (*func)(float a) = target_func;
328
329         float res = func (*(float*)&margs->fargs [FIDX (0)]);
330         *(float*)margs->retval = res;
331 }
332
333 static void
334 wasm_enter_icall_trampoline (void *target_func, InterpMethodArguments *margs)
335 {
336         static char cookie [8];
337         static int c_count;
338
339         MonoMethodSignature *sig = margs->sig;
340
341         c_count = sig->param_count + sig->hasthis + 1;
342         cookie [0] = type_to_c (sig->ret);
343         if (sig->hasthis)
344                 cookie [1] = 'I';
345         for (int i = 0; i < sig->param_count; ++i)
346                 cookie [1 + sig->hasthis + i ] = type_to_c (sig->params [i]);
347         cookie [c_count] = 0;
348
349         if (!strcmp ("V", cookie))
350                 wasm_invoke_v (target_func, margs);
351         else if (!strcmp ("VI", cookie))
352                 wasm_invoke_vi (target_func, margs);
353         else if (!strcmp ("VII", cookie))
354                 wasm_invoke_vii (target_func, margs);
355         else if (!strcmp ("VIII", cookie))
356                 wasm_invoke_viii (target_func, margs);
357         else if (!strcmp ("VIIII", cookie))
358                 wasm_invoke_viiii (target_func, margs);
359         else if (!strcmp ("VIIIII", cookie))
360                 wasm_invoke_viiiii (target_func, margs);
361         else if (!strcmp ("VIIIIII", cookie))
362                 wasm_invoke_viiiiii (target_func, margs);
363         else if (!strcmp ("I", cookie))
364                 wasm_invoke_i (target_func, margs);
365         else if (!strcmp ("II", cookie))
366                 wasm_invoke_ii (target_func, margs);
367         else if (!strcmp ("III", cookie))
368                 wasm_invoke_iii (target_func, margs);
369         else if (!strcmp ("IIII", cookie))
370                 wasm_invoke_iiii (target_func, margs);
371         else if (!strcmp ("IIIII", cookie))
372                 wasm_invoke_iiiii (target_func, margs);
373         else if (!strcmp ("IIIIII", cookie))
374                 wasm_invoke_iiiiii (target_func, margs);
375         else if (!strcmp ("IIIIIIIII", cookie))
376                 wasm_invoke_iiiiiiiii (target_func, margs);
377         else if (!strcmp ("L", cookie))
378                 wasm_invoke_l (target_func, margs);
379         else if (!strcmp ("LL", cookie))
380                 wasm_invoke_ll (target_func, margs);
381         else if (!strcmp ("LI", cookie))
382                 wasm_invoke_li (target_func, margs);
383         else if (!strcmp ("LIL", cookie))
384                 wasm_invoke_lil (target_func, margs);
385         else if (!strcmp ("DD", cookie))
386                 wasm_invoke_dd (target_func, margs);
387         else if (!strcmp ("DDD", cookie))
388                 wasm_invoke_ddd (target_func, margs);
389         else if (!strcmp ("VIF", cookie))
390                 wasm_invoke_vif (target_func, margs);
391         else if (!strcmp ("VIFF", cookie))
392                 wasm_invoke_viff (target_func, margs);
393         else if (!strcmp ("VIFFFF", cookie))
394                 wasm_invoke_viffff (target_func, margs);
395         else if (!strcmp ("VIFFFFFI", cookie))
396                 wasm_invoke_vifffffi (target_func, margs);
397         else if (!strcmp ("FF", cookie))
398                 wasm_invoke_ff (target_func, margs);
399         else {
400                 printf ("CANNOT HANDLE COOKIE %s\n", cookie);
401                 g_assert (0);
402         }
403 }
404
405 gpointer
406 mono_aot_get_trampoline_full (const char *name, MonoTrampInfo **out_tinfo)
407 {
408         gpointer code = NULL;
409
410         if (!strcmp (name, "restore_context"))
411                 code = wasm_restore_context;
412         else if (!strcmp (name, "call_filter"))
413                 code = wasm_call_filter;
414         else if (!strcmp (name, "throw_exception"))
415                 code = wasm_throw_exception;
416         else if (!strcmp (name, "rethrow_exception"))
417                 code = wasm_rethrow_exception;
418         else if (!strcmp (name, "throw_corlib_exception"))
419                 code = wasm_throw_corlib_exception;
420         else if (!strcmp (name, "enter_icall_trampoline"))
421                 code = wasm_enter_icall_trampoline;
422
423         g_assert (code);
424
425         if (out_tinfo) {
426                 MonoTrampInfo *tinfo = g_new0 (MonoTrampInfo, 1);
427                 tinfo->code = code;
428                 tinfo->code_size = 1;
429                 tinfo->name = g_strdup (name);
430                 tinfo->ji = NULL;
431                 tinfo->unwind_ops = NULL;
432                 tinfo->uw_info = NULL;
433                 tinfo->uw_info_len = 0;
434                 tinfo->owns_uw_info = FALSE;
435
436                 *out_tinfo = tinfo;
437         }
438
439         return code;
440 }
441 #else /* TARGET_WASM */
442
443 MONO_EMPTY_SOURCE_FILE (aot_runtime_wasm);
444
445 #endif /* TARGET_WASM */