[Debugger] Added support for stepping over await and out of async met…
[mono.git] / mono / mini / mini-llvm.c
index 55bdb27e7912ca542b6b022cab3c259ffcda7b6c..563607f8c0fbeb4b48eba4b4103a1c94729623ff 100644 (file)
@@ -6,7 +6,8 @@
  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
-#include "mini.h"
+#include "config.h"
+
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/debug-mono-symfile.h>
 #include <mono/metadata/mempool-internals.h>
@@ -33,6 +34,8 @@
 #include "aot-compiler.h"
 #include "mini-llvm.h"
 
+#ifndef DISABLE_JIT
+
 #ifdef __MINGW32__
 
 #include <stddef.h>
@@ -148,6 +151,7 @@ typedef struct {
        LLVMValueRef rgctx_arg;
        LLVMValueRef this_arg;
        LLVMTypeRef *vreg_types;
+       gboolean *is_vphi;
        LLVMTypeRef method_type;
        LLVMBasicBlockRef init_bb, inited_bb;
        gboolean *is_dead;
@@ -170,6 +174,7 @@ typedef struct {
        GPtrArray *bblock_list;
        char *method_name;
        GHashTable *jit_callees;
+       LLVMValueRef long_bb_break_var;
 } EmitContext;
 
 typedef struct {
@@ -353,6 +358,36 @@ simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass)
                return LLVMVectorType (LLVMInt8Type (), 16);
        } else if (!strcmp (klass->name, "Vector16b")) {
                return LLVMVectorType (LLVMInt8Type (), 16);
+       } else if (!strcmp (klass->name, "Vector2")) {
+               /* System.Numerics */
+               return LLVMVectorType (LLVMFloatType (), 4);
+       } else if (!strcmp (klass->name, "Vector3")) {
+               return LLVMVectorType (LLVMFloatType (), 4);
+       } else if (!strcmp (klass->name, "Vector4")) {
+               return LLVMVectorType (LLVMFloatType (), 4);
+       } else if (!strcmp (klass->name, "Vector`1")) {
+               MonoType *etype = mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
+               switch (etype->type) {
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+                       return LLVMVectorType (LLVMInt8Type (), 16);
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+                       return LLVMVectorType (LLVMInt16Type (), 8);
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+                       return LLVMVectorType (LLVMInt32Type (), 4);
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       return LLVMVectorType (LLVMInt64Type (), 2);
+               case MONO_TYPE_R4:
+                       return LLVMVectorType (LLVMFloatType (), 4);
+               case MONO_TYPE_R8:
+                       return LLVMVectorType (LLVMDoubleType (), 2);
+               default:
+                       g_assert_not_reached ();
+                       return NULL;
+               }
        } else {
                printf ("%s\n", klass->name);
                NOT_IMPLEMENTED;
@@ -399,6 +434,9 @@ create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass)
                 * This is needed on arm64 where HFAs are returned in
                 * registers.
                 */
+               /* SIMD types have size 16 in mono_class_value_size () */
+               if (klass->simd_type)
+                       nfields = 16/ esize;
                size = nfields;
                eltypes = g_new (LLVMTypeRef, size);
                for (i = 0; i < size; ++i)
@@ -813,14 +851,6 @@ simd_op_to_intrins (int opcode)
                return "llvm.x86.sse2.min.pd";
        case OP_MINPS:
                return "llvm.x86.sse.min.ps";
-       case OP_PMIND_UN:
-               return "llvm.x86.sse41.pminud";
-       case OP_PMINW_UN:
-               return "llvm.x86.sse41.pminuw";
-       case OP_PMINB_UN:
-               return "llvm.x86.sse2.pminu.b";
-       case OP_PMINW:
-               return "llvm.x86.sse2.pmins.w";
        case OP_MAXPD:
                return "llvm.x86.sse2.max.pd";
        case OP_MAXPS:
@@ -833,12 +863,6 @@ simd_op_to_intrins (int opcode)
                return "llvm.x86.sse3.hsub.pd";
        case OP_HSUBPS:
                return "llvm.x86.sse3.hsub.ps";
-       case OP_PMAXD_UN:
-               return "llvm.x86.sse41.pmaxud";
-       case OP_PMAXW_UN:
-               return "llvm.x86.sse41.pmaxuw";
-       case OP_PMAXB_UN:
-               return "llvm.x86.sse2.pmaxu.b";
        case OP_ADDSUBPS:
                return "llvm.x86.sse3.addsub.ps";
        case OP_ADDSUBPD:
@@ -913,10 +937,6 @@ simd_op_to_intrins (int opcode)
                return "llvm.x86.sse2.cvttpd2dq";
        case OP_CVTTPS2DQ:
                return "llvm.x86.sse2.cvttps2dq";
-       case OP_COMPPS:
-               return "llvm.x86.sse.cmp.ps";
-       case OP_COMPPD:
-               return "llvm.x86.sse2.cmp.pd";
        case OP_PACKW:
                return "llvm.x86.sse2.packsswb.128";
        case OP_PACKD:
@@ -929,6 +949,8 @@ simd_op_to_intrins (int opcode)
                return "llvm.x86.sse2.pmulh.w";
        case OP_PMULW_HIGH_UN:
                return "llvm.x86.sse2.pmulhu.w";
+       case OP_DPPS:
+               return "llvm.x86.sse41.dpps";
 #endif
        default:
                g_assert_not_reached ();
