[llvm] Fix type mismatches in the implementation of the atomic opcodes.
[mono.git] / mono / mini / mini-llvm.c
index dcf1e95d0a07b0273ca07e2537346cb2fdbb3aca..f85a2ec355e308d6e4546fb58107341147118f97 100644 (file)
@@ -205,6 +205,12 @@ IntPtrType (void)
        return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
 }
 
+static LLVMTypeRef
+ObjRefType (void)
+{
+       return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
+}
+
 /*
  * get_vtype_size:
  *
@@ -217,7 +223,7 @@ get_vtype_size (MonoType *t)
 
        size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
 
-       while (size < sizeof (gpointer) && mono_is_power_of_two (size) == -1)
+       while (size < 2 * sizeof (gpointer) && mono_is_power_of_two (size) == -1)
                size ++;
 
        return size;
@@ -326,14 +332,14 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
-               return IntPtrType ();
+               return ObjRefType ();
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* Because of generic sharing */
-               return IntPtrType ();
+               return ObjRefType ();
        case MONO_TYPE_GENERICINST:
                if (!mono_type_generic_inst_is_valuetype (t))
-                       return IntPtrType ();
+                       return ObjRefType ();
                /* Fall through */
        case MONO_TYPE_VALUETYPE:
        case MONO_TYPE_TYPEDBYREF: {
@@ -641,7 +647,7 @@ static const char*
 simd_op_to_intrins (int opcode)
 {
        switch (opcode) {
-#ifdef MONO_ARCH_SIMD_INTRINSICS
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
        case OP_MINPD:
                return "llvm.x86.sse2.min.pd";
        case OP_MINPS:
@@ -772,7 +778,7 @@ simd_op_to_intrins (int opcode)
 static LLVMTypeRef
 simd_op_to_llvm_type (int opcode)
 {
-#ifdef MONO_ARCH_SIMD_INTRINSICS
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
        switch (opcode) {
        case OP_EXTRACT_R8:
        case OP_EXPAND_R8:
@@ -934,12 +940,12 @@ convert_full (EmitContext *ctx, LLVMValueRef v, LLVMTypeRef dtype, gboolean is_u
                if (LLVMGetTypeKind (stype) == LLVMPointerTypeKind)
                        return LLVMBuildPtrToInt (ctx->builder, v, dtype, "");
 
-#ifdef MONO_ARCH_SOFT_FLOAT
-               if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
-                       return LLVMBuildBitCast (ctx->builder, v, dtype, "");
-               if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
-                       return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
-#endif
+               if (mono_arch_is_soft_float ()) {
+                       if (stype == LLVMInt32Type () && dtype == LLVMFloatType ())
+                               return LLVMBuildBitCast (ctx->builder, v, dtype, "");
+                       if (stype == LLVMInt32Type () && dtype == LLVMDoubleType ())
+                               return LLVMBuildBitCast (ctx->builder, LLVMBuildZExt (ctx->builder, v, LLVMInt64Type (), ""), dtype, "");
+               }
 
                if (LLVMGetTypeKind (stype) == LLVMVectorTypeKind && LLVMGetTypeKind (dtype) == LLVMVectorTypeKind)
                        return LLVMBuildBitCast (ctx->builder, v, dtype, "");
@@ -1044,7 +1050,7 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                } else {
                        g_assert_not_reached ();
                }
-       } else if (cinfo && MONO_TYPE_ISSTRUCT (sig->ret)) {
+       } else if (cinfo && mini_type_is_vtype (ctx->cfg, sig->ret)) {
                g_assert (cinfo->ret.storage == LLVMArgVtypeRetAddr);
                vretaddr = TRUE;
                ret_type = LLVMVoidType ();
@@ -1274,12 +1280,26 @@ set_metadata_flag (LLVMValueRef v, const char *flag_name)
 {
        LLVMValueRef md_arg;
        int md_kind;
-       
+
        md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
        md_arg = LLVMMDString ("mono", 4);
        LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
 }
 
+static void
+set_invariant_load_flag (LLVMValueRef v)
+{
+       LLVMValueRef md_arg;
+       int md_kind;
+       const char *flag_name;
+
+       // FIXME: Cache this
+       flag_name = "invariant.load";
+       md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
+       md_arg = LLVMMDString ("<index>", strlen ("<index>"));
+       LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
+}
+
 /*
  * emit_call:
  *
@@ -1680,7 +1700,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
                MonoInst *var = cfg->varinfo [i];
                LLVMTypeRef vtype;
 
-               if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || MONO_TYPE_ISSTRUCT (var->inst_vtype)) {
+               if (var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || mini_type_is_vtype (cfg, var->inst_vtype)) {
                        vtype = type_to_llvm_type (ctx, var->inst_vtype);
                        CHECK_FAILURE (ctx);
                        /* Could be already created by an OP_VPHI */
@@ -1733,7 +1753,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder)
        if (sig->hasthis)
                emit_volatile_store (ctx, cfg->args [0]->dreg);
        for (i = 0; i < sig->param_count; ++i)
-               if (!MONO_TYPE_ISSTRUCT (sig->params [i]))
+               if (!mini_type_is_vtype (cfg, sig->params [i]))
                        emit_volatile_store (ctx, cfg->args [i + sig->hasthis]->dreg);
 
        if (sig->hasthis && !cfg->rgctx_var && cfg->generic_sharing_context) {
@@ -1821,7 +1841,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        LLVMValueRef *args;
        LLVMCallInfo *cinfo;
        GSList *l;
-       int i, len;
+       int i, len, nargs;
        gboolean vretaddr;
        LLVMTypeRef llvm_sig;
        gpointer target;
@@ -1865,6 +1885,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                                LLVMAddGlobalMapping (ee, callee, target);
                        }
                }
+
+               if (call->method && strstr (call->method->klass->name, "AsyncVoidMethodBuilder"))
+                       /* LLVM miscompiles async methods */
+                       LLVM_FAILURE (ctx, "#13734");
        } else if (calli) {
        } else {
                MonoJitICallInfo *info = mono_find_jit_icall_by_addr (call->fptr);
@@ -1943,23 +1967,27 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        /* 
         * Collect and convert arguments
         */
-       len = sizeof (LLVMValueRef) * ((sig->param_count * 2) + sig->hasthis + vretaddr + call->rgctx_reg);
+       nargs = (sig->param_count * 2) + sig->hasthis + vretaddr + call->rgctx_reg + call->imt_arg_reg;
+       len = sizeof (LLVMValueRef) * nargs;
        args = alloca (len);
        memset (args, 0, len);
        l = call->out_ireg_args;
 
        if (call->rgctx_arg_reg) {
                g_assert (values [call->rgctx_arg_reg]);
+               g_assert (sinfo.rgctx_arg_pindex < nargs);
                args [sinfo.rgctx_arg_pindex] = values [call->rgctx_arg_reg];
        }
        if (call->imt_arg_reg) {
                g_assert (values [call->imt_arg_reg]);
+               g_assert (sinfo.imt_arg_pindex < nargs);
                args [sinfo.imt_arg_pindex] = values [call->imt_arg_reg];
        }
 
        if (vretaddr) {
                if (!addresses [call->inst.dreg])
                        addresses [call->inst.dreg] = build_alloca (ctx, sig->ret);
+               g_assert (sinfo.vret_arg_pindex < nargs);
                args [sinfo.vret_arg_pindex] = LLVMBuildPtrToInt (builder, addresses [call->inst.dreg], IntPtrType (), "");
        }
 
@@ -2017,7 +2045,6 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
 
        lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
 
-#ifdef LLVM_MONO_BRANCH
        /*
         * Modify cconv and parameter attributes to pass rgctx/imt correctly.
         */
@@ -2033,7 +2060,6 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                LLVMAddInstrAttribute (lcall, 1 + sinfo.rgctx_arg_pindex, LLVMInRegAttribute);
        if (call->imt_arg_reg)
                LLVMAddInstrAttribute (lcall, 1 + sinfo.imt_arg_pindex, LLVMInRegAttribute);
-#endif
 
        /* Add byval attributes if needed */
        for (i = 0; i < sig->param_count; ++i) {
@@ -2150,14 +2176,20 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        type_info = LLVMAddGlobal (module, LLVMInt32Type (), ti_name);
                        LLVMSetInitializer (type_info, LLVMConstInt (LLVMInt32Type (), clause_index, FALSE));
 
-                       LLVMSetLinkage (type_info, LLVMPrivateLinkage);
-                       LLVMSetVisibility (type_info, LLVMHiddenVisibility);
+                       /*
+                        * These symbols are not really used, the clause_index is embedded into the EH tables generated by DwarfMonoException in LLVM.
+                        */
+                       LLVMSetLinkage (type_info, LLVMInternalLinkage);
 
                        /* 
                         * Enabling this causes llc to crash:
                         * http://llvm.org/bugs/show_bug.cgi?id=6102
                         */
                        //LLVM_FAILURE (ctx, "aot+clauses");
+#ifdef TARGET_ARM
+                       // test_0_invalid_unbox_arrays () fails
+                       LLVM_FAILURE (ctx, "aot+clauses");
+#endif
                } else {
                        /*
                         * After the cfg mempool is freed, the type info will point to stale memory,
@@ -2671,7 +2703,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_AND_IMM:
                case OP_MUL_IMM:
                case OP_SHL_IMM:
-               case OP_SHR_IMM: {
+               case OP_SHR_IMM:
+               case OP_SHR_UN_IMM: {
                        LLVMValueRef imm;
 
                        if (spec [MONO_INST_SRC1] == 'l') {
@@ -2747,6 +2780,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
                                break;
                        case OP_LSHR_UN_IMM:
+                       case OP_SHR_UN_IMM:
                                values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
                                break;
                        default:
@@ -2858,10 +2892,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildFPExt (builder, v, LLVMDoubleType (), dname);
                        break;
                case OP_SEXT_I4:
-                       values [ins->dreg] = LLVMBuildSExt (builder, lhs, LLVMInt64Type (), dname);
+                       values [ins->dreg] = LLVMBuildSExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
                        break;
                case OP_ZEXT_I4:
-                       values [ins->dreg] = LLVMBuildZExt (builder, lhs, LLVMInt64Type (), dname);
+                       values [ins->dreg] = LLVMBuildZExt (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMInt64Type (), dname);
                        break;
                case OP_TRUNC_I4:
                        values [ins->dreg] = LLVMBuildTrunc (builder, lhs, LLVMInt32Type (), dname);
@@ -2958,12 +2992,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 
                        values [ins->dreg] = emit_load (ctx, bb, &builder, size, addr, dname, is_volatile);
 
-                       if (!is_volatile && (ins->flags & MONO_INST_CONSTANT_LOAD)) {
+                       if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
                                /*
                                 * These will signal LLVM that these loads do not alias any stores, and
                                 * they can't fail, allowing them to be hoisted out of loops.
                                 */
-                               set_metadata_flag (values [ins->dreg], "mono.noalias");
+                               set_invariant_load_flag (values [ins->dreg]);
                                set_metadata_flag (values [ins->dreg], "mono.nofail.load");
                        }
 
@@ -3081,23 +3115,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
                        got_entry_addr = LLVMBuildGEP (builder, ctx->lmodule->got_var, indexes, 2, "");
 
-                       // FIXME: This doesn't work right now, because it must be
-                       // paired with an invariant.end, and even then, its only in effect
-                       // inside its basic block
-#if 0
-                       {
-                               LLVMValueRef args [3];
-                               LLVMValueRef ptr, val;
-
-                               ptr = LLVMBuildBitCast (builder, got_entry_addr, LLVMPointerType (LLVMInt8Type (), 0), "ptr");
-
-                               args [0] = LLVMConstInt (LLVMInt64Type (), sizeof (gpointer), FALSE);
-                               args [1] = ptr;
-                               val = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.invariant.start"), args, 2, "");
-                       }
-#endif
-
                        values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, dname);
+                       set_invariant_load_flag (values [ins->dreg]);
                        break;
                }
                case OP_NOT_REACHED:
@@ -3196,44 +3215,38 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
                        break;
                }
