2009-04-25 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini.h
index 76a84919af01f1c1ece3234d39f0b38152ddcc7d..f427a9772cab39fa18ba21645913da88e2464f71 100644 (file)
 
 #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
 
+#if !defined(DISABLE_TASKLETS) && defined(MONO_ARCH_SUPPORT_TASKLETS) && defined(__GNUC__)
+#define MONO_SUPPORT_TASKLETS 1
+#endif
+
+#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)
 
 #ifndef DISABLE_AOT
 #define MONO_FAKE_VTABLE_METHOD ((MonoMethod*)GINT_TO_POINTER(-2))
 
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "45"
+#define MONO_AOT_FILE_VERSION "51"
+
+/* 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,
+};
  
 /* Per-domain information maintained by the JIT */
 typedef struct
@@ -80,9 +118,13 @@ 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 {
@@ -121,18 +163,23 @@ enum {
 
 #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)
 
@@ -153,7 +200,8 @@ enum {
 
 #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)
 
@@ -179,7 +227,7 @@ enum {
  * this is used to determine when some branch optimizations are possible: we exclude FP compares
  * because they have weird semantics with NaNs.
  */
-#define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= CEE_BEQ && (ins)->opcode <= CEE_BLT_UN) || ((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_IBEQ && (ins)->opcode <= OP_IBLT_UN))
+#define MONO_IS_COND_BRANCH_OP(ins) (((ins)->opcode >= OP_LBEQ && (ins)->opcode <= OP_LBLT_UN) || ((ins)->opcode >= OP_FBEQ && (ins)->opcode <= OP_FBLT_UN) || ((ins)->opcode >= OP_IBEQ && (ins)->opcode <= OP_IBLT_UN))
 #define MONO_IS_COND_BRANCH_NOFP(ins) (MONO_IS_COND_BRANCH_OP(ins) && !(((ins)->opcode >= OP_FBEQ) && ((ins)->opcode <= OP_FBLT_UN)) && (!(ins)->inst_left || (ins)->inst_left->inst_left->type != STACK_R8))
 
 #define MONO_IS_BRANCH_OP(ins) (MONO_IS_COND_BRANCH_OP(ins) || ((ins)->opcode == OP_BR) || ((ins)->opcode == OP_BR_REG) || ((ins)->opcode == OP_SWITCH))
@@ -188,7 +236,6 @@ enum {
 
 #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))
@@ -203,10 +250,12 @@ enum {
 /* 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))
@@ -216,6 +265,7 @@ enum {
 
 #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*/
@@ -241,11 +291,7 @@ extern guint32 mono_jit_tls_id;
 extern MonoTraceSpec *mono_jit_trace_calls;
 extern gboolean mono_break_on_exc;
 extern int mono_exc_esp_offset;
-#ifdef DISABLE_AOT
-#define mono_compile_aot 0
-#else
 extern gboolean mono_compile_aot;
-#endif
 extern gboolean mono_aot_only;
 extern gboolean mono_use_imt;
 extern MonoMethodDesc *mono_inject_async_exc_method;
@@ -258,10 +304,15 @@ extern gboolean mono_verify_all;
 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)
 
@@ -271,121 +322,6 @@ extern const char ins_info[];
 
 #define mono_bb_first_ins(bb) (bb)->code
 
-#if 0
-
-static inline void
-MONO_INST_LIST_ADD_TAIL (MonoInstList *new, MonoInstList *head)
-{
-       __MONO_INST_LIST_ADD (new, head->prev, head);
-}
-
-static inline void
-__MONO_INST_LIST_DEL (MonoInstList *prev, MonoInstList *next)
-{
-       next->prev = prev;
-       prev->next = next;
-}
-
-static inline void
-__MONO_INST_LIST_SPLICE (MonoInstList *list, MonoInstList *head)
-{
-       MonoInstList *first = list->next;
-       MonoInstList *last = list->prev;
-       MonoInstList *at = head->next;
-
-       first->prev = head;
-       head->next = first;
-
-       last->next = at;
-       at->prev = last;
-}
-
-static inline void
-MONO_INST_LIST_SPLICE (MonoInstList *list, MonoInstList *head) 
-{
-       if (!MONO_INST_LIST_EMPTY (list))
-               __MONO_INST_LIST_SPLICE (list, head);
-}
-
-static inline void
-MONO_INST_LIST_SPLICE_TAIL (MonoInstList *list, MonoInstList *head) 
-{
-       if (!MONO_INST_LIST_EMPTY (list))
-               __MONO_INST_LIST_SPLICE (list, head->prev);
-}
-
-static inline void
-MONO_INST_LIST_SPLICE_INIT (MonoInstList *list, MonoInstList *head)
-{
-       if (!MONO_INST_LIST_EMPTY (list)) {
-               __MONO_INST_LIST_SPLICE (list, head);
-               MONO_INST_LIST_INIT (list);
-       }
-}
-
-static inline void
-MONO_INST_LIST_SPLICE_TAIL_INIT (MonoInstList *list, MonoInstList *head)
-{
-       if (!MONO_INST_LIST_EMPTY (list)) {
-               __MONO_INST_LIST_SPLICE (list, head->prev);
-               MONO_INST_LIST_INIT (list);
-       }
-}
-
-/*#define mono_container_of(ptr, type, member) ({                      \
-       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-       (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#define MONO_INST_LIST_ENTRY(ptr, type, member) \
-       mono_container_of(ptr, type, member)*/
-
-#define MONO_INST_LIST_ENTRY(ptr, type, member)        \
-       ((type *)(gpointer)(ptr))
-
-#define MONO_INST_LIST_FIRST_ENTRY(ptr, type, member) \
-       MONO_INST_LIST_ENTRY((ptr)->next, type, member)
-
-#define MONO_INST_LIST_LAST_ENTRY(ptr, type, member) \
-       MONO_INST_LIST_ENTRY((ptr)->prev, type, member)
-
-#define MONO_INST_LIST_FOR_EACH(pos, head) \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#define MONO_INST_LIST_FOR_EACH_PREV(pos, head) \
-       for (pos = (head)->prev; pos != (head); pos = pos->prev)
-
-#define MONO_INST_LIST_FOR_EACH_SAFE(pos, n, head) \
-       for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, n = pos->next)
-
-#define MONO_INST_LIST_FOR_EACH_PREV_SAFE(pos, n, head) \
-       for (pos = (head)->prev, n = pos->prev; pos != (head); \
-               pos = n, n = pos->prev)
-
-#define MONO_INST_LIST_FOR_EACH_ENTRY(pos, head, member) \
-       for (pos = MONO_INST_LIST_ENTRY ((head)->next, MonoInst, member);\
-            &pos->member != (head);\
-            pos = MONO_INST_LIST_ENTRY (pos->member.next, MonoInst, member))
-
-#define MONO_INST_LIST_FOR_EACH_ENTRY_REVERSE(pos, head, member) \
-       for (pos = MONO_INST_LIST_ENTRY ((head)->prev, MonoInst, member);\
-            &pos->member != (head);\
-            pos = MONO_INST_LIST_ENTRY (pos->member.prev, MonoInst, member))
-
-#define MONO_INST_LIST_FOR_EACH_ENTRY_SAFE(pos, n, head, member) \
-       for (pos = MONO_INST_LIST_ENTRY ((head)->next, MonoInst, member),\
-               n = MONO_INST_LIST_ENTRY (pos->member.next, MonoInst, member);\
-            &pos->member != (head);                                    \
-            pos = n, n = MONO_INST_LIST_ENTRY (n->member.next, MonoInst, member))
-
-#define MONO_BB_FOR_EACH_INS(bb, ins) MONO_INST_LIST_FOR_EACH_ENTRY ((ins), &((bb)->ins_list), node)
-
-#define MONO_BB_FOR_EACH_INS_SAFE(bb, next, ins) MONO_INST_LIST_FOR_EACH_ENTRY_SAFE ((ins), (next), &((bb)->ins_list), node)
-
-#define MONO_BB_FOR_EACH_INS_REVERSE(bb, ins) MONO_INST_LIST_FOR_EACH_ENTRY_REVERSE ((ins), &((bb)->ins_list), node)
-
-#endif
-
 struct MonoEdge {
        MonoEdge *next;
        MonoBasicBlock *bb;
@@ -519,6 +455,30 @@ typedef struct MonoMemcpyArgs {
        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 */
@@ -526,7 +486,7 @@ struct MonoInst {
        guint8  flags  : 5;
        
        /* used by the register allocator */
-       gint32 dreg, sreg1, sreg2;
+       gint32 dreg, sreg1, sreg2, sreg3;
 
        MonoInst *next, *prev;
 
@@ -534,8 +494,14 @@ struct MonoInst {
                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;
@@ -589,10 +555,15 @@ struct MonoCallInst {
        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 {
@@ -630,8 +601,13 @@ enum {
 #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
@@ -660,8 +636,9 @@ enum {
 /* 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
@@ -712,6 +689,13 @@ struct MonoMethodVar {
        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 {
@@ -810,6 +794,9 @@ typedef enum {
        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;
 
@@ -868,6 +855,7 @@ typedef struct {
        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;
@@ -935,14 +923,15 @@ typedef struct {
        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            new_ir : 1;
        guint            globalra : 1;
        guint            unverifiable : 1;
        guint            skip_visibility : 1;
@@ -951,6 +940,8 @@ typedef struct {
        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;
@@ -967,6 +958,8 @@ typedef struct {
        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 */
@@ -1072,13 +1065,18 @@ enum {
 #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
@@ -1110,6 +1108,9 @@ enum {
 #define OP_PMUL OP_IMUL
 #define OP_PMUL_IMM OP_IMUL_IMM
 #define OP_PNEG OP_INEG
+#define OP_PCONV_TO_I1 OP_ICONV_TO_I1
+#define OP_PCONV_TO_U1 OP_ICONV_TO_U1
+#define OP_PCONV_TO_I2 OP_ICONV_TO_I2
 #define OP_PCONV_TO_U2 OP_ICONV_TO_U2
 #define OP_PCONV_TO_OVF_I1_UN OP_ICONV_TO_OVF_I1_UN
 #define OP_PCONV_TO_OVF_I1 OP_ICONV_TO_OVF_I1
@@ -1156,7 +1157,7 @@ extern const char MONO_ARCH_CPU_SPEC [] MONO_INTERNAL;
 #define MONO_ARCH_CPU_SPEC_IDX_COMBINE(a) a ## _idx
 #define MONO_ARCH_CPU_SPEC_IDX(a) MONO_ARCH_CPU_SPEC_IDX_COMBINE(a)
 extern const guint16 MONO_ARCH_CPU_SPEC_IDX(MONO_ARCH_CPU_SPEC) [] MONO_INTERNAL;
-#define ins_get_spec(op) ((const char*)&MONO_ARCH_CPU_SPEC + MONO_ARCH_CPU_SPEC_IDX(MONO_ARCH_CPU_SPEC)[(op)])
+#define ins_get_spec(op) ((const char*)&MONO_ARCH_CPU_SPEC + MONO_ARCH_CPU_SPEC_IDX(MONO_ARCH_CPU_SPEC)[(op) - OP_LOAD])
 
 enum {
        MONO_COMP_DOM = 1,
@@ -1192,6 +1193,7 @@ typedef struct {
        gboolean better_cast_details;
        gboolean mdb_optimizations;
        gboolean no_gdb_backtrace;
+       gboolean suspend_on_sigsegv;
 } MonoDebugOptions;
 
 enum {
@@ -1237,6 +1239,17 @@ 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 */
@@ -1283,16 +1296,14 @@ void      mono_merge_basic_blocks           (MonoCompile *cfg, MonoBasicBlock *b
 void      mono_optimize_branches            (MonoCompile *cfg) MONO_INTERNAL;
 
 void      mono_blockset_print               (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom) MONO_INTERNAL;
-void      mono_print_tree                   (MonoInst *tree) MONO_INTERNAL;
-void      mono_print_tree_nl                (MonoInst *tree) MONO_INTERNAL;
 void      mono_print_ins_index              (int i, MonoInst *ins) MONO_INTERNAL;
 void      mono_print_ins                    (MonoInst *ins) MONO_INTERNAL;
 void      mono_print_bb                     (MonoBasicBlock *bb, const char *msg) MONO_INTERNAL;
 void      mono_print_code                   (MonoCompile *cfg, const char *msg) MONO_INTERNAL;
 void      mono_print_method_from_ip         (void *ip);
 char     *mono_pmip                         (void *ip);
-void      mono_select_instructions          (MonoCompile *cfg) MONO_INTERNAL;
 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;
@@ -1300,7 +1311,6 @@ guint     mono_type_to_load_membase         (MonoCompile *cfg, MonoType *type) M
 guint     mono_type_to_store_membase        (MonoCompile *cfg, MonoType *type) MONO_INTERNAL;
 guint     mini_type_to_stind                (MonoCompile* cfg, MonoType *type) MONO_INTERNAL;
 guint32   mono_reverse_branch_op            (guint32 opcode) MONO_INTERNAL;
-void      mono_inst_foreach                 (MonoInst *tree, MonoInstFunc func, gpointer data) MONO_INTERNAL;
 void      mono_disassemble_code             (MonoCompile *cfg, guint8 *code, int size, char *id) MONO_INTERNAL;
 void      mono_add_patch_info               (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target) MONO_INTERNAL;
 void      mono_remove_patch_info            (MonoCompile *cfg, int ip) MONO_INTERNAL;
@@ -1309,6 +1319,7 @@ guint     mono_patch_info_hash (gconstpointer data) 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;
@@ -1318,6 +1329,8 @@ gint32    mono_get_jit_tls_offset           (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;
@@ -1363,17 +1376,34 @@ gpointer mono_aot_create_specific_trampoline   (MonoImage *image, gpointer arg1,
 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;
+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 (char *name, guint8 *code, guint32 code_len) 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_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;
 
 void      mono_register_opcode_emulation    (int opcode, const char* name, const char *sigstr, gpointer func, gboolean no_throw) MONO_INTERNAL;
 void      mono_draw_graph                   (MonoCompile *cfg, MonoGraphOptions draw_options) MONO_INTERNAL;
-void      mono_add_varcopy_to_end           (MonoCompile *cfg, MonoBasicBlock *bb, int src, int dest) MONO_INTERNAL;
 void      mono_add_ins_to_end               (MonoBasicBlock *bb, MonoInst *inst) MONO_INTERNAL;
 gpointer  mono_create_ftnptr                (MonoDomain *domain, gpointer addr) MONO_INTERNAL;
 
@@ -1401,6 +1431,8 @@ gpointer          mono_create_delegate_trampoline (MonoClass *klass) MONO_INTERN
 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;
@@ -1417,6 +1449,7 @@ void              mono_monitor_enter_trampoline (gssize *regs, guint8 *code, Mon
 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;
@@ -1434,6 +1467,9 @@ CompRelation      mono_negate_cond (CompRelation cond) 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;
@@ -1442,7 +1478,7 @@ int               mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoB
                                                                         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;
@@ -1467,8 +1503,9 @@ gpointer  mono_arch_get_throw_exception         (void) 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;
@@ -1477,6 +1514,7 @@ gpointer  mono_arch_create_monitor_enter_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;
@@ -1506,6 +1544,8 @@ void      mono_arch_emit_setret                 (MonoCompile *cfg, MonoMethod *m
 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, 
@@ -1523,6 +1563,7 @@ gpointer  mono_arch_get_throw_exception_full    (guint32 *code_size, MonoJumpInf
 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;
@@ -1537,13 +1578,13 @@ MonoInst* mono_arch_get_thread_intrinsic        (MonoCompile* cfg) 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;
@@ -1723,10 +1764,62 @@ enum {
 };
 
 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 {