@@ -1156,8 +1178,19 @@ static LLVMValueRef
 emit_volatile_load (EmitContext *ctx, int vreg)
 {
        MonoType *t;
+       LLVMValueRef v;
 
-       LLVMValueRef v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
+#ifdef TARGET_ARM64
+       // FIXME: This hack is required because we pass the rgctx in a callee saved
+       // register on arm64 (x15), and llvm might keep the value in that register
+       // even through the register is marked as 'reserved' inside llvm.
+       if (ctx->cfg->rgctx_var && ctx->cfg->rgctx_var->dreg == vreg)
+               v = mono_llvm_build_load (ctx->builder, ctx->addresses [vreg], "", TRUE);
+       else
+               v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
+#else
+       v = LLVMBuildLoad (ctx->builder, ctx->addresses [vreg], "");
+#endif
        t = ctx->vreg_cli_types [vreg];
        if (t && !t->byref) {
                /* 
@@ -1590,18 +1623,17 @@ get_aotconst_typed (EmitContext *ctx, MonoJumpInfoType type, gconstpointer data,
        MonoCompile *cfg;
        guint32 got_offset;
        LLVMValueRef indexes [2];
-       MonoJumpInfo *ji;
        LLVMValueRef got_entry_addr, load;
        LLVMBuilderRef builder = ctx->builder;
        char *name = NULL;
 
        cfg = ctx->cfg;
 
-       ji = g_new0 (MonoJumpInfo, 1);
-       ji->type = type;
-       ji->data.target = data;
+       MonoJumpInfo tmp_ji;
+       tmp_ji.type = type;
+       tmp_ji.data.target = data;
 
-       ji = mono_aot_patch_info_dup (ji);
+       MonoJumpInfo *ji = mono_aot_patch_info_dup (&tmp_ji);
 
        ji->next = cfg->patch_info;
        cfg->patch_info = ji;
@@ -1747,6 +1779,8 @@ get_handler_clause (MonoCompile *cfg, MonoBasicBlock *bb)
 static MonoExceptionClause *
 get_most_deep_clause (MonoCompile *cfg, EmitContext *ctx, MonoBasicBlock *bb)
 {
+       if (bb == cfg->bb_init)
+               return NULL;
        // Since they're sorted by nesting we just need
        // the first one that the bb is a member of
        for (int i = 0; i < cfg->header->num_clauses; i++) {
@@ -1958,15 +1992,18 @@ emit_load_general (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder
                 * LLVM will generate invalid code when encountering a load from a
                 * NULL address.
                 */
-                res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting, barrier);
+               if (barrier != LLVM_BARRIER_NONE)
+                       res = mono_llvm_build_atomic_load (*builder_ref, addr, name, is_faulting, size, barrier);
+               else
+                       res = mono_llvm_build_load (*builder_ref, addr, name, is_faulting);
 
-                /* Mark it with a custom metadata */
-                /*
-                if (is_faulting)
-                        set_metadata_flag (res, "mono.faulting.load");
-                */
+               /* Mark it with a custom metadata */
+               /*
+                 if (is_faulting)
+                 set_metadata_flag (res, "mono.faulting.load");
+               */
 
-                return res;
+               return res;
        }
 }
 
@@ -2420,7 +2457,7 @@ emit_get_method (MonoLLVMModule *module)
        LLVMBasicBlockRef entry_bb, fail_bb, bb, code_start_bb, code_end_bb;
        LLVMBasicBlockRef *bbs;
        LLVMTypeRef rtype;
-       LLVMBuilderRef builder;
+       LLVMBuilderRef builder = LLVMCreateBuilder ();
        char *name;
        int i;
 
@@ -2446,14 +2483,12 @@ emit_get_method (MonoLLVMModule *module)
        name = g_strdup_printf ("BB_CODE_START");
        code_start_bb = LLVMAppendBasicBlock (func, name);
        g_free (name);
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, code_start_bb);
        LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_start, rtype, ""));
 
        name = g_strdup_printf ("BB_CODE_END");
        code_end_bb = LLVMAppendBasicBlock (func, name);
        g_free (name);
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, code_end_bb);
        LLVMBuildRet (builder, LLVMBuildBitCast (builder, module->code_end, rtype, ""));
 
@@ -2464,7 +2499,6 @@ emit_get_method (MonoLLVMModule *module)
                g_free (name);
                bbs [i] = bb;
 
-               builder = LLVMCreateBuilder ();
                LLVMPositionBuilderAtEnd (builder, bb);
 
                m = (LLVMValueRef)g_hash_table_lookup (module->idx_to_lmethod, GINT_TO_POINTER (i));
@@ -2475,11 +2509,9 @@ emit_get_method (MonoLLVMModule *module)
        }
 
        fail_bb = LLVMAppendBasicBlock (func, "FAIL");
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, fail_bb);
        LLVMBuildRet (builder, LLVMConstNull (rtype));
 
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, entry_bb);
 
        switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
@@ -2490,6 +2522,8 @@ emit_get_method (MonoLLVMModule *module)
        }
 
        mark_as_used (module, func);
+
+       LLVMDisposeBuilder (builder);
 }
 
 /*
@@ -2505,7 +2539,7 @@ emit_get_unbox_tramp (MonoLLVMModule *module)
        LLVMBasicBlockRef entry_bb, fail_bb, bb;
        LLVMBasicBlockRef *bbs;
        LLVMTypeRef rtype;
-       LLVMBuilderRef builder;
+       LLVMBuilderRef builder = LLVMCreateBuilder ();
        char *name;
        int i;
 
@@ -2531,18 +2565,15 @@ emit_get_unbox_tramp (MonoLLVMModule *module)
                g_free (name);
                bbs [i] = bb;
 
-               builder = LLVMCreateBuilder ();
                LLVMPositionBuilderAtEnd (builder, bb);
 
                LLVMBuildRet (builder, LLVMBuildBitCast (builder, m, rtype, ""));
        }
 
        fail_bb = LLVMAppendBasicBlock (func, "FAIL");
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, fail_bb);
        LLVMBuildRet (builder, LLVMConstNull (rtype));
 
-       builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, entry_bb);
 
        switch_ins = LLVMBuildSwitch (builder, LLVMGetParam (func, 0), fail_bb, 0);
@@ -2555,6 +2586,7 @@ emit_get_unbox_tramp (MonoLLVMModule *module)
        }
 
        mark_as_used (module, func);
+       LLVMDisposeBuilder (builder);
 }
 
 /* Add a function to mark the beginning of LLVM code */