-               case OP_ATOMIC_EXCHANGE_I4: {
-                       LLVMValueRef args [2];
-
-                       g_assert (ins->inst_offset == 0);
-
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
-                       args [1] = rhs;
-
-                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
-                       break;
-               }
+               case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_EXCHANGE_I8: {
                        LLVMValueRef args [2];
+                       LLVMTypeRef t;
+                               
+                       if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
+                               t = LLVMInt32Type ();
+                       else
+                               t = LLVMInt64Type ();
 
                        g_assert (ins->inst_offset == 0);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
-                       args [1] = convert (ctx, rhs, LLVMInt64Type ());
-                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
-                       break;
-               }
-               case OP_ATOMIC_ADD_NEW_I4: {
-                       LLVMValueRef args [2];
-
-                       g_assert (ins->inst_offset == 0);
+                       args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+                       args [1] = convert (ctx, rhs, t);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
-                       args [1] = rhs;
-                       values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
+                       values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
                        break;
                }
+               case OP_ATOMIC_ADD_NEW_I4:
                case OP_ATOMIC_ADD_NEW_I8: {
                        LLVMValueRef args [2];
+                       LLVMTypeRef t;
+                               
+                       if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+                               t = LLVMInt32Type ();
+                       else
+                               t = LLVMInt64Type ();
 
                        g_assert (ins->inst_offset == 0);
 
-                       args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
-                       args [1] = convert (ctx, rhs, LLVMInt64Type ());
+                       args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+                       args [1] = convert (ctx, rhs, t);
                        values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
                        break;
                }
