#define MONO_BREAKPOINT_ARRAY_SIZE 64
+/* C type matching the size of a machine register. Not always the same as 'int' */
+/* Note that member 'p' of MonoInst must be the same type, as OP_PCONST is defined
+ * as one of the OP_ICONST types, so inst_c0 must be the same as inst_p0
+ */
+#if SIZEOF_REGISTER == 4
+typedef gint32 mgreg_t;
+#elif SIZEOF_REGISTER == 8
+typedef gint64 mgreg_t;
+#endif
+
#include "mini-arch.h"
#include "regalloc.h"
#include "declsec.h"
#define MINI_DEBUG(level,limit,code) do {if (G_UNLIKELY ((level) >= (limit))) code} while (0)
#endif
-#define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0)
+#if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS) && defined(__GNUC__)
+#define MONO_SUPPORT_TASKLETS 1
+#endif
-#ifndef DISABLE_AOT
-#define MONO_USE_AOT_COMPILER
+#if ENABLE_LLVM
+#define COMPILE_LLVM(cfg) ((cfg)->compile_llvm)
+#define LLVM_ENABLED TRUE
+#else
+#define COMPILE_LLVM(cfg) (0)
+#define LLVM_ENABLED FALSE
#endif
+#define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0)
+
/* for 32 bit systems */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define MINI_LS_WORD_IDX 0
#define MONO_FAKE_IMT_METHOD ((MonoMethod*)GINT_TO_POINTER(-1))
#define MONO_FAKE_VTABLE_METHOD ((MonoMethod*)GINT_TO_POINTER(-2))
+#ifndef DISABLE_AOT
+#define MONO_USE_AOT_COMPILER
+#endif
+
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "45"
+#define MONO_AOT_FILE_VERSION "54"
+
+/* Constants used to encode different types of methods in AOT */
+enum {
+ MONO_AOT_METHODREF_MIN = 240,
+ /* Method encoded using its name */
+ MONO_AOT_METHODREF_WRAPPER_NAME = 250,
+ /* Runtime provided methods on arrays */
+ MONO_AOT_METHODREF_ARRAY = 251,
+ MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE = 252,
+ /* Wrappers */
+ MONO_AOT_METHODREF_WRAPPER = 253,
+ /* Methods on generic instances */
+ MONO_AOT_METHODREF_GINST = 254,
+ /* Methods resolve using a METHODSPEC token */
+ MONO_AOT_METHODREF_METHODSPEC = 255,
+};
+
+/* Trampolines which we have a lot of */
+typedef enum {
+ MONO_AOT_TRAMP_SPECIFIC = 0,
+ MONO_AOT_TRAMP_STATIC_RGCTX = 1,
+ MONO_AOT_TRAMP_IMT_THUNK = 2,
+ MONO_AOT_TRAMP_NUM = 3
+} MonoAotTrampoline;
+
+/* This structure is stored in the AOT file */
+typedef struct MonoAotFileInfo
+{
+ guint32 plt_got_offset_base;
+ guint32 got_size;
+ guint32 plt_size;
+
+ guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
+ guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
+ guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
+} MonoAotFileInfo;
/* Per-domain information maintained by the JIT */
typedef struct
GHashTable *jump_trampoline_hash;
GHashTable *jit_trampoline_hash;
GHashTable *delegate_trampoline_hash;
+ GHashTable *static_rgctx_trampoline_hash;
+ GHashTable *llvm_vcall_trampoline_hash;
/* maps MonoMethod -> MonoJitDynamicMethodInfo */
GHashTable *dynamic_code_hash;
GHashTable *method_code_hash;
+ /* Compiled runtime invoke function for parameterless ctors */
+ gpointer ctor_runtime_invoke;
} MonoJitDomainInfo;
typedef struct {
#define MONO_VARINFO(cfg,varnum) (&(cfg)->vars [varnum])
+#define MONO_INST_NULLIFY_SREGS(dest) do { \
+ (dest)->sreg1 = (dest)->sreg2 = (dest)->sreg3 = -1; \
+ } while (0)
+
#define MONO_INST_NEW(cfg,dest,op) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
(dest)->opcode = (op); \
- (dest)->dreg = (dest)->sreg1 = (dest)->sreg2 = -1; \
+ (dest)->dreg = -1; \
+ MONO_INST_NULLIFY_SREGS ((dest)); \
(dest)->cil_code = (cfg)->ip; \
- (dest)->cil_code = (cfg)->ip; \
} while (0)
#define MONO_INST_NEW_CALL(cfg,dest,op) do { \
(dest) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoCallInst)); \
(dest)->inst.opcode = (op); \
- (dest)->inst.dreg = (dest)->inst.sreg1 = (dest)->inst.sreg2 = -1; \
+ (dest)->inst.dreg = -1; \
+ MONO_INST_NULLIFY_SREGS (&(dest)->inst); \
(dest)->inst.cil_code = (cfg)->ip; \
} while (0)
#define NULLIFY_INS(ins) do { \
(ins)->opcode = OP_NOP; \
- (ins)->dreg = (ins)->sreg1 = (ins)->sreg2 = -1; \
+ (ins)->dreg = -1; \
+ MONO_INST_NULLIFY_SREGS ((ins)); \
(ins)->ssa_op = MONO_SSA_NOP; \
} while (0)
#define MONO_IS_SETCC(ins) ((((ins)->opcode >= OP_CEQ) && ((ins)->opcode <= OP_CLT_UN)) || (((ins)->opcode >= OP_ICEQ) && ((ins)->opcode <= OP_ICLT_UN)) || (((ins)->opcode >= OP_LCEQ) && ((ins)->opcode <= OP_LCLT_UN)) || (((ins)->opcode >= OP_FCEQ) && ((ins)->opcode <= OP_FCLT_UN)))
-#define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI))
#define MONO_IS_LOAD_MEMBASE(ins) (((ins)->opcode >= OP_LOAD_MEMBASE) && ((ins)->opcode <= OP_LOADV_MEMBASE))
#define MONO_IS_STORE_MEMBASE(ins) (((ins)->opcode >= OP_STORE_MEMBASE_REG) && ((ins)->opcode <= OP_STOREV_MEMBASE))
/* FIXME: Add more instructions */
#define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_INEG) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2))
+#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && ((m)->klass->flags & TYPE_ATTRIBUTE_SEALED)))
#ifdef MONO_ARCH_SIMD_INTRINSICS
+#define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI) || ((ins)->opcode == OP_XPHI))
#define MONO_IS_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_VMOVE) || ((ins)->opcode == OP_XMOVE))
#define MONO_IS_NON_FP_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_VMOVE) || ((ins)->opcode == OP_XMOVE))
#define MONO_IS_REAL_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_XMOVE))
#else
+#define MONO_IS_PHI(ins) (((ins)->opcode == OP_PHI) || ((ins)->opcode == OP_FPHI) || ((ins)->opcode == OP_VPHI))
#define MONO_IS_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_FMOVE) || ((ins)->opcode == OP_VMOVE))
#define MONO_IS_NON_FP_MOVE(ins) (((ins)->opcode == OP_MOVE) || ((ins)->opcode == OP_VMOVE))
/*A real MOVE is one that isn't decomposed such as a VMOVE or LMOVE*/
extern gboolean mono_dont_free_global_codeman;
extern gboolean mono_do_x86_stack_align;
extern const char *mono_build_date;
+extern gboolean mono_do_signal_chaining;
-#define INS_INFO(opcode) (&ins_info [((opcode) - OP_START - 1) * 3])
+#define INS_INFO(opcode) (&ins_info [((opcode) - OP_START - 1) * 4])
extern const char ins_info[];
+extern const gint8 ins_sreg_counts [];
+
+#define mono_inst_get_num_src_registers(ins) (ins_sreg_counts [(ins)->opcode - OP_START - 1])
+#define mono_inst_get_src_registers(ins, regs) (((regs) [0] = (ins)->sreg1), ((regs) [1] = (ins)->sreg2), ((regs) [2] = (ins)->sreg3), mono_inst_get_num_src_registers ((ins)))
#define MONO_BB_FOR_EACH_INS(bb, ins) for ((ins) = (bb)->code; (ins); (ins) = (ins)->next)
/* The address of the generated code, used for fixups */
int native_offset;
int max_offset;
+ int max_length;
/* Visited and reachable flags */
guint32 flags;
int size, align;
} MonoMemcpyArgs;
+typedef enum {
+ LLVMArgNone,
+ LLVMArgInIReg,
+ LLVMArgInFPReg,
+ LLVMArgVtypeInReg,
+ LLVMArgVtypeByVal,
+ LLVMArgVtypeRetAddr /* On on cinfo->ret */
+} LLVMArgStorage;
+
+typedef struct {
+ LLVMArgStorage storage;
+
+ /* Only if storage == ArgValuetypeInReg */
+ LLVMArgStorage pair_storage [2];
+} LLVMArgInfo;
+
+typedef struct {
+ LLVMArgInfo ret;
+ /* args [0] is for the this argument if it exists */
+ LLVMArgInfo args [1];
+} LLVMCallInfo;
+
+#define MONO_MAX_SRC_REGS 3
+
struct MonoInst {
guint16 opcode;
guint8 type; /* stack type */
guint8 flags : 5;
/* used by the register allocator */
- gint32 dreg, sreg1, sreg2;
+ gint32 dreg, sreg1, sreg2, sreg3;
MonoInst *next, *prev;
union {
MonoInst *src;
MonoMethodVar *var;
- gssize const_val;
+ mgreg_t const_val;
+#if (SIZEOF_REGISTER > SIZEOF_VOID_P) && (G_BYTE_ORDER == G_BIG_ENDIAN)
+ struct {
+ gpointer p[SIZEOF_REGISTER/SIZEOF_VOID_P];
+ } pdata;
+#else
gpointer p;
+#endif
MonoMethod *method;
MonoMethodSignature *signature;
MonoBasicBlock **many_blocks;
guint vret_in_reg : 1;
/* Whenever there is an IMT argument and it is dynamic */
guint dynamic_imt_arg : 1;
+ /* Whenever there is an RGCTX argument */
+ guint32 rgctx_reg : 1;
regmask_t used_iregs;
regmask_t used_fregs;
GSList *out_ireg_args;
GSList *out_freg_args;
+#ifdef ENABLE_LLVM
+ LLVMCallInfo *cinfo;
+#endif
};
struct MonoCallArgParm {
MONO_INST_IS_DEAD = 2,
MONO_INST_TAILCALL = 4,
MONO_INST_VOLATILE = 4,
- MONO_INST_BRLABEL = 4,
MONO_INST_NOTYPECHECK = 4,
MONO_INST_UNALIGNED = 8,
MONO_INST_CFOLD_TAKEN = 8, /* On branches */
#define inst_c1 data.op[1].const_val
#define inst_i0 data.op[0].src
#define inst_i1 data.op[1].src
+#if (SIZEOF_REGISTER > SIZEOF_VOID_P) && (G_BYTE_ORDER == G_BIG_ENDIAN)
+#define inst_p0 data.op[0].pdata.p[SIZEOF_REGISTER/SIZEOF_VOID_P - 1]
+#define inst_p1 data.op[1].pdata.p[SIZEOF_REGISTER/SIZEOF_VOID_P - 1]
+#else
#define inst_p0 data.op[0].p
#define inst_p1 data.op[1].p
+#endif
#define inst_l data.i8const
#define inst_r data.r8const
#define inst_left data.op[0].src
/* instruction description for use in regalloc/scheduling */
enum {
MONO_INST_DEST,
- MONO_INST_SRC1,
+ MONO_INST_SRC1, /* we depend on the SRCs to be consecutive */
MONO_INST_SRC2,
+ MONO_INST_SRC3,
MONO_INST_LEN,
MONO_INST_CLOB,
/* Unused, commented out to reduce the size of the mdesc tables
MonoBasicBlock *def_bb; /* used by SSA */
GList *uses; /* used by SSA */
char cpstate; /* used by SSA conditional constant propagation */
+ /* The native offsets corresponding to the live range of the variable */
+ gint32 live_range_start, live_range_end;
+ /*
+ * cfg->varinfo [idx]->dreg could be replaced for OP_REGVAR, this contains the
+ * original vreg.
+ */
+ gint32 vreg;
};
typedef struct {
MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
MONO_TRAMPOLINE_MONITOR_ENTER,
MONO_TRAMPOLINE_MONITOR_EXIT,
+#ifdef ENABLE_LLVM
+ MONO_TRAMPOLINE_LLVM_VCALL,
+#endif
MONO_TRAMPOLINE_NUM
} MonoTrampolineType;
gint stack_offset;
gint max_ireg;
gint cil_offset_to_bb_len;
+ gint locals_min_stack_offset, locals_max_stack_offset;
MonoRegState *rs;
MonoSpillInfo *spill_info [16]; /* machine register spills */
gint spill_count;
gint32 sig_cookie;
guint disable_aot : 1;
guint disable_ssa : 1;
+ guint disable_llvm : 1;
guint enable_extended_bblocks : 1;
guint run_cctors : 1;
guint need_lmf_area : 1;
guint compile_aot : 1;
+ guint compile_llvm : 1;
guint got_var_allocated : 1;
guint ret_var_is_local : 1;
guint ret_var_set : 1;
guint disable_initlocals_opt : 1;
guint disable_omit_fp : 1;
guint disable_vreg_to_lvreg : 1;
+ guint disable_deadce_vars : 1;
+ guint extend_live_ranges : 1;
guint has_got_slots : 1;
guint uses_rgctx_reg : 1;
guint uses_vtable_reg : 1;
char* exception_message;
gpointer exception_ptr;
+ guint8 * encoded_unwind_ops;
+ guint32 encoded_unwind_ops_len;
GSList* unwind_ops;
/* Fields used by the local reg allocator */
#ifdef MINI_OP
#undef MINI_OP
#endif
+#ifdef MINI_OP3
+#undef MINI_OP3
+#endif
#define MINI_OP(a,b,dest,src1,src2) a,
+#define MINI_OP3(a,b,dest,src1,src2,src3) a,
enum {
OP_START = MONO_CEE_LAST - 1,
#include "mini-ops.h"
OP_LAST
};
#undef MINI_OP
+#undef MINI_OP3
#if SIZEOF_VOID_P == 8
#define OP_PCONST OP_I8CONST
gboolean better_cast_details;
gboolean mdb_optimizations;
gboolean no_gdb_backtrace;
+ gboolean suspend_on_sigsegv;
} MonoDebugOptions;
enum {
MINI_TOKEN_SOURCE_FIELD
};
+/*
+ * This structures contains information about a trampoline function required by
+ * the AOT compiler in full-aot mode.
+ */
+typedef struct
+{
+ guint8 *code;
+ guint32 code_size;
+ char *name;
+} MonoAotTrampInfo;
+
typedef void (*MonoInstFunc) (MonoInst *tree, gpointer data);
/* main function */
void mono_print_method_from_ip (void *ip);
char *mono_pmip (void *ip);
const char* mono_inst_name (int op);
+void mono_inst_set_src_registers (MonoInst *ins, int *regs) MONO_INTERNAL;
int mono_op_to_op_imm (int opcode) MONO_INTERNAL;
int mono_op_imm_to_op (int opcode) MONO_INTERNAL;
int mono_load_membase_to_load_mem (int opcode) MONO_INTERNAL;
gint mono_patch_info_equal (gconstpointer ka, gconstpointer kb) MONO_INTERNAL;
MonoJumpInfo *mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target) MONO_INTERNAL;
gpointer mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors) MONO_INTERNAL;
+gpointer mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji) MONO_INTERNAL;
gpointer mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method) MONO_INTERNAL;
MonoLMF * mono_get_lmf (void) MONO_INTERNAL;
MonoLMF** mono_get_lmf_addr (void) MONO_INTERNAL;
gint32 mono_get_lmf_tls_offset (void) MONO_INTERNAL;
gint32 mono_get_lmf_addr_tls_offset (void) MONO_INTERNAL;
MonoInst* mono_get_jit_tls_intrinsic (MonoCompile *cfg) MONO_INTERNAL;
+MonoInst* mono_get_domain_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
+MonoInst* mono_get_thread_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
GList *mono_varlist_insert_sorted (MonoCompile *cfg, GList *list, MonoMethodVar *mv, gboolean sort_end) MONO_INTERNAL;
GList *mono_varlist_sort (MonoCompile *cfg, GList *list, int sort_type) MONO_INTERNAL;
void mono_analyze_liveness (MonoCompile *cfg) MONO_INTERNAL;
gpointer mono_aot_get_named_code (const char *name) MONO_INTERNAL;
gpointer mono_aot_get_unbox_trampoline (MonoMethod *method) MONO_INTERNAL;
gpointer mono_aot_get_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
+gpointer mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr) MONO_INTERNAL;
+gpointer mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) MONO_INTERNAL;
+guint8* mono_aot_get_unwind_info (MonoJitInfo *ji, guint32 *unwind_info_len) MONO_INTERNAL;
+guint32 mono_aot_method_hash (MonoMethod *method) MONO_INTERNAL;
+char* mono_aot_wrapper_name (MonoMethod *method) MONO_INTERNAL;
+MonoAotTrampInfo* mono_aot_tramp_info_create (const char *name, guint8 *code, guint32 code_len) MONO_INTERNAL;
+gboolean mono_aot_is_shared_got_patch (MonoJumpInfo *patch_info) MONO_INTERNAL;
+guint mono_aot_str_hash (gconstpointer v1) MONO_INTERNAL;
+
/* This is an exported function */
void mono_aot_register_globals (gpointer *globals);
/* This too */
void mono_aot_register_module (gpointer *aot_info);
-void mono_save_xdebug_info (MonoMethod *method, guint8 *code, guint32 code_size, MonoInst **args, GSList *unwind_info) MONO_INTERNAL;
+void mono_xdebug_init (void) MONO_INTERNAL;
+void mono_save_xdebug_info (MonoCompile *cfg) MONO_INTERNAL;
+void mono_save_trampoline_xdebug_info (const char *tramp_name, guint8 *code, guint32 code_size, GSList *unwind_info) MONO_INTERNAL;
/* This is an exported function */
void mono_xdebug_emit (void) MONO_INTERNAL;
+/* LLVM backend */
+void mono_llvm_init (void) MONO_INTERNAL;
+void mono_llvm_cleanup (void) MONO_INTERNAL;
+void mono_llvm_emit_method (MonoCompile *cfg) MONO_INTERNAL;
+void mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call) MONO_INTERNAL;
+
gboolean mono_method_blittable (MonoMethod *method) MONO_INTERNAL;
gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee) MONO_INTERNAL;
gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset) MONO_INTERNAL;
gpointer mono_create_monitor_enter_trampoline (void) MONO_INTERNAL;
gpointer mono_create_monitor_exit_trampoline (void) MONO_INTERNAL;
+gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) MONO_INTERNAL;
+gpointer mono_create_llvm_vcall_trampoline (MonoMethod *method) MONO_INTERNAL;
MonoVTable* mono_find_class_init_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
MonoClass* mono_find_delegate_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
guint32 mono_find_rgctx_lazy_fetch_trampoline_by_addr (gconstpointer addr) MONO_INTERNAL;
void mono_monitor_exit_trampoline (gssize *regs, guint8 *code, MonoObject *obj, guint8 *tramp) MONO_INTERNAL;
gconstpointer mono_get_trampoline_func (MonoTrampolineType tramp_type);
gpointer mini_get_vtable_trampoline (void) MONO_INTERNAL;
+gpointer* mono_get_vcall_slot_addr (guint8* code, gpointer *regs) MONO_INTERNAL;
gboolean mono_running_on_valgrind (void) MONO_INTERNAL;
void* mono_global_codeman_reserve (int size) MONO_INTERNAL;
int mono_op_imm_to_op (int opcode) MONO_INTERNAL;
void mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) MONO_INTERNAL;
void mono_peephole_ins (MonoBasicBlock *bb, MonoInst *ins) MONO_INTERNAL;
+MonoUnwindOp *mono_create_unwind_op (int when,
+ int tag, int reg,
+ int val) MONO_INTERNAL;
void mono_emit_unwind_op (MonoCompile *cfg, int when,
int tag, int reg,
int val) MONO_INTERNAL;
MonoInst *return_var, GList *dont_inline, MonoInst **inline_args,
guint inline_offset, gboolean is_virtual_call) MONO_INTERNAL;
-void mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
+MonoInst *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
void mono_decompose_long_opts (MonoCompile *cfg) MONO_INTERNAL;
void mono_decompose_vtype_opts (MonoCompile *cfg) MONO_INTERNAL;
void mono_decompose_array_access_opts (MonoCompile *cfg) MONO_INTERNAL;
void mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code) MONO_INTERNAL;
void *mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) MONO_INTERNAL;
void *mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) MONO_INTERNAL;
+void *mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers) MONO_INTERNAL;
void mono_codegen (MonoCompile *cfg) MONO_INTERNAL;
void mono_call_inst_add_outarg_reg (MonoCompile *cfg, MonoCallInst *call, int vreg, int hreg, gboolean fp) MONO_INTERNAL;
const char *mono_arch_regname (int reg) MONO_INTERNAL;
gpointer mono_arch_get_rethrow_exception (void) MONO_INTERNAL;
gpointer mono_arch_get_throw_exception_by_name (void) MONO_INTERNAL;
gpointer mono_arch_get_throw_corlib_exception (void) MONO_INTERNAL;
+void mono_arch_exceptions_init (void) MONO_INTERNAL;
guchar* mono_arch_create_trampoline_code (MonoTrampolineType tramp_type) MONO_INTERNAL;
-guchar* mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+guchar* mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, GSList **out_unwind_ops, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline_full (guint32 slot, guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_generic_class_init_trampoline (void) MONO_INTERNAL;
gpointer mono_arch_create_monitor_exit_trampoline (void) MONO_INTERNAL;
gpointer mono_arch_create_monitor_enter_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_monitor_exit_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer mono_arch_create_generic_class_init_trampoline_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MONO_INTERNAL;
GList *mono_arch_get_global_int_regs (MonoCompile *cfg) MONO_INTERNAL;
GList *mono_arch_get_global_fp_regs (MonoCompile *cfg) MONO_INTERNAL;
MonoInst *mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) MONO_INTERNAL;
void mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
void mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
+GSList* mono_arch_get_delegate_invoke_impls (void) MONO_INTERNAL;
+LLVMCallInfo* mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) MONO_INTERNAL;
MonoJitInfo *mono_arch_find_jit_info (MonoDomain *domain,
MonoJitTlsData *jit_tls,
gpointer mono_arch_get_rethrow_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_throw_exception_by_name_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_throw_corlib_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer mono_arch_get_throw_pending_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) MONO_INTERNAL;
void mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
gboolean mono_handle_soft_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr) MONO_INTERNAL;
gboolean mono_arch_is_int_overflow (void *sigctx, void *info) MONO_INTERNAL;
void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) MONO_INTERNAL;
guint32 mono_arch_get_patch_offset (guint8 *code) MONO_INTERNAL;
-gpointer*mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs) MONO_INTERNAL;
gpointer mono_arch_get_vcall_slot (guint8 *code, gpointer *regs, int *displacement) MONO_INTERNAL;
gpointer*mono_arch_get_delegate_method_ptr_addr (guint8* code, gpointer *regs) MONO_INTERNAL;
void mono_arch_create_vars (MonoCompile *cfg) MONO_INTERNAL;
void mono_arch_save_unwind_info (MonoCompile *cfg) MONO_INTERNAL;
void mono_arch_register_lowlevel_calls (void) MONO_INTERNAL;
gpointer mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *m, gpointer addr) MONO_INTERNAL;
+gpointer mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr) MONO_INTERNAL;
void mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) MONO_INTERNAL;
void mono_arch_patch_plt_entry (guint8 *code, guint8 *addr) MONO_INTERNAL;
void mono_arch_nullify_class_init_trampoline(guint8 *code, gssize *regs) MONO_INTERNAL;
MonoVTable* mono_arch_find_static_call_vtable (gpointer *regs, guint8 *code) MONO_INTERNAL;
gpointer mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp) MONO_INTERNAL;
void mono_arch_notify_pending_exc (void) MONO_INTERNAL;
-void mono_arch_fixup_jinfo (MonoCompile *cfg) MONO_INTERNAL;
/* Exception handling */
void mono_exceptions_init (void) MONO_INTERNAL;
};
const char *mono_arch_xregname (int reg) MONO_INTERNAL;
-void mono_simd_simplify_indirection (MonoCompile *cfg) MONO_INTERNAL;
-MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) MONO_INTERNAL;
-guint32 mono_arch_cpu_enumerate_simd_versions (void) MONO_INTERNAL;
-void mono_simd_intrinsics_init (void) MONO_INTERNAL;
+void mono_simd_simplify_indirection (MonoCompile *cfg) MONO_INTERNAL;
+MonoInst* mono_emit_simd_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args) MONO_INTERNAL;
+guint32 mono_arch_cpu_enumerate_simd_versions (void) MONO_INTERNAL;
+void mono_simd_intrinsics_init (void) MONO_INTERNAL;
+
+/*
+ * Per-OS implementation functions.
+ */
+void mono_runtime_install_handlers (void) MONO_INTERNAL;
+void mono_runtime_cleanup_handlers (void) MONO_INTERNAL;
+void mono_runtime_setup_stat_profiler (void) MONO_INTERNAL;
+void mono_runtime_shutdown_stat_profiler (void) MONO_INTERNAL;
+void mono_runtime_posix_install_handlers (void) MONO_INTERNAL;
+
+/*
+ * Signal handling
+ */
+#ifdef MONO_GET_CONTEXT
+#define GET_CONTEXT MONO_GET_CONTEXT
+#endif
+
+#ifndef GET_CONTEXT
+#ifdef PLATFORM_WIN32
+#define GET_CONTEXT \
+ struct sigcontext *ctx = (struct sigcontext*)_dummy;
+#else
+#ifdef MONO_ARCH_USE_SIGACTION
+#define GET_CONTEXT \
+ void *ctx = context;
+#elif defined(__sparc__)
+#define GET_CONTEXT \
+ void *ctx = sigctx;
+#else
+#define GET_CONTEXT \
+ void **_p = (void **)&_dummy; \
+ struct sigcontext *ctx = (struct sigcontext *)++_p;
+#endif
+#endif
+#endif
+
+#ifdef MONO_ARCH_USE_SIGACTION
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context)
+#define SIG_HANDLER_PARAMS _dummy, info, context
+#elif defined(__sparc__)
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *sigctx)
+#define SIG_HANDLER_PARAMS _dummy, sigctx
+#else
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy)
+#define SIG_HANDLER_PARAMS _dummy
+#endif
+
+void SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) MONO_INTERNAL;
+void SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) MONO_INTERNAL;
+void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL;
+void SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL;
+gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL;
/* for MONO_WRAPPER_UNKNOWN subtypes */
enum {