@@ -2574,6 +2606,7 @@ emit_llvm_code_start (MonoLLVMModule *module)
        builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, entry_bb);
        LLVMBuildRetVoid (builder);
+       LLVMDisposeBuilder (builder);
 }
 
 static LLVMValueRef
@@ -2647,6 +2680,7 @@ emit_init_icall_wrapper (MonoLLVMModule *module, const char *name, const char *i
        LLVMBuildRetVoid (builder);
 
        LLVMVerifyFunction(func, LLVMAbortProcessAction);
+       LLVMDisposeBuilder (builder);
        return func;
 }
 
@@ -2680,6 +2714,7 @@ emit_llvm_code_end (MonoLLVMModule *module)
        builder = LLVMCreateBuilder ();
        LLVMPositionBuilderAtEnd (builder, entry_bb);
        LLVMBuildRetVoid (builder);
+       LLVMDisposeBuilder (builder);
 }
 
 static void
@@ -2870,6 +2905,7 @@ emit_unbox_tramp (EmitContext *ctx, const char *method_name, LLVMTypeRef method_
                LLVMBuildRet (builder, call);
 
        g_hash_table_insert (ctx->module->idx_to_unbox_tramp, GINT_TO_POINTER (method_index), tramp);
+       LLVMDisposeBuilder (builder);
 }
 
 /*
@@ -3364,7 +3400,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                if (!ctx->imt_rgctx_loc)
                        ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
                LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
-               args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE, LLVM_BARRIER_NONE);
+               args [cinfo->rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
 #else
                args [cinfo->rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->module->ptr_type);
 #endif
@@ -3377,7 +3413,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                if (!ctx->imt_rgctx_loc)
                        ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->module->ptr_type, sizeof (gpointer));
                LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->module->ptr_type), ctx->imt_rgctx_loc);
-               args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE, LLVM_BARRIER_NONE);
+               args [cinfo->imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
 #else
                args [cinfo->imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->module->ptr_type);
 #endif
@@ -3489,6 +3525,9 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
 
        lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
 
+       if (ins->opcode != OP_TAILCALL && LLVMGetInstructionOpcode (lcall) == LLVMCall)
+               mono_llvm_set_call_notail (lcall);
+
        /*
         * Modify cconv and parameter attributes to pass rgctx/imt correctly.
         */
@@ -3893,7 +3932,7 @@ emit_landing_pad (EmitContext *ctx, int group_index, int group_size)
                LLVMValueRef switch_ins = LLVMBuildSwitch (lpadBuilder, match, resume_bb, group_size);
 
                // else move to that target bb
-               for (int i=0; i < group_size; i++) {
+               for (int i = 0; i < group_size; i++) {
                        MonoExceptionClause *clause = group_start + i;
                        int clause_index = clause - cfg->header->clauses;
                        MonoBasicBlock *handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->clause_to_handler, GINT_TO_POINTER (clause_index));
@@ -3983,6 +4022,7 @@ emit_handler_start (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef builder
                        LLVMPositionBuilderAtEnd (builder2, entry_bb);
                        LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
                        ctx->module->personality = personality;
+                       LLVMDisposeBuilder (builder2);
                }
 #else
                static gint32 mapping_inited;
@@ -4155,13 +4195,36 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                if (nins > 1000) {
                        /*
                         * Some steps in llc are non-linear in the size of basic blocks, see #5714.
-                        * Start a new bblock. If the llvm optimization passes merge these, we
-                        * can work around that by doing a volatile load + cond branch from
-                        * localloc-ed memory.
+                        * Start a new bblock.
+                        * Prevent the bblocks to be merged by doing a volatile load + cond branch
+                        * from localloc-ed memory.
                         */
-                       //set_failure (ctx, "basic block too long");
+                       if (!cfg->llvm_only)
+                               ;//set_failure (ctx, "basic block too long");
+
+                       if (!ctx->long_bb_break_var) {
+                               ctx->long_bb_break_var = build_alloca_llvm_type_name (ctx, LLVMInt32Type (), 0, "long_bb_break");
+                               mono_llvm_build_store (ctx->alloca_builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
+                       }
+
                        cbb = gen_bb (ctx, "CONT_LONG_BB");
-                       LLVMBuildBr (ctx->builder, cbb);
+                       LLVMBasicBlockRef dummy_bb = gen_bb (ctx, "CONT_LONG_BB_DUMMY");
+
+                       LLVMValueRef load = mono_llvm_build_load (builder, ctx->long_bb_break_var, "", TRUE);
+                       /*
+                        * The long_bb_break_var is initialized to 0 in the prolog, so this branch will always go to 'cbb'
+                        * but llvm doesn't know that, so the branch is not going to be eliminated.
+                        */
+                       LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntEQ, load, LLVMConstInt (LLVMInt32Type (), 0, FALSE), "");
+
+                       LLVMBuildCondBr (builder, cmp, cbb, dummy_bb);
+
+                       /* Emit a dummy false bblock which does nothing but contains a volatile store so it cannot be eliminated */
+                       ctx->builder = builder = create_builder (ctx);
+                       LLVMPositionBuilderAtEnd (builder, dummy_bb);
+                       mono_llvm_build_store (builder, LLVMConstInt (LLVMInt32Type (), 1, FALSE), ctx->long_bb_break_var, TRUE, LLVM_BARRIER_NONE);
+                       LLVMBuildBr (builder, cbb);
+
                        ctx->builder = builder = create_builder (ctx);
                        LLVMPositionBuilderAtEnd (builder, cbb);
                        ctx->bblocks [bb->block_num].end_bblock = cbb;
@@ -5380,6 +5443,17 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
                        break;
                }
+
+/*
+ * See the ARM64 comment in mono/utils/atomic.h for an explanation of why this
+ * hack is necessary (for now).
+ */
+#ifdef TARGET_ARM64
+#define ARM64_ATOMIC_FENCE_FIX mono_llvm_build_fence (builder, LLVM_BARRIER_SEQ)
+#else
+#define ARM64_ATOMIC_FENCE_FIX
+#endif
+
                case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_EXCHANGE_I8: {
                        LLVMValueRef args [2];
@@ -5395,7 +5469,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
                        args [1] = convert (ctx, rhs, t);
 
+                       ARM64_ATOMIC_FENCE_FIX;
                        values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
+                       ARM64_ATOMIC_FENCE_FIX;
                        break;
                }
                case OP_ATOMIC_ADD_I4:
@@ -5412,7 +5488,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
                        args [1] = convert (ctx, rhs, t);
+                       ARM64_ATOMIC_FENCE_FIX;
                        values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
+                       ARM64_ATOMIC_FENCE_FIX;
                        break;
                }
                case OP_ATOMIC_CAS_I4:
@@ -5430,7 +5508,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        args [1] = convert (ctx, values [ins->sreg3], t);
                        /* new value */
                        args [2] = convert (ctx, values [ins->sreg2], t);
+                       ARM64_ATOMIC_FENCE_FIX;
                        val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
+                       ARM64_ATOMIC_FENCE_FIX;
                        /* cmpxchg returns a pair */
                        values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
                        break;
@@ -5449,8 +5529,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_ATOMIC_LOAD_U8:
                case OP_ATOMIC_LOAD_R4:
                case OP_ATOMIC_LOAD_R8: {
-                       //#if LLVM_API_VERSION > 100
-#if 0
+#if LLVM_API_VERSION > 100
                        int size;
                        gboolean sext, zext;
                        LLVMTypeRef t;
@@ -5472,7 +5551,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        addr = convert (ctx, addr, LLVMPointerType (t, 0));
 
+                       ARM64_ATOMIC_FENCE_FIX;
                        values [ins->dreg] = emit_load_general (ctx, bb, &builder, size, addr, lhs, dname, is_volatile, barrier);
+                       ARM64_ATOMIC_FENCE_FIX;
 
                        if (sext)
                                values [ins->dreg] = LLVMBuildSExt (builder, values [ins->dreg], LLVMInt32Type (), dname);
@@ -5501,10 +5582,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        BarrierKind barrier = (BarrierKind) ins->backend.memory_barrier_kind;
                        LLVMValueRef index, addr, value, base;
 
+#if LLVM_API_VERSION < 100
                        if (!cfg->llvm_only) {
                                set_failure (ctx, "atomic mono.store intrinsic");
                                break;
                        }
+#endif
 
                        if (!values [ins->inst_destbasereg]) {
                            set_failure (ctx, "inst_destbasereg");
@@ -5518,7 +5601,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (t, 0)), &index, 1, "");
                        value = convert (ctx, values [ins->sreg1], t);
 
+                       ARM64_ATOMIC_FENCE_FIX;
                        emit_store_general (ctx, bb, &builder, size, value, addr, base, is_volatile, barrier);
+                       ARM64_ATOMIC_FENCE_FIX;
                        break;
                }
                case OP_RELAXED_NOP: {
@@ -5554,35 +5639,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        break;
                }
-               case OP_TLS_GET_REG: {
-#if defined(TARGET_AMD64) && defined(__linux__)
-                       // 257 == FS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
-                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt64Type ()), ptrtype, ""), "");
-#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
-                       /* See emit_tls_get_reg () */
-                       // 256 == GS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
-                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
-#else
-                       set_failure (ctx, "opcode tls-get");
-                       break;
-#endif
-                       break;
-               }
-
-               case OP_TLS_SET_REG: {
-#if defined(TARGET_AMD64) && defined(TARGET_OSX)
-                       /* See emit_tls_get_reg () */
-                       // 256 == GS segment register
-                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
-                       LLVMBuildStore (builder, convert (ctx, lhs, IntPtrType ()), LLVMBuildIntToPtr (builder, convert (ctx, rhs, LLVMInt32Type ()), ptrtype, ""));
-#else
-                       set_failure (ctx, "opcode tls-set-reg");
-                       break;
-#endif
-                       break;
-               }
                case OP_GC_SAFE_POINT: {
                        LLVMValueRef val, cmp, callee;
                        LLVMBasicBlockRef poll_bb, cont_bb;
@@ -5597,7 +5653,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                         *   mono_threads_state_poll ();
                         * FIXME: Use a preserveall wrapper
                         */
-                       val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE, LLVM_BARRIER_NONE);
+                       val = mono_llvm_build_load (builder, convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
                        cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
                        poll_bb = gen_bb (ctx, "POLL_BB");
                        cont_bb = gen_bb (ctx, "CONT_BB");
@@ -5789,18 +5845,30 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        const char *name = (const char*)ins->inst_p0;
                        LLVMValueRef var;
 
-                       if (!ctx->module->objc_selector_to_var)
+                       if (!ctx->module->objc_selector_to_var) {
                                ctx->module->objc_selector_to_var = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+                               LLVMValueRef info_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), 8), "@OBJC_IMAGE_INFO");
+                               int32_t objc_imageinfo [] = { 0, 16 };
+                               LLVMSetInitializer (info_var, mono_llvm_create_constant_data_array ((uint8_t *) &objc_imageinfo, 8));
+                               LLVMSetLinkage (info_var, LLVMPrivateLinkage);
+                               LLVMSetExternallyInitialized (info_var, TRUE);
+                               LLVMSetSection (info_var, "__DATA, __objc_imageinfo,regular,no_dead_strip");
+                               LLVMSetAlignment (info_var, sizeof (mgreg_t));
+                               mark_as_used (ctx->module, info_var);
+                       }
+
                        var = g_hash_table_lookup (ctx->module->objc_selector_to_var, name);
                        if (!var) {
                                LLVMValueRef indexes [16];
 
-                               LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME");
+                               LLVMValueRef name_var = LLVMAddGlobal (ctx->lmodule, LLVMArrayType (LLVMInt8Type (), strlen (name) + 1), "@OBJC_METH_VAR_NAME_");
                                LLVMSetInitializer (name_var, mono_llvm_create_constant_data_array ((const uint8_t*)name, strlen (name) + 1));
                                LLVMSetLinkage (name_var, LLVMPrivateLinkage);
                                LLVMSetSection (name_var, "__TEXT,__objc_methname,cstring_literals");
+                               mark_as_used (ctx->module, name_var);
 
-                               LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES");
+                               LLVMValueRef ref_var = LLVMAddGlobal (ctx->lmodule, LLVMPointerType (LLVMInt8Type (), 0), "@OBJC_SELECTOR_REFERENCES_");
 
                                indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, 0);
                                indexes [1] = LLVMConstInt (LLVMInt32Type (), 0, 0);
@@ -5809,6 +5877,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                LLVMSetExternallyInitialized (ref_var, TRUE);
                                LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
                                LLVMSetAlignment (ref_var, sizeof (mgreg_t));
+                               mark_as_used (ctx->module, ref_var);
 
                                g_hash_table_insert (ctx->module->objc_selector_to_var, g_strdup (name), ref_var);
                                var = ref_var;
@@ -5938,19 +6007,31 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildBitCast (builder, v, rt, "");
                        break;
                }
+               case OP_PMIND_UN:
+               case OP_PMINW_UN:
+               case OP_PMINB_UN: {
+                       LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntULT, lhs, rhs, "");
+                       values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
+                       break;
+               }
+               case OP_PMAXD_UN:
+               case OP_PMAXW_UN:
+               case OP_PMAXB_UN: {
+                       LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntUGT, lhs, rhs, "");
+                       values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
+                       break;
+               }
+               case OP_PMINW: {
+                       LLVMValueRef cmp = LLVMBuildICmp (builder, LLVMIntSLT, lhs, rhs, "");
+                       values [ins->dreg] = LLVMBuildSelect (builder, cmp, lhs, rhs, "");
+                       break;
+               }
                case OP_MINPD:
                case OP_MINPS:
                case OP_MAXPD:
                case OP_MAXPS:
                case OP_ADDSUBPD:
                case OP_ADDSUBPS:
-               case OP_PMIND_UN:
-               case OP_PMINW_UN:
-               case OP_PMINB_UN:
-               case OP_PMINW:
-               case OP_PMAXD_UN:
-               case OP_PMAXW_UN:
-               case OP_PMAXB_UN:
                case OP_HADDPD:
                case OP_HADDPS:
                case OP_HSUBPD:
@@ -6066,14 +6147,42 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildInsertElement (builder, values [ins->sreg1], convert (ctx, values [ins->sreg2], LLVMDoubleType ()), LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE), dname);
                        break;
 
+#if LLVM_API_VERSION > 100
+               case OP_CVTDQ2PD: {
+                       LLVMValueRef indexes [16];
+
+                       indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+                       indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
+                       LLVMValueRef mask = LLVMConstVector (indexes, 2);
+                       LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
+                       values [ins->dreg] = LLVMBuildSIToFP (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
+                       break;
+               }
+               case OP_CVTPS2PD: {
+                       LLVMValueRef indexes [16];
+
+                       indexes [0] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+                       indexes [1] = LLVMConstInt (LLVMInt32Type (), 1, FALSE);
+                       LLVMValueRef mask = LLVMConstVector (indexes, 2);
+                       LLVMValueRef shuffle = LLVMBuildShuffleVector (builder, lhs, LLVMConstNull (LLVMTypeOf (lhs)), mask, "");
+                       values [ins->dreg] = LLVMBuildFPExt (builder, shuffle, LLVMVectorType (LLVMDoubleType (), 2), dname);
+                       break;
+               }
+               case OP_CVTTPS2DQ:
+                       values [ins->dreg] = LLVMBuildFPToSI (builder, lhs, LLVMVectorType (LLVMInt32Type (), 4), dname);
+                       break;
+#endif
+
+#if LLVM_API_VERSION <= 100
                case OP_CVTDQ2PD:
+               case OP_CVTPS2PD:
+               case OP_CVTTPS2DQ:
+#endif
                case OP_CVTDQ2PS:
                case OP_CVTPD2DQ:
                case OP_CVTPS2DQ:
                case OP_CVTPD2PS:
-               case OP_CVTPS2PD:
                case OP_CVTTPD2DQ:
-               case OP_CVTTPS2DQ:
                case OP_EXTRACT_MASK:
                case OP_SQRTPS:
                case OP_SQRTPD:
@@ -6086,19 +6195,46 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), &v, 1, dname);
                        break;
                }
-
                case OP_COMPPS:
                case OP_COMPPD: {
-                       LLVMValueRef args [3];
+                       LLVMRealPredicate op;
 
-                       args [0] = lhs;
-                       args [1] = rhs;
-                       args [2] = LLVMConstInt (LLVMInt8Type (), ins->inst_c0, FALSE);
+                       switch (ins->inst_c0) {
+                       case SIMD_COMP_EQ:
+                               op = LLVMRealOEQ;
+                               break;
+                       case SIMD_COMP_LT:
+                               op = LLVMRealOLT;
+                               break;
+                       case SIMD_COMP_LE:
+                               op = LLVMRealOLE;
+                               break;
+                       case SIMD_COMP_UNORD:
+                               op = LLVMRealUNO;
+                               break;
+                       case SIMD_COMP_NEQ:
+                               op = LLVMRealUNE;
+                               break;
+                       case SIMD_COMP_NLT:
+                               op = LLVMRealUGE;
+                               break;
+                       case SIMD_COMP_NLE:
+                               op = LLVMRealUGT;
+                               break;
+                       case SIMD_COMP_ORD:
+                               op = LLVMRealORD;
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                       }
 
-                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
+                       LLVMValueRef cmp = LLVMBuildFCmp (builder, op, lhs, rhs, "");
+                       if (ins->opcode == OP_COMPPD)
+                               values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt64Type (), 2), ""), LLVMTypeOf (lhs), "");
+                       else
+                               values [ins->dreg] = LLVMBuildBitCast (builder, LLVMBuildSExt (builder, cmp, LLVMVectorType (LLVMInt32Type (), 4), ""), LLVMTypeOf (lhs), "");
                        break;
                }
-
                case OP_ICONV_TO_X:
                        /* This is only used for implementing shifts by non-immediate */
                        values [ins->dreg] = lhs;
@@ -6323,6 +6459,18 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        break;
                }
 
+               case OP_DPPS: {
+                       LLVMValueRef args [3];
+
+                       args [0] = lhs;
+                       args [1] = rhs;
+                       /* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
+                       args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
+
+                       values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
+                       break;
+               }
+
 #endif /* SIMD */
 
                case OP_DUMMY_USE:
@@ -6457,7 +6605,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                /* Convert the value to the type required by phi nodes */
                if (spec [MONO_INST_DEST] != ' ' && !MONO_IS_STORE_MEMBASE (ins) && ctx->vreg_types [ins->dreg]) {
-                       if (!values [ins->dreg])
+                       if (ctx->is_vphi [ins->dreg])
                                /* vtypes */
                                values [ins->dreg] = addresses [ins->dreg];
                        else
@@ -6606,6 +6754,7 @@ free_ctx (EmitContext *ctx)
        g_free (ctx->values);
        g_free (ctx->addresses);
        g_free (ctx->vreg_types);
+       g_free (ctx->is_vphi);
        g_free (ctx->vreg_cli_types);
        g_free (ctx->is_dead);
        g_free (ctx->unreachable);
@@ -6614,6 +6763,14 @@ free_ctx (EmitContext *ctx)
        g_hash_table_destroy (ctx->region_to_handler);
        g_hash_table_destroy (ctx->clause_to_handler);
        g_hash_table_destroy (ctx->jit_callees);
+
+       GHashTableIter iter;
+       g_hash_table_iter_init (&iter, ctx->method_to_callers);
+       while (g_hash_table_iter_next (&iter, NULL, (gpointer)&l))
+               g_slist_free (l);
+
+       g_hash_table_destroy (ctx->method_to_callers);
+
        g_free (ctx->method_name);
        g_ptr_array_free (ctx->bblock_list, TRUE);
 
@@ -6658,6 +6815,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
         */
        ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
        ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
+       ctx->is_vphi = g_new0 (gboolean, cfg->next_vreg);
        ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
        ctx->phi_values = g_ptr_array_sized_new (256);
        /* 
@@ -7006,8 +7164,11 @@ emit_method_inner (EmitContext *ctx)
                                for (i = 0; i < ins->inst_phi_args [0]; i++) {
                                        int sreg1 = ins->inst_phi_args [i + 1];
                                        
-                                       if (sreg1 != -1)
+                                       if (sreg1 != -1) {
+                                               if (ins->opcode == OP_VPHI)
+                                                       ctx->is_vphi [sreg1] = TRUE;
                                                ctx->vreg_types [sreg1] = phi_type;
+                                       }
                                }
                                break;
                                }
@@ -7155,8 +7316,12 @@ emit_method_inner (EmitContext *ctx)
                        LLVMValueRef switch_ins = (LLVMValueRef)l->data;
                        GSList *bb_list = info->call_handler_return_bbs;
 
-                       for (i = 0; i < g_slist_length (bb_list); ++i)
-                               LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)(g_slist_nth (bb_list, i)->data));
+                       GSList *bb_list_iter;
+                       i = 0;
+                       for (bb_list_iter = bb_list; bb_list_iter; bb_list_iter = g_slist_next (bb_list_iter)) {
+                               LLVMAddCase (switch_ins, LLVMConstInt (LLVMInt32Type (), i + 1, FALSE), (LLVMBasicBlockRef)bb_list_iter->data);
+                               i ++;
+                       }
                }
        }
 
@@ -7169,7 +7334,11 @@ emit_method_inner (EmitContext *ctx)
                ctx->module->max_method_idx = MAX (ctx->module->max_method_idx, cfg->method_index);
 
                // FIXME: beforefieldinit
-               if (ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) {
+               /*
+                * NATIVE_TO_MANAGED methods might be called on a thread not attached to the runtime, so they are initialized when loaded
+                * in load_method ().
+                */
+               if ((ctx->has_got_access || mono_class_get_cctor (cfg->method->klass)) && !(cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)) {
                        /*
                         * linkonce methods shouldn't have initialization,
                         * because they might belong to assemblies which
@@ -7710,11 +7879,6 @@ typedef enum {
        INTRINS_SSE_HADDPD,
        INTRINS_SSE_HSUBPD,
        INTRINS_SSE_ADDSUBPD,
-       INTRINS_SSE_PMINUD,
-       INTRINS_SSE_PMAXUD,
-       INTRINS_SSE_PMINUW,
-       INTRINS_SSE_PMINSW,
-       INTRINS_SSE_PMAXUW,
        INTRINS_SSE_PADDSW,
        INTRINS_SSE_PSUBSW,
        INTRINS_SSE_PADDUSW,
@@ -7722,14 +7886,13 @@ typedef enum {
        INTRINS_SSE_PAVGW,
        INTRINS_SSE_PMULHW,
        INTRINS_SSE_PMULHU,
-       INTRINS_SSE_PMINUB,
-       INTRINS_SSE_PMAXUB,
        INTRINS_SE_PADDSB,
        INTRINS_SSE_PSUBSB,
        INTRINS_SSE_PADDUSB,
        INTRINS_SSE_PSUBUSB,
        INTRINS_SSE_PAVGB,
        INTRINS_SSE_PAUSE,
+       INTRINS_SSE_DPPS,
 #endif
        INTRINS_NUM
 } IntrinsicId;
@@ -7799,11 +7962,6 @@ static IntrinsicDesc intrinsics[] = {
        {INTRINS_SSE_HADDPD, "llvm.x86.sse3.hadd.pd"},
        {INTRINS_SSE_HSUBPD, "llvm.x86.sse3.hsub.pd"},
        {INTRINS_SSE_ADDSUBPD, "llvm.x86.sse3.addsub.pd"},
-       {INTRINS_SSE_PMINUD, "llvm.x86.sse41.pminud"},
-       {INTRINS_SSE_PMAXUD, "llvm.x86.sse41.pmaxud"},
-       {INTRINS_SSE_PMINUW, "llvm.x86.sse41.pminuw"},
-       {INTRINS_SSE_PMINSW, "llvm.x86.sse2.pmins.w"},
-       {INTRINS_SSE_PMAXUW, "llvm.x86.sse41.pmaxuw"},
        {INTRINS_SSE_PADDSW, "llvm.x86.sse2.padds.w"},
        {INTRINS_SSE_PSUBSW, "llvm.x86.sse2.psubs.w"},
        {INTRINS_SSE_PADDUSW, "llvm.x86.sse2.paddus.w"},
@@ -7811,14 +7969,13 @@ static IntrinsicDesc intrinsics[] = {
        {INTRINS_SSE_PAVGW, "llvm.x86.sse2.pavg.w"},
        {INTRINS_SSE_PMULHW, "llvm.x86.sse2.pmulh.w"},
        {INTRINS_SSE_PMULHU, "llvm.x86.sse2.pmulhu.w"},
-       {INTRINS_SSE_PMINUB, "llvm.x86.sse2.pminu.b"},
-       {INTRINS_SSE_PMAXUB, "llvm.x86.sse2.pmaxu.b"},
        {INTRINS_SE_PADDSB, "llvm.x86.sse2.padds.b"},
        {INTRINS_SSE_PSUBSB, "llvm.x86.sse2.psubs.b"},
        {INTRINS_SSE_PADDUSB, "llvm.x86.sse2.paddus.b"},
        {INTRINS_SSE_PSUBUSB, "llvm.x86.sse2.psubus.b"},
        {INTRINS_SSE_PAVGB, "llvm.x86.sse2.pavg.b"},
-       {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"}
+       {INTRINS_SSE_PAUSE, "llvm.x86.sse2.pause"},
+       {INTRINS_SSE_DPPS, "llvm.x86.sse41.dpps"}
 #endif
 };
 
@@ -8018,13 +8175,6 @@ add_intrinsic (LLVMModuleRef module, int id)
                AddFunc (module, name, ret_type, arg_types, 2);
                break;
                /* SSE Binary ops */
-       case INTRINS_SSE_PMINUD:
-       case INTRINS_SSE_PMAXUD:
-               add_sse_binary (module, name, MONO_TYPE_I4);
-               break;
-       case INTRINS_SSE_PMINUW:
-       case INTRINS_SSE_PMINSW:
-       case INTRINS_SSE_PMAXUW:
        case INTRINS_SSE_PADDSW:
        case INTRINS_SSE_PSUBSW:
        case INTRINS_SSE_PADDUSW:
@@ -8048,8 +8198,6 @@ add_intrinsic (LLVMModuleRef module, int id)
        case INTRINS_SSE_ADDSUBPD:
                add_sse_binary (module, name, MONO_TYPE_R8);
                break;
-       case INTRINS_SSE_PMINUB:
-       case INTRINS_SSE_PMAXUB:
        case INTRINS_SE_PADDSB:
        case INTRINS_SSE_PSUBSB:
        case INTRINS_SSE_PADDUSB:
@@ -8060,6 +8208,13 @@ add_intrinsic (LLVMModuleRef module, int id)
        case INTRINS_SSE_PAUSE:
                AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
                break;
+       case INTRINS_SSE_DPPS:
+               ret_type = type_to_simd_type (MONO_TYPE_R4);
+               arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
+               arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
+               arg_types [2] = LLVMInt32Type ();
+               AddFunc (module, name, ret_type, arg_types, 3);
+               break;
 #endif
        default:
                g_assert_not_reached ();
@@ -8122,11 +8277,6 @@ add_intrinsics (LLVMModuleRef module)
                AddFunc (module, "llvm_resume_unwind_trampoline", LLVMVoidType (), NULL, 0);
        }
 
-       /* SSE intrinsics */
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
-
-#endif
-
        /* Load/Store intrinsics */
        {
                LLVMTypeRef arg_types [5];
@@ -8288,16 +8438,12 @@ mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix,
        module->llvm_only = llvm_only;
        /* The first few entries are reserved */
        module->max_got_offset = 16;
-       module->context = LLVMContextCreate ();
+       module->context = LLVMGetGlobalContext ();
 
        if (llvm_only)
                /* clang ignores our debug info because it has an invalid version */
                module->emit_dwarf = FALSE;
 
-#if LLVM_API_VERSION > 100
-       module->emit_dwarf = FALSE;
-#endif
-
        add_intrinsics (module->lmodule);
        add_types (module);
 
@@ -8385,6 +8531,19 @@ llvm_array_from_uints (LLVMTypeRef el_type, guint32 *values, int nvalues)
        return res;
 }
 
+static LLVMValueRef
+llvm_array_from_bytes (guint8 *values, int nvalues)
+{
+       int i;
+       LLVMValueRef res, *vals;
+
+       vals = g_new0 (LLVMValueRef, nvalues);
+       for (i = 0; i < nvalues; ++i)
+               vals [i] = LLVMConstInt (LLVMInt8Type (), values [i], FALSE);
+       res = LLVMConstArray (LLVMInt8Type (), vals, nvalues);
+       g_free (vals);
+       return res;
+}
 /*
  * mono_llvm_emit_aot_file_info:
  *
@@ -8448,7 +8607,7 @@ emit_aot_file_info (MonoLLVMModule *module)
        info = &module->aot_info;
 
        /* Create an LLVM type to represent MonoAotFileInfo */
-       nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 15 + 5;
+       nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 16 + 5;
        eltypes = g_new (LLVMTypeRef, nfields);
        tindex = 0;
        eltypes [tindex ++] = LLVMInt32Type ();
@@ -8463,6 +8622,7 @@ emit_aot_file_info (MonoLLVMModule *module)
        eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
        for (i = 0; i < 4; ++i)
                eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TRAMP_NUM);
+       eltypes [tindex ++] = LLVMArrayType (LLVMInt8Type (), 16);
        g_assert (tindex == nfields);
        file_info_type = LLVMStructCreateNamed (module->context, "MonoAotFileInfo");
        LLVMStructSetBody (file_info_type, eltypes, nfields, FALSE);
@@ -8531,7 +8691,7 @@ emit_aot_file_info (MonoLLVMModule *module)
        if (info->trampoline_size [0]) {
                fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
                fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
-               fields [tindex ++] = AddJitGlobal (module, eltype, "imt_thunks");
+               fields [tindex ++] = AddJitGlobal (module, eltype, "imt_trampolines");
                fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
        } else {
                fields [tindex ++] = LLVMConstNull (eltype);
@@ -8585,6 +8745,8 @@ emit_aot_file_info (MonoLLVMModule *module)
        fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_got_offset_base, MONO_AOT_TRAMP_NUM);
        fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->trampoline_size, MONO_AOT_TRAMP_NUM);
        fields [tindex ++] = llvm_array_from_uints (LLVMInt32Type (), info->tramp_page_code_offsets, MONO_AOT_TRAMP_NUM);
+
+       fields [tindex ++] = llvm_array_from_bytes (info->aotid, 16);
        g_assert (tindex == nfields);
 
        LLVMSetInitializer (info_var, LLVMConstNamedStruct (file_info_type, fields, nfields));
@@ -8676,6 +8838,9 @@ mono_llvm_emit_aot_module (const char *filename, const char *cu_name)
                while (g_hash_table_iter_next (&iter, (void**)&method, (void**)&callers)) {
                        LLVMValueRef lmethod;
 
+                       if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
+                               continue;
+
                        lmethod = (LLVMValueRef)g_hash_table_lookup (module->method_to_lmethod, method);
                        if (lmethod) {
                                for (l = callers; l; l = l->next) {
@@ -8856,7 +9021,7 @@ emit_dbg_subprogram (EmitContext *ctx, MonoCompile *cfg, LLVMValueRef method, co
        filename = g_path_get_basename (source_file);
 
 #if LLVM_API_VERSION > 100
-       return mono_llvm_di_create_function (module->di_builder, module->cu, cfg->method->name, name, dir, filename, n_seq_points ? sym_seq_points [0].line : 1);
+       return mono_llvm_di_create_function (module->di_builder, module->cu, method, cfg->method->name, name, dir, filename, n_seq_points ? sym_seq_points [0].line : 1);
 #endif
 
        ctx_args [0] = LLVMConstInt (LLVMInt32Type (), 0x29, FALSE);
@@ -8975,7 +9140,8 @@ default_mono_llvm_unhandled_exception (void)
        MonoObject *target = mono_gchandle_get_target (jit_tls->thrown_exc);
 
        mono_unhandled_exception (target);
-       exit (mono_environment_exitcode_get ());
+       mono_invoke_unhandled_exception_hook (target);
+       g_assert_not_reached ();
 }
 
 /*
@@ -9080,3 +9246,27 @@ default_mono_llvm_unhandled_exception (void)
  *   code.
  * - use pointer types to help optimizations.
  */
+
+#else /* DISABLE_JIT */
+
+void
+mono_llvm_cleanup (void)
+{
+}
+
+void
+mono_llvm_free_domain_info (MonoDomain *domain)
+{
+}
+
+void
+mono_llvm_init (void)
+{
+}
+
+void
+default_mono_llvm_unhandled_exception (void)
+{
+}
+
+#endif /* DISABLE_JIT */