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>
21 //FIXME figure out if we need to distingush between i,l,f,d types
24 ArgValuetypeAddrOnStack
,
26 ArgValuetypeAddrInIReg
,
31 ArgStorage storage
: 8;
43 get_storage (MonoType
*type
, gboolean is_return
)
56 case MONO_TYPE_OBJECT
:
69 case MONO_TYPE_GENERICINST
:
70 if (!mono_type_generic_inst_is_valuetype (type
))
73 if (mini_is_gsharedvt_type (type
)) {
74 return ArgGsharedVTOnStack
;
77 case MONO_TYPE_VALUETYPE
:
78 case MONO_TYPE_TYPEDBYREF
: {
79 return is_return
? ArgValuetypeAddrInIReg
: ArgValuetypeAddrOnStack
;
84 g_assert (mini_is_gsharedvt_type (type
));
85 return ArgGsharedVTOnStack
;
91 g_error ("Can't handle as return value 0x%x", type
->type
);
97 get_call_info (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
99 int n
= sig
->hasthis
+ sig
->param_count
;
103 cinfo
= (CallInfo
*)mono_mempool_alloc0 (mp
, sizeof (CallInfo
) + (sizeof (ArgInfo
) * n
));
105 cinfo
= (CallInfo
*)g_malloc0 (sizeof (CallInfo
) + (sizeof (ArgInfo
) * n
));
108 cinfo
->gsharedvt
= mini_is_gsharedvt_variable_signature (sig
);
111 cinfo
->ret
.storage
= get_storage (mini_get_underlying_type (sig
->ret
), TRUE
);
114 cinfo
->args
[0].storage
= ArgOnStack
;
117 g_assert (sig
->call_convention
!= MONO_CALL_VARARG
);
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
);
127 mono_arch_have_fast_tls (void)
133 mono_arch_get_patch_offset (guint8
*code
)
135 g_error ("mono_arch_get_patch_offset");
139 mono_arch_ip_from_context (void *sigctx
)
141 g_error ("mono_arch_ip_from_context");
145 mono_arch_is_inst_imm (int opcode
, int imm_opcode
, gint64 imm
)
151 mono_arch_lowering_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
156 mono_arch_opcode_supported (int opcode
)
162 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
164 g_error ("mono_arch_output_basic_block");
168 mono_arch_peephole_pass_1 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
173 mono_arch_peephole_pass_2 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
178 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
184 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
186 g_error ("mono_arch_get_allocatable_int_vars");
190 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
192 g_error ("mono_arch_get_global_int_regs");
196 mono_arch_allocate_vars (MonoCompile
*cfg
)
198 g_error ("mono_arch_allocate_vars");
202 mono_arch_create_vars (MonoCompile
*cfg
)
204 MonoMethodSignature
*sig
;
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
;
236 mono_arch_emit_call (MonoCompile
*cfg
, MonoCallInst
*call
)
238 g_error ("mono_arch_emit_call");
242 mono_arch_emit_epilog (MonoCompile
*cfg
)
244 g_error ("mono_arch_emit_epilog");
248 mono_arch_emit_exceptions (MonoCompile
*cfg
)
250 g_error ("mono_arch_emit_exceptions");
254 mono_arch_emit_inst_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
260 mono_arch_emit_outarg_vt (MonoCompile
*cfg
, MonoInst
*ins
, MonoInst
*src
)
262 g_error ("mono_arch_emit_outarg_vt");
266 mono_arch_emit_prolog (MonoCompile
*cfg
)
268 g_error ("mono_arch_emit_prolog");
272 mono_arch_emit_setret (MonoCompile
*cfg
, MonoMethod
*method
, MonoInst
*val
)
274 MonoType
*ret
= mini_get_underlying_type (mono_method_signature_internal (method
)->ret
);
277 if (ret
->type
== MONO_TYPE_R4
) {
278 MONO_EMIT_NEW_UNALU (cfg
, cfg
->r4fp
? OP_RMOVE
: OP_FMOVE
, cfg
->ret
->dreg
, val
->dreg
);
280 } else if (ret
->type
== MONO_TYPE_R8
) {
281 MONO_EMIT_NEW_UNALU (cfg
, OP_FMOVE
, cfg
->ret
->dreg
, val
->dreg
);
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
);
288 MONO_EMIT_NEW_UNALU (cfg
, OP_MOVE
, cfg
->ret
->dreg
, val
->dreg
);
292 mono_arch_flush_icache (guint8
*code
, gint size
)
297 mono_arch_get_llvm_call_info (MonoCompile
*cfg
, MonoMethodSignature
*sig
)
303 cinfo
= get_call_info (cfg
->mempool
, sig
);
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;
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
) {
322 linfo
->args
[i
].storage
= LLVMArgNormal
;
324 case ArgValuetypeAddrOnStack
:
325 linfo
->args
[i
].storage
= LLVMArgVtypeByRef
;
327 case ArgGsharedVTOnStack
:
328 linfo
->args
[i
].storage
= LLVMArgGsharedvtVariable
;
330 case ArgValuetypeAddrInIReg
:
331 g_error ("this is only valid for sig->ret");
340 mono_arch_tailcall_supported (MonoCompile
*cfg
, MonoMethodSignature
*caller_sig
, MonoMethodSignature
*callee_sig
, gboolean virtual_
)
345 #endif // DISABLE_JIT
348 mono_arch_fregname (int reg
)
354 mono_arch_regname (int reg
)
360 mono_arch_get_argument_info (MonoMethodSignature
*csig
, int param_count
, MonoJitArgumentInfo
*arg_info
)
362 g_error ("mono_arch_get_argument_info");
366 mono_arch_get_delegate_invoke_impls (void)
368 g_error ("mono_arch_get_delegate_invoke_impls");
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");
379 mono_arch_get_delegate_invoke_impl (MonoMethodSignature
*sig
, gboolean has_target
)
381 g_error ("mono_arch_get_delegate_invoke_impl");
386 #include <emscripten.h>
388 //functions exported to be used by JS
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);
397 void mono_background_exec (void);
402 mono_arch_get_this_arg_from_call (host_mgreg_t
*regs
, guint8
*code
)
404 g_error ("mono_arch_get_this_arg_from_call");
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");
415 mono_arch_cpu_init (void)
417 // printf ("mono_arch_cpu_init\n");
421 mono_arch_finish_init (void)
423 // printf ("mono_arch_finish_init\n");
427 mono_arch_init (void)
429 // printf ("mono_arch_init\n");
433 mono_arch_cleanup (void)
438 mono_arch_register_lowlevel_calls (void)
443 mono_arch_flush_register_windows (void)
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
];
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
];
462 mono_arch_get_cie_program (void)
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");
476 mono_arch_cpu_optimizations (guint32
*exclude_mask
)
478 /* No arch specific passes yet */
484 mono_arch_context_get_int_reg (MonoContext
*ctx
, int reg
)
486 g_error ("mono_arch_context_get_int_reg");
493 mono_runtime_setup_stat_profiler (void)
495 g_error ("mono_runtime_setup_stat_profiler");
500 mono_runtime_shutdown_stat_profiler (void)
502 g_error ("mono_runtime_shutdown_stat_profiler");
507 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal
)
509 g_error ("mono_chain_signal");
515 mono_runtime_install_handlers (void)
520 mono_runtime_cleanup_handlers (void)
525 mono_init_native_crash_info (void)
531 mono_cleanup_native_crash_info (void)
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");
543 EMSCRIPTEN_KEEPALIVE
void
544 mono_set_timeout_exec (int id
)
548 #ifdef ENABLE_NETCORE
549 MonoClass
*klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System.Threading", "TimerQueue");
551 MonoClass
*klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System.Threading", "WasmRuntime");
555 MonoMethod
*method
= mono_class_get_method_from_name_checked (klass
, "TimeoutCallback", -1, 0, error
);
556 mono_error_assert_ok (error
);
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
);
572 char *type_name
= mono_type_get_full_name (mono_object_class (exc
));
573 printf ("timeout callback threw a %s\n", type_name
);
581 mono_wasm_set_timeout (int timeout
, int id
)
584 mono_set_timeout (timeout
, id
);
593 MonoClass
*klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System.Threading", "ThreadPool");
596 MonoMethod
*method
= mono_class_get_method_from_name_checked (klass
, "Callback", -1, 0, error
);
597 mono_error_assert_ok (error
);
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
);
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
);
618 mono_wasm_queue_tp_cb (void)
620 mono_threads_schedule_background_job (tp_cb
);
625 mono_arch_register_icall (void)
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
);
632 mono_add_internal_call_internal ("System.Threading.WasmRuntime::SetTimeout", mono_wasm_set_timeout
);
638 mono_arch_patch_code_new (MonoCompile
*cfg
, MonoDomain
*domain
, guint8
*code
, MonoJumpInfo
*ji
, gpointer target
)
640 g_error ("mono_arch_patch_code_new");
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
);
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
);
663 mono_w32file_get_file_system_type (const gunichar2
*path
, gunichar2
*fsbuffer
, gint fsbuffersize
)
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
));
682 //llvm builtin's that we should not have used in the first place
684 #include <sys/types.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");
697 pthread_setschedparam(pthread_t thread
, int policy
, const struct sched_param
*param
)
703 pthread_sigmask (int how
, const sigset_t
*set
, sigset_t
*oset
)
710 sigsuspend(const sigset_t
*sigmask
)
712 g_error ("sigsuspend");
719 return 256; //random constant that is the fd limit
723 getgrnam (const char *name
)
737 g_error ("inotify_init");
741 inotify_rm_watch (int fd
, int wd
)
743 g_error ("inotify_rm_watch");
748 inotify_add_watch (int fd
, const char *pathname
, uint32_t mask
)
750 g_error ("inotify_add_watch");
754 #ifndef __EMSCRIPTEN_PTHREADS__
756 sem_timedwait (sem_t
*sem
, const struct timespec
*abs_timeout
)
758 g_error ("sem_timedwait");
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
)
772 getpwnam_r (const char *name
, struct passwd
*pwd
, char *buffer
, size_t bufsize
,
773 struct passwd
**result
)
780 getpwuid_r (uid_t uid
, struct passwd
*pwd
, char *buffer
, size_t bufsize
,
781 struct passwd
**result
)
792 mono_arch_load_function (MonoJitICallId jit_icall_id
)