[runtime] cleanup around native crash info (#12581)
[mono-project.git] / mono / mini / mini-wasm.c
blob9bb114960f6d9068db941a0c3c4b9c42aa4b49c3
1 #include "mini.h"
2 #include "mini-runtime.h"
3 #include <mono/metadata/mono-debug.h>
4 #include <mono/metadata/assembly.h>
5 #include <mono/metadata/metadata.h>
6 #include <mono/metadata/loader-internals.h>
7 #include <mono/metadata/icall-internals.h>
8 #include <mono/metadata/seq-points-data.h>
9 #include <mono/mini/aot-runtime.h>
10 #include <mono/mini/seq-points.h>
12 //XXX This is dirty, extend ee.h to support extracting info from MonoInterpFrameHandle
13 #include <mono/mini/interp/interp-internals.h>
15 #ifndef DISABLE_JIT
17 #include "ir-emit.h"
18 #include "cpu-wasm.h"
20 //FIXME figure out if we need to distingush between i,l,f,d types
21 typedef enum {
22 ArgOnStack,
23 ArgValuetypeAddrOnStack,
24 ArgGsharedVTOnStack,
25 ArgValuetypeAddrInIReg,
26 ArgInvalid,
27 } ArgStorage;
29 typedef struct {
30 ArgStorage storage : 8;
31 } ArgInfo;
33 struct CallInfo {
34 int nargs;
35 gboolean gsharedvt;
37 ArgInfo ret;
38 ArgInfo args [1];
41 static ArgStorage
42 get_storage (MonoType *type, gboolean is_return)
44 switch (type->type) {
45 case MONO_TYPE_I1:
46 case MONO_TYPE_U1:
47 case MONO_TYPE_I2:
48 case MONO_TYPE_U2:
49 case MONO_TYPE_I4:
50 case MONO_TYPE_U4:
51 case MONO_TYPE_I:
52 case MONO_TYPE_U:
53 case MONO_TYPE_PTR:
54 case MONO_TYPE_FNPTR:
55 case MONO_TYPE_OBJECT:
56 return ArgOnStack;
58 case MONO_TYPE_U8:
59 case MONO_TYPE_I8:
60 return ArgOnStack;
62 case MONO_TYPE_R4:
63 return ArgOnStack;
65 case MONO_TYPE_R8:
66 return ArgOnStack;
68 case MONO_TYPE_GENERICINST:
69 if (!mono_type_generic_inst_is_valuetype (type))
70 return ArgOnStack;
72 if (mini_is_gsharedvt_type (type)) {
73 return ArgGsharedVTOnStack;
75 /* fall through */
76 case MONO_TYPE_VALUETYPE:
77 case MONO_TYPE_TYPEDBYREF: {
78 return is_return ? ArgValuetypeAddrInIReg : ArgValuetypeAddrOnStack;
79 break;
81 case MONO_TYPE_VAR:
82 case MONO_TYPE_MVAR:
83 g_assert (mini_is_gsharedvt_type (type));
84 return ArgGsharedVTOnStack;
85 break;
86 case MONO_TYPE_VOID:
87 g_assert (is_return);
88 break;
89 default:
90 g_error ("Can't handle as return value 0x%x", type->type);
92 return ArgInvalid;
95 static CallInfo*
96 get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
98 int n = sig->hasthis + sig->param_count;
99 CallInfo *cinfo;
101 if (mp)
102 cinfo = (CallInfo *)mono_mempool_alloc0 (mp, sizeof (CallInfo) + (sizeof (ArgInfo) * n));
103 else
104 cinfo = (CallInfo *)g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
106 cinfo->nargs = n;
107 cinfo->gsharedvt = mini_is_gsharedvt_variable_signature (sig);
109 /* return value */
110 cinfo->ret.storage = get_storage (mini_get_underlying_type (sig->ret), TRUE);
112 if (sig->hasthis)
113 cinfo->args [0].storage = ArgOnStack;
115 // not supported
116 g_assert (sig->call_convention != MONO_CALL_VARARG);
118 int i;
119 for (i = 0; i < sig->param_count; ++i)
120 cinfo->args [i + sig->hasthis].storage = get_storage (mini_get_underlying_type (sig->params [i]), FALSE);
122 return cinfo;
125 gboolean
126 mono_arch_have_fast_tls (void)
128 return FALSE;
131 guint32
132 mono_arch_get_patch_offset (guint8 *code)
134 g_error ("mono_arch_get_patch_offset");
135 return 0;
137 gpointer
138 mono_arch_ip_from_context (void *sigctx)
140 g_error ("mono_arch_ip_from_context");
143 gboolean
144 mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
146 return TRUE;
149 void
150 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
154 gboolean
155 mono_arch_opcode_supported (int opcode)
157 return FALSE;
160 void
161 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
163 g_error ("mono_arch_output_basic_block");
166 void
167 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
171 void
172 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
176 guint32
177 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
179 return 0;
182 GList *
183 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
185 g_error ("mono_arch_get_allocatable_int_vars");
188 GList *
189 mono_arch_get_global_int_regs (MonoCompile *cfg)
191 g_error ("mono_arch_get_global_int_regs");
194 void
195 mono_arch_allocate_vars (MonoCompile *cfg)
197 g_error ("mono_arch_allocate_vars");
200 void
201 mono_arch_create_vars (MonoCompile *cfg)
203 MonoMethodSignature *sig;
204 CallInfo *cinfo;
205 MonoType *sig_ret;
207 sig = mono_method_signature_internal (cfg->method);
209 if (!cfg->arch.cinfo)
210 cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
211 cinfo = (CallInfo *)cfg->arch.cinfo;
213 // if (cinfo->ret.storage == ArgValuetypeInReg)
214 // cfg->ret_var_is_local = TRUE;
216 sig_ret = mini_get_underlying_type (sig->ret);
217 if (cinfo->ret.storage == ArgValuetypeAddrInIReg || cinfo->ret.storage == ArgGsharedVTOnStack) {
218 cfg->vret_addr = mono_compile_create_var (cfg, mono_get_int_type (), OP_ARG);
219 if (G_UNLIKELY (cfg->verbose_level > 1)) {
220 printf ("vret_addr = ");
221 mono_print_ins (cfg->vret_addr);
225 if (cfg->gen_sdb_seq_points)
226 g_error ("gen_sdb_seq_points not supported");
228 if (cfg->method->save_lmf)
229 cfg->create_lmf_var = TRUE;
231 if (cfg->method->save_lmf)
232 cfg->lmf_ir = TRUE;
235 void
236 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
238 g_error ("mono_arch_emit_call");
241 void
242 mono_arch_emit_epilog (MonoCompile *cfg)
244 g_error ("mono_arch_emit_epilog");
247 void
248 mono_arch_emit_exceptions (MonoCompile *cfg)
250 g_error ("mono_arch_emit_exceptions");
253 MonoInst*
254 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
256 return NULL;
259 void
260 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
262 g_error ("mono_arch_emit_outarg_vt");
265 guint8 *
266 mono_arch_emit_prolog (MonoCompile *cfg)
268 g_error ("mono_arch_emit_prolog");
271 void
272 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
274 MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret);
276 if (!ret->byref) {
277 if (ret->type == MONO_TYPE_R4) {
278 MONO_EMIT_NEW_UNALU (cfg, cfg->r4fp ? OP_RMOVE : OP_FMOVE, cfg->ret->dreg, val->dreg);
279 return;
280 } else if (ret->type == MONO_TYPE_R8) {
281 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
282 return;
283 } else if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) {
284 MONO_EMIT_NEW_UNALU (cfg, OP_LMOVE, cfg->ret->dreg, val->dreg);
285 return;
288 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
291 void
292 mono_arch_flush_icache (guint8 *code, gint size)
296 LLVMCallInfo*
297 mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
299 int i, n;
300 CallInfo *cinfo;
301 LLVMCallInfo *linfo;
303 cinfo = get_call_info (cfg->mempool, sig);
304 n = cinfo->nargs;
306 linfo = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
308 if (mini_type_is_vtype (sig->ret)) {
309 /* Vtype returned using a hidden argument */
310 linfo->ret.storage = LLVMArgVtypeRetAddr;
311 // linfo->vret_arg_index = cinfo->vret_arg_index;
312 } else {
313 if (sig->ret->type != MONO_TYPE_VOID)
314 linfo->ret.storage = LLVMArgNormal;
317 for (i = 0; i < n; ++i) {
318 ArgInfo *ainfo = &cinfo->args[i];
320 switch (ainfo->storage) {
321 case ArgOnStack:
322 linfo->args [i].storage = LLVMArgNormal;
323 break;
324 case ArgValuetypeAddrOnStack:
325 linfo->args [i].storage = LLVMArgVtypeByRef;
326 break;
327 case ArgGsharedVTOnStack:
328 linfo->args [i].storage = LLVMArgGsharedvtVariable;
329 break;
330 case ArgValuetypeAddrInIReg:
331 g_error ("this is only valid for sig->ret");
332 break;
336 return linfo;
339 gboolean
340 mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_)
342 return FALSE;
345 #endif // DISABLE_JIT
347 const char*
348 mono_arch_fregname (int reg)
350 return "freg0";
353 const char*
354 mono_arch_regname (int reg)
356 return "r0";
360 mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count, MonoJitArgumentInfo *arg_info)
362 g_error ("mono_arch_get_argument_info");
365 GSList*
366 mono_arch_get_delegate_invoke_impls (void)
368 g_error ("mono_arch_get_delegate_invoke_impls");
371 gpointer
372 mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
374 g_error ("mono_arch_get_gsharedvt_call_info");
375 return NULL;
378 gpointer
379 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
381 g_error ("mono_arch_get_delegate_invoke_impl");
384 #ifdef HOST_WASM
386 #include <emscripten.h>
388 //functions exported to be used by JS
389 G_BEGIN_DECLS
390 EMSCRIPTEN_KEEPALIVE void mono_set_timeout_exec (int id);
392 //JS functions imported that we use
393 extern void mono_set_timeout (int t, int d);
394 G_END_DECLS
396 #endif // HOST_WASM
398 gpointer
399 mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code)
401 g_error ("mono_arch_get_this_arg_from_call");
404 gpointer
405 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
407 g_error ("mono_arch_get_delegate_virtual_invoke_impl");
411 void
412 mono_arch_cpu_init (void)
414 // printf ("mono_arch_cpu_init\n");
417 void
418 mono_arch_finish_init (void)
420 // printf ("mono_arch_finish_init\n");
423 void
424 mono_arch_init (void)
426 // printf ("mono_arch_init\n");
429 void
430 mono_arch_cleanup (void)
434 void
435 mono_arch_register_lowlevel_calls (void)
439 void
440 mono_arch_flush_register_windows (void)
444 void
445 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
450 MonoMethod*
451 mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code)
453 g_error ("mono_arch_find_static_call_vtable");
454 return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
457 MonoVTable*
458 mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code)
460 g_error ("mono_arch_find_static_call_vtable");
461 return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
464 gpointer
465 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
467 g_error ("mono_arch_build_imt_trampoline");
470 guint32
471 mono_arch_cpu_enumerate_simd_versions (void)
473 return 0;
476 guint32
477 mono_arch_cpu_optimizations (guint32 *exclude_mask)
479 /* No arch specific passes yet */
480 *exclude_mask = 0;
481 return 0;
484 host_mgreg_t
485 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
487 g_error ("mono_arch_context_get_int_reg");
488 return 0;
491 #ifdef HOST_WASM
493 void
494 mono_runtime_setup_stat_profiler (void)
496 g_error ("mono_runtime_setup_stat_profiler");
500 void
501 mono_runtime_shutdown_stat_profiler (void)
503 g_error ("mono_runtime_shutdown_stat_profiler");
507 gboolean
508 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
510 g_error ("mono_chain_signal");
512 return FALSE;
515 void
516 mono_runtime_install_handlers (void)
520 void
521 mono_runtime_cleanup_handlers (void)
525 void
526 mono_init_native_crash_info (void)
528 return;
531 void
532 mono_cleanup_native_crash_info (void)
534 return;
537 gboolean
538 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info, void *sigctx)
540 g_error ("WASM systems don't support mono_thread_state_init_from_handle");
541 return FALSE;
544 EMSCRIPTEN_KEEPALIVE void
545 mono_set_timeout_exec (int id)
547 ERROR_DECL (error);
548 MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "WasmRuntime");
549 g_assert (klass);
551 MonoMethod *method = mono_class_get_method_from_name_checked (klass, "TimeoutCallback", -1, 0, error);
552 mono_error_assert_ok (error);
553 g_assert (method);
555 gpointer params[1] = { &id };
556 MonoObject *exc = NULL;
558 mono_runtime_try_invoke (method, NULL, params, &exc, error);
560 //YES we swallow exceptions cuz there's nothing much we can do from here.
561 //FIXME Maybe call the unhandled exception function?
562 if (!is_ok (error)) {
563 printf ("timeout callback failed due to %s\n", mono_error_get_message (error));
564 mono_error_cleanup (error);
567 if (exc) {
568 char *type_name = mono_type_get_full_name (mono_object_class (exc));
569 printf ("timeout callback threw a %s\n", type_name);
570 g_free (type_name);
574 #endif
576 void
577 mono_wasm_set_timeout (int timeout, int id)
579 #ifdef HOST_WASM
580 mono_set_timeout (timeout, id);
581 #endif
584 void
585 mono_arch_register_icall (void)
587 mono_add_internal_call_internal ("System.Threading.WasmRuntime::SetTimeout", mono_wasm_set_timeout);
590 void
591 mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gpointer target)
593 g_error ("mono_arch_patch_code_new");
596 #ifdef HOST_WASM
599 The following functions don't belong here, but are due to laziness.
601 gboolean mono_w32file_get_file_system_type (const gunichar2 *path, gunichar2 *fsbuffer, gint fsbuffersize);
603 G_BEGIN_DECLS
605 void * getgrnam (const char *name);
606 void * getgrgid (gid_t gid);
607 int inotify_init (void);
608 int inotify_rm_watch (int fd, int wd);
609 int inotify_add_watch (int fd, const char *pathname, uint32_t mask);
610 int sem_timedwait (sem_t *sem, const struct timespec *abs_timeout);
612 G_END_DECLS
614 //w32file-wasm.c
615 gboolean
616 mono_w32file_get_file_system_type (const gunichar2 *path, gunichar2 *fsbuffer, gint fsbuffersize)
618 glong len;
619 gboolean status = FALSE;
621 gunichar2 *ret = g_utf8_to_utf16 ("memfs", -1, NULL, &len, NULL);
622 if (ret != NULL && len < fsbuffersize) {
623 memcpy (fsbuffer, ret, len * sizeof (gunichar2));
624 fsbuffer [len] = 0;
625 status = TRUE;
627 if (ret != NULL)
628 g_free (ret);
630 return status;
633 G_BEGIN_DECLS
635 //llvm builtin's that we should not have used in the first place
637 #include <sys/types.h>
638 #include <pwd.h>
639 #include <uuid/uuid.h>
641 //libc / libpthread missing bits from musl or shit we didn't detect :facepalm:
642 int pthread_getschedparam (pthread_t thread, int *policy, struct sched_param *param)
644 g_error ("pthread_getschedparam");
645 return 0;
649 pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
651 return 0;
656 pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *stacksize)
658 return 65536; //wasm page size
662 pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
664 return 0;
669 sigsuspend(const sigset_t *sigmask)
671 g_error ("sigsuspend");
672 return 0;
676 getdtablesize (void)
678 return 256; //random constant that is the fd limit
681 void *
682 getgrnam (const char *name)
684 return NULL;
687 void *
688 getgrgid (gid_t gid)
690 return NULL;
694 inotify_init (void)
696 g_error ("inotify_init");
700 inotify_rm_watch (int fd, int wd)
702 g_error ("inotify_rm_watch");
703 return 0;
707 inotify_add_watch (int fd, const char *pathname, uint32_t mask)
709 g_error ("inotify_add_watch");
710 return 0;
714 sem_timedwait (sem_t *sem, const struct timespec *abs_timeout)
716 g_error ("sem_timedwait");
717 return 0;
721 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
723 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
725 g_error ("sendfile");
726 return 0;
730 getpwnam_r (const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
731 struct passwd **result)
733 g_error ("getpwnam_r");
734 return 0;
738 getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
739 struct passwd **result)
741 g_error ("getpwuid_r");
742 return 0;
745 G_END_DECLS
747 #endif // HOST_WASM