@@ -3242,11 +3255,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        LLVMValueRef args [3];
                        LLVMTypeRef t;
                                
-                       if (ins->opcode == OP_ATOMIC_CAS_I4) {
+                       if (ins->opcode == OP_ATOMIC_CAS_I4)
                                t = LLVMInt32Type ();
-                       } else {
+                       else
                                t = LLVMInt64Type ();
-                       }
 
                        args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
                        /* comparand */
@@ -3277,9 +3289,15 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        // 256 == GS segment register
                        LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
 #endif
-
                        // FIXME: XEN
                        values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
+#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
+                       /* See mono_amd64_emit_tls_get () */
+                       int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
+
+                       // 256 == GS segment register
+                       LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+                       values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
 #else
                        LLVM_FAILURE (ctx, "opcode tls-get");
 #endif
@@ -3362,6 +3380,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                break;
                        }
 
+                       if (mini_is_gsharedvt_klass (cfg, klass)) {
+                               // FIXME:
+                               LLVM_FAILURE (ctx, "gsharedvt");
+                               break;
+                       }
+
                        switch (ins->opcode) {
                        case OP_STOREV_MEMBASE:
                                if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg) {
@@ -3424,7 +3448,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        /* 
                         * SIMD
                         */
-#ifdef MONO_ARCH_SIMD_INTRINSICS
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
                case OP_XZERO: {
                        values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, &ins->klass->byval_arg));
                        break;
@@ -3979,7 +4003,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                else
                                        ctx->lmodule->throw = callee;
                        }
-                       arg = convert (ctx, values [ins->sreg1], type_to_llvm_type (ctx, &mono_get_object_class ()->byval_arg));
+                       arg = convert (ctx, lhs, type_to_llvm_type (ctx, &mono_get_object_class ()->byval_arg));
                        emit_call (ctx, bb, &builder, callee, &arg, 1);
                        break;
                }
@@ -4108,18 +4132,16 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
 void
 mono_llvm_check_method_supported (MonoCompile *cfg)
 {
-       /*
        MonoMethodHeader *header = cfg->header;
        MonoExceptionClause *clause;
        int i;
-       */
 
        if (cfg->method->save_lmf) {
                cfg->exception_message = g_strdup ("lmf");
                cfg->disable_llvm = TRUE;
        }
 
-#if 0
+#if 1
        for (i = 0; i < header->num_clauses; ++i) {
                clause = &header->clauses [i];
                
@@ -4215,18 +4237,21 @@ mono_llvm_emit_method (MonoCompile *cfg)
        
        module = ctx->module = ctx->lmodule->module;
 
+       if (cfg->gsharedvt)
+               LLVM_FAILURE (ctx, "gsharedvt");
+
 #if 1
        {
                static int count = 0;
                count ++;
 
-               if (getenv ("LLVM_COUNT")) {
-                       if (count == atoi (getenv ("LLVM_COUNT"))) {
+               if (g_getenv ("LLVM_COUNT")) {
+                       if (count == atoi (g_getenv ("LLVM_COUNT"))) {
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
                                fflush (stdout);
                                last = TRUE;
                        }
-                       if (count > atoi (getenv ("LLVM_COUNT")))
+                       if (count > atoi (g_getenv ("LLVM_COUNT")))
                                LLVM_FAILURE (ctx, "");
                }
        }
@@ -4253,9 +4278,7 @@ mono_llvm_emit_method (MonoCompile *cfg)
        method = LLVMAddFunction (module, method_name, method_type);
        ctx->lmethod = method;
 
-#ifdef LLVM_MONO_BRANCH
        LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
-#endif
        LLVMSetLinkage (method, LLVMPrivateLinkage);
 
        LLVMAddFunctionAttr (method, LLVMUWTable);
@@ -4490,6 +4513,19 @@ mono_llvm_emit_method (MonoCompile *cfg)
 
        mark_as_used (module, method);
 
+       if (cfg->compile_aot) {
+               LLVMValueRef md_args [16];
+               LLVMValueRef md_node;
+               int method_index;
+
+               method_index = mono_aot_get_method_index (cfg->orig_method);
+               md_args [0] = LLVMMDString (method_name, strlen (method_name));
+               md_args [1] = LLVMConstInt (LLVMInt32Type (), method_index, FALSE);
+               md_node = LLVMMDNode (md_args, 2);
+               LLVMAddNamedMetadataOperand (module, "mono.function_indexes", md_node);
+               //LLVMSetMetadata (method, md_kind, LLVMMDNode (&md_arg, 1));
+       }
+
        if (cfg->compile_aot) {
                /* Don't generate native code, keep the LLVM IR */
                if (cfg->compile_aot && cfg->verbose_level)
@@ -4740,11 +4776,21 @@ static char*
 dlsym_cb (const char *name, void **symbol)
 {
        MonoDl *current;
+       char *err;
 
-       current = mono_dl_open (NULL, 0, NULL);
-       g_assert (current);
+       err = NULL;
+       if (!strcmp (name, "__bzero")) {
+               *symbol = (void*)bzero;
+       } else {
+               current = mono_dl_open (NULL, 0, NULL);
+               g_assert (current);
 
-       return mono_dl_symbol (current, name, symbol);
+               err = mono_dl_symbol (current, name, symbol);
+       }
+#ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
+       *symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
+#endif
+       return err;
 }
 
 static inline void
@@ -4825,16 +4871,6 @@ add_intrinsics (LLVMModuleRef module)
                LLVMAddFunction (module, "llvm.umul.with.overflow.i64", LLVMFunctionType (LLVMStructType (ovf_res_i64, 2, FALSE), ovf_params_i64, 2, FALSE));
        }
 
-       {
-               LLVMTypeRef struct_ptr = LLVMPointerType (LLVMStructType (NULL, 0, FALSE), 0);
-               LLVMTypeRef invariant_start_params [] = { LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
-               LLVMTypeRef invariant_end_params [] = { struct_ptr, LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
-
-               LLVMAddFunction (module, "llvm.invariant.start", LLVMFunctionType (struct_ptr, invariant_start_params, 2, FALSE));
-
-               LLVMAddFunction (module, "llvm.invariant.end", LLVMFunctionType (LLVMVoidType (), invariant_end_params, 3, FALSE));
-       }
-
        /* EH intrinsics */
        {
                LLVMTypeRef arg_types [2];
@@ -5108,7 +5144,7 @@ mono_llvm_create_aot_module (const char *got_symbol)
                LLVMValueRef personality;
 
                personality = LLVMAddFunction (aot_module.module, "mono_aot_personality", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
-               LLVMSetLinkage (personality, LLVMPrivateLinkage);
+               LLVMSetLinkage (personality, LLVMInternalLinkage);
                lbb = LLVMAppendBasicBlock (personality, "BB0");
                lbuilder = LLVMCreateBuilder ();
                LLVMPositionBuilderAtEnd (lbuilder, lbb);