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