Revert "[mono][debugger] First PR to implement iCorDebug on mono (#20757)"
[mono-project.git] / mono / mini / mini-wasm.c
blobf8d3e1855be75801dcdd237a987b0c3660af8698
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>
11 #include <mono/utils/mono-threads.h>
13 //XXX This is dirty, extend ee.h to support extracting info from MonoInterpFrameHandle
14 #include <mono/mini/interp/interp-internals.h>
16 #ifndef DISABLE_JIT
18 #include "ir-emit.h"
19 #include "cpu-wasm.h"
21 //FIXME figure out if we need to distingush between i,l,f,d types
22 typedef enum {
23 ArgOnStack,
24 ArgValuetypeAddrOnStack,
25 ArgGsharedVTOnStack,
26 ArgValuetypeAddrInIReg,
27 ArgInvalid,
28 } ArgStorage;
30 typedef struct {
31 ArgStorage storage : 8;
32 } ArgInfo;
34 struct CallInfo {
35 int nargs;
36 gboolean gsharedvt;
38 ArgInfo ret;
39 ArgInfo args [1];
42 static ArgStorage
43 get_storage (MonoType *type, gboolean is_return)
45 switch (type->type) {
46 case MONO_TYPE_I1:
47 case MONO_TYPE_U1:
48 case MONO_TYPE_I2:
49 case MONO_TYPE_U2:
50 case MONO_TYPE_I4:
51 case MONO_TYPE_U4:
52 case MONO_TYPE_I:
53 case MONO_TYPE_U:
54 case MONO_TYPE_PTR:
55 case MONO_TYPE_FNPTR:
56 case MONO_TYPE_OBJECT:
57 return ArgOnStack;
59 case MONO_TYPE_U8:
60 case MONO_TYPE_I8:
61 return ArgOnStack;
63 case MONO_TYPE_R4:
64 return ArgOnStack;
66 case MONO_TYPE_R8:
67 return ArgOnStack;
69 case MONO_TYPE_GENERICINST:
70 if (!mono_type_generic_inst_is_valuetype (type))
71 return ArgOnStack;
73 if (mini_is_gsharedvt_type (type)) {
74 return ArgGsharedVTOnStack;
76 /* fall through */
77 case MONO_TYPE_VALUETYPE:
78 case MONO_TYPE_TYPEDBYREF: {
79 return is_return ? ArgValuetypeAddrInIReg : ArgValuetypeAddrOnStack;
80 break;
82 case MONO_TYPE_VAR:
83 case MONO_TYPE_MVAR:
84 g_assert (mini_is_gsharedvt_type (type));
85 return ArgGsharedVTOnStack;
86 break;
87 case MONO_TYPE_VOID:
88 g_assert (is_return);
89 break;
90 default:
91 g_error ("Can't handle as return value 0x%x", type->type);
93 return ArgInvalid;
96 static CallInfo*
97 get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
99 int n = sig->hasthis + sig->param_count;
100 CallInfo *cinfo;
102 if (mp)
103 cinfo = (CallInfo *)mono_mempool_alloc0 (mp, sizeof (CallInfo) + (sizeof (ArgInfo) * n));
104 else
105 cinfo = (CallInfo *)g_malloc0 (sizeof (CallInfo) + (sizeof (ArgInfo) * n));
107 cinfo->nargs = n;
108 cinfo->gsharedvt = mini_is_gsharedvt_variable_signature (sig);
110 /* return value */
111 cinfo->ret.storage = get_storage (mini_get_underlying_type (sig->ret), TRUE);
113 if (sig->hasthis)
114 cinfo->args [0].storage = ArgOnStack;
116 // not supported
117 g_assert (sig->call_convention != MONO_CALL_VARARG);
119 int i;
120 for (i = 0; i < sig->param_count; ++i)
121 cinfo->args [i + sig->hasthis].storage = get_storage (mini_get_underlying_type (sig->params [i]), FALSE);
123 return cinfo;
126 gboolean
127 mono_arch_have_fast_tls (void)
129 return FALSE;
132 guint32
133 mono_arch_get_patch_offset (guint8 *code)
135 g_error ("mono_arch_get_patch_offset");
136 return 0;
138 gpointer
139 mono_arch_ip_from_context (void *sigctx)
141 g_error ("mono_arch_ip_from_context");
144 gboolean
145 mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
147 return TRUE;
150 void
151 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
155 gboolean
156 mono_arch_opcode_supported (int opcode)
158 return FALSE;
161 void
162 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
164 g_error ("mono_arch_output_basic_block");
167 void
168 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
172 void
173 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
177 guint32
178 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
180 return 0;
183 GList *
184 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
186 g_error ("mono_arch_get_allocatable_int_vars");
189 GList *
190 mono_arch_get_global_int_regs (MonoCompile *cfg)
192 g_error ("mono_arch_get_global_int_regs");
195 void
196 mono_arch_allocate_vars (MonoCompile *cfg)
198 g_error ("mono_arch_allocate_vars");
201 void
202 mono_arch_create_vars (MonoCompile *cfg)
204 MonoMethodSignature *sig;
205 CallInfo *cinfo;
206 MonoType *sig_ret;
208 sig = mono_method_signature_internal (cfg->method);
210 if (!cfg->arch.cinfo)
211 cfg->arch.cinfo = get_call_info (cfg->mempool, sig);
212 cinfo = (CallInfo *)cfg->arch.cinfo;
214 // if (cinfo->ret.storage == ArgValuetypeInReg)
215 // cfg->ret_var_is_local = TRUE;
217 sig_ret = mini_get_underlying_type (sig->ret);
218 if (cinfo->ret.storage == ArgValuetypeAddrInIReg || cinfo->ret.storage == ArgGsharedVTOnStack) {
219 cfg->vret_addr = mono_compile_create_var (cfg, mono_get_int_type (), OP_ARG);
220 if (G_UNLIKELY (cfg->verbose_level > 1)) {
221 printf ("vret_addr = ");
222 mono_print_ins (cfg->vret_addr);
226 if (cfg->gen_sdb_seq_points)
227 g_error ("gen_sdb_seq_points not supported");
229 if (cfg->method->save_lmf) {
230 cfg->create_lmf_var = TRUE;
231 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 extern void mono_wasm_queue_tp_cb (void);
395 G_END_DECLS
397 void mono_background_exec (void);
399 #endif // HOST_WASM
401 gpointer
402 mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code)
404 g_error ("mono_arch_get_this_arg_from_call");
407 gpointer
408 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
410 g_error ("mono_arch_get_delegate_virtual_invoke_impl");
414 void
415 mono_arch_cpu_init (void)
417 // printf ("mono_arch_cpu_init\n");
420 void
421 mono_arch_finish_init (void)
423 // printf ("mono_arch_finish_init\n");
426 void
427 mono_arch_init (void)
429 // printf ("mono_arch_init\n");
432 void
433 mono_arch_cleanup (void)
437 void
438 mono_arch_register_lowlevel_calls (void)
442 void
443 mono_arch_flush_register_windows (void)
447 MonoMethod*
448 mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code)
450 g_error ("mono_arch_find_static_call_vtable");
451 return (MonoMethod*) regs [MONO_ARCH_IMT_REG];
454 MonoVTable*
455 mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code)
457 g_error ("mono_arch_find_static_call_vtable");
458 return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
461 GSList*
462 mono_arch_get_cie_program (void)
464 GSList *l = NULL;
466 return l;
469 gpointer
470 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
472 g_error ("mono_arch_build_imt_trampoline");
475 guint32
476 mono_arch_cpu_optimizations (guint32 *exclude_mask)
478 /* No arch specific passes yet */
479 *exclude_mask = 0;
480 return 0;
483 host_mgreg_t
484 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
486 g_error ("mono_arch_context_get_int_reg");
487 return 0;
490 #ifdef HOST_WASM
492 void
493 mono_runtime_setup_stat_profiler (void)
495 g_error ("mono_runtime_setup_stat_profiler");
499 void
500 mono_runtime_shutdown_stat_profiler (void)
502 g_error ("mono_runtime_shutdown_stat_profiler");
506 gboolean
507 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
509 g_error ("mono_chain_signal");
511 return FALSE;
514 void
515 mono_runtime_install_handlers (void)
519 void
520 mono_runtime_cleanup_handlers (void)
524 void
525 mono_init_native_crash_info (void)
527 return;
530 void
531 mono_cleanup_native_crash_info (void)
533 return;
536 gboolean
537 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info, void *sigctx)
539 g_error ("WASM systems don't support mono_thread_state_init_from_handle");
540 return FALSE;
543 EMSCRIPTEN_KEEPALIVE void
544 mono_set_timeout_exec (int id)
546 ERROR_DECL (error);
548 #ifdef ENABLE_NETCORE
549 MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "TimerQueue");
550 #else
551 MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "WasmRuntime");
552 #endif
553 g_assert (klass);
555 MonoMethod *method = mono_class_get_method_from_name_checked (klass, "TimeoutCallback", -1, 0, error);
556 mono_error_assert_ok (error);
557 g_assert (method);
559 gpointer params[1] = { &id };
560 MonoObject *exc = NULL;
562 mono_runtime_try_invoke (method, NULL, params, &exc, error);
564 //YES we swallow exceptions cuz there's nothing much we can do from here.
565 //FIXME Maybe call the unhandled exception function?
566 if (!is_ok (error)) {
567 printf ("timeout callback failed due to %s\n", mono_error_get_message (error));
568 mono_error_cleanup (error);
571 if (exc) {
572 char *type_name = mono_type_get_full_name (mono_object_class (exc));
573 printf ("timeout callback threw a %s\n", type_name);
574 g_free (type_name);
578 #endif
580 void
581 mono_wasm_set_timeout (int timeout, int id)
583 #ifdef HOST_WASM
584 mono_set_timeout (timeout, id);
585 #endif
588 static void
589 tp_cb (void)
591 ERROR_DECL (error);
593 MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System.Threading", "ThreadPool");
594 g_assert (klass);
596 MonoMethod *method = mono_class_get_method_from_name_checked (klass, "Callback", -1, 0, error);
597 mono_error_assert_ok (error);
598 g_assert (method);
600 MonoObject *exc = NULL;
602 mono_runtime_try_invoke (method, NULL, NULL, &exc, error);
604 if (!is_ok (error)) {
605 printf ("ThreadPool Callback failed due to error: %s\n", mono_error_get_message (error));
606 mono_error_cleanup (error);
609 if (exc) {
610 char *type_name = mono_type_get_full_name (mono_object_class (exc));
611 printf ("ThreadPool Callback threw an unhandled exception of type %s\n", type_name);
612 g_free (type_name);
616 #ifdef HOST_WASM
617 void
618 mono_wasm_queue_tp_cb (void)
620 mono_threads_schedule_background_job (tp_cb);
622 #endif
624 void
625 mono_arch_register_icall (void)
627 #ifdef HOST_WASM
628 #ifdef ENABLE_NETCORE
629 mono_add_internal_call_internal ("System.Threading.TimerQueue::SetTimeout", mono_wasm_set_timeout);
630 mono_add_internal_call_internal ("System.Threading.ThreadPool::QueueCallback", mono_wasm_queue_tp_cb);
631 #else
632 mono_add_internal_call_internal ("System.Threading.WasmRuntime::SetTimeout", mono_wasm_set_timeout);
633 #endif
634 #endif
637 void
638 mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code, MonoJumpInfo *ji, gpointer target)
640 g_error ("mono_arch_patch_code_new");
643 #ifdef HOST_WASM
646 The following functions don't belong here, but are due to laziness.
648 gboolean mono_w32file_get_file_system_type (const gunichar2 *path, gunichar2 *fsbuffer, gint fsbuffersize);
650 G_BEGIN_DECLS
652 void * getgrnam (const char *name);
653 void * getgrgid (gid_t gid);
654 int inotify_init (void);
655 int inotify_rm_watch (int fd, int wd);
656 int inotify_add_watch (int fd, const char *pathname, uint32_t mask);
657 int sem_timedwait (sem_t *sem, const struct timespec *abs_timeout);
659 G_END_DECLS
661 //w32file-wasm.c
662 gboolean
663 mono_w32file_get_file_system_type (const gunichar2 *path, gunichar2 *fsbuffer, gint fsbuffersize)
665 glong len;
666 gboolean status = FALSE;
668 gunichar2 *ret = g_utf8_to_utf16 ("memfs", -1, NULL, &len, NULL);
669 if (ret != NULL && len < fsbuffersize) {
670 memcpy (fsbuffer, ret, len * sizeof (gunichar2));
671 fsbuffer [len] = 0;
672 status = TRUE;
674 if (ret != NULL)
675 g_free (ret);
677 return status;
680 G_BEGIN_DECLS
682 //llvm builtin's that we should not have used in the first place
684 #include <sys/types.h>
685 #include <pwd.h>
686 #include <uuid/uuid.h>
688 #ifndef __EMSCRIPTEN_PTHREADS__
689 int pthread_getschedparam (pthread_t thread, int *policy, struct sched_param *param)
691 g_error ("pthread_getschedparam");
692 return 0;
694 #endif
697 pthread_setschedparam(pthread_t thread, int policy, const struct sched_param *param)
699 return 0;
703 pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
705 return 0;
710 sigsuspend(const sigset_t *sigmask)
712 g_error ("sigsuspend");
713 return 0;
717 getdtablesize (void)
719 return 256; //random constant that is the fd limit
722 void *
723 getgrnam (const char *name)
725 return NULL;
728 void *
729 getgrgid (gid_t gid)
731 return NULL;
735 inotify_init (void)
737 g_error ("inotify_init");
741 inotify_rm_watch (int fd, int wd)
743 g_error ("inotify_rm_watch");
744 return 0;
748 inotify_add_watch (int fd, const char *pathname, uint32_t mask)
750 g_error ("inotify_add_watch");
751 return 0;
754 #ifndef __EMSCRIPTEN_PTHREADS__
756 sem_timedwait (sem_t *sem, const struct timespec *abs_timeout)
758 g_error ("sem_timedwait");
759 return 0;
761 #endif
763 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
765 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
767 errno = ENOTSUP;
768 return -1;
772 getpwnam_r (const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
773 struct passwd **result)
775 *result = NULL;
776 return ENOTSUP;
780 getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
781 struct passwd **result)
783 *result = NULL;
784 return ENOTSUP;
787 G_END_DECLS
789 #endif // HOST_WASM
791 gpointer
792 mono_arch_load_function (MonoJitICallId jit_icall_id)
794 return NULL;