Merge pull request #601 from knocte/sock_improvements
[mono.git] / mono / mini / mini-llvm.c
index af2a00d9dbd42dc4ad6caf127d61ed2eec224667..fd822480af158b26346703d6b756b6642d8b67a9 100644 (file)
@@ -9,6 +9,7 @@
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/mempool-internals.h>
 #include <mono/utils/mono-tls.h>
+#include <mono/utils/mono-dl.h>
 
 #ifndef __STDC_LIMIT_MACROS
 #define __STDC_LIMIT_MACROS
@@ -325,11 +326,14 @@ type_to_llvm_type (EmitContext *ctx, MonoType *t)
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
-               return LLVMPointerType (IntPtrType (), 0);
+               return IntPtrType ();
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                /* Because of generic sharing */
-               return IntPtrType ();
+               if (mini_type_var_is_vt (ctx->cfg, t))
+                       return type_to_llvm_type (ctx, mini_get_gsharedvt_alloc_type_for_type (ctx->cfg, t));
+               else
+                       return IntPtrType ();
        case MONO_TYPE_GENERICINST:
                if (!mono_type_generic_inst_is_valuetype (t))
                        return IntPtrType ();
@@ -729,16 +733,6 @@ simd_op_to_intrins (int opcode)
                return "llvm.x86.sse.rsqrt.ps";
        case OP_RCPPS:
                return "llvm.x86.sse.rcp.ps";
-       case OP_PCMPEQB:
-               return "llvm.x86.sse2.pcmpeq.b";
-       case OP_PCMPEQW:
-               return "llvm.x86.sse2.pcmpeq.w";
-       case OP_PCMPEQD:
-               return "llvm.x86.sse2.pcmpeq.d";
-       case OP_PCMPEQQ:
-               return "llvm.x86.sse41.pcmpeqq";
-       case OP_PCMPGTB:
-               return "llvm.x86.sse2.pcmpgt.b";
        case OP_CVTDQ2PD:
                return "llvm.x86.sse2.cvtdq2pd";
        case OP_CVTDQ2PS:
@@ -1053,7 +1047,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 ();
@@ -1068,7 +1062,7 @@ sig_to_llvm_sig_full (EmitContext *ctx, MonoMethodSignature *sig, LLVMCallInfo *
                param_types [pindex] = IntPtrType ();
                pindex ++;
        }
-       if (cinfo && cinfo->imt_arg && IS_LLVM_MONO_BRANCH) {
+       if (cinfo && cinfo->imt_arg) {
                if (sinfo)
                        sinfo->imt_arg_pindex = pindex;
                param_types [pindex] = IntPtrType ();
@@ -1284,9 +1278,6 @@ set_metadata_flag (LLVMValueRef v, const char *flag_name)
        LLVMValueRef md_arg;
        int md_kind;
        
-       if (!IS_LLVM_MONO_BRANCH)
-               return;
-
        md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
        md_arg = LLVMMDString ("mono", 4);
        LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
@@ -1354,7 +1345,7 @@ emit_load (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, in
        LLVMValueRef args [16], res;
        LLVMTypeRef addr_type;
 
-       if (is_faulting && bb->region != -1 && IS_LLVM_MONO_BRANCH) {
+       if (is_faulting && bb->region != -1) {
                /*
                 * We handle loads which can fault by calling a mono specific intrinsic
                 * using an invoke, so they are handled properly inside try blocks.
@@ -1419,7 +1410,7 @@ emit_store (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, i
        const char *intrins_name;
        LLVMValueRef args [16];
 
-       if (is_faulting && bb->region != -1 && IS_LLVM_MONO_BRANCH) {
+       if (is_faulting && bb->region != -1) {
                switch (size) {
                case 1:
                        intrins_name = "llvm.mono.store.i8.p0i8";
@@ -1486,13 +1477,8 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
                MonoMethodSignature *throw_sig = mono_metadata_signature_alloc (mono_get_corlib (), 2);
                throw_sig->ret = &mono_get_void_class ()->byval_arg;
                throw_sig->params [0] = &mono_get_int32_class ()->byval_arg;
-               if (IS_LLVM_MONO_BRANCH) {
-                       icall_name = "llvm_throw_corlib_exception_abs_trampoline";
-                       throw_sig->params [1] = &mono_get_intptr_class ()->byval_arg;
-               } else {
-                       icall_name = "llvm_throw_corlib_exception_trampoline";
-                       throw_sig->params [1] = &mono_get_int32_class ()->byval_arg;
-               }
+               icall_name = "llvm_throw_corlib_exception_abs_trampoline";
+               throw_sig->params [1] = &mono_get_intptr_class ()->byval_arg;
                sig = sig_to_llvm_sig (ctx, throw_sig);
 
                if (ctx->cfg->compile_aot) {
@@ -1518,24 +1504,12 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
        else
                args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE);
 
-       if (IS_LLVM_MONO_BRANCH) {
-               /*
-                * The LLVM mono branch contains changes so a block address can be passed as an
-                * argument to a call.
-                */
-               args [1] = LLVMBuildPtrToInt (builder, LLVMBlockAddress (ctx->lmethod, ex_bb), IntPtrType (), "");
-               emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2);
-       } else {
-               /*
-                * FIXME: The offset is 0, this is only a problem if the code is inside a clause,
-                * otherwise only the line numbers in stack traces are incorrect.
-                */
-               if (bb->region != -1 && !IS_LLVM_MONO_BRANCH)
-                       LLVM_FAILURE (ctx, "system-ex-in-region");
-
-               args [1] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
-               emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2);
-       }
+       /*
+        * The LLVM mono branch contains changes so a block address can be passed as an
+        * argument to a call.
+        */
+       args [1] = LLVMBuildPtrToInt (builder, LLVMBlockAddress (ctx->lmethod, ex_bb), IntPtrType (), "");
+       emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2);
 
        LLVMBuildUnreachable (builder);
 
@@ -1546,9 +1520,6 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
 
        ctx->ex_index ++;
        return;
-
- FAILURE:
-       return;
 }
 
 /*
@@ -1712,7 +1683,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 */
@@ -1765,7 +1736,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) {
@@ -1853,7 +1824,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;
@@ -1864,18 +1835,6 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
        if (call->signature->call_convention != MONO_CALL_DEFAULT)
                LLVM_FAILURE (ctx, "non-default callconv");
 
-       if (call->rgctx_arg_reg && !IS_LLVM_MONO_BRANCH)
-               LLVM_FAILURE (ctx, "rgctx reg in call");
-
-       if (call->rgctx_reg && !IS_LLVM_MONO_BRANCH) {
-               /*
-                * It might be possible to support this by creating a static rgctx trampoline, but
-                * common_call_trampoline () would patch callsites to call the trampoline, which
-                * would be incorrect if the rgctx arg is computed dynamically.
-                */
-               LLVM_FAILURE (ctx, "rgctx reg");
-       }
-
        cinfo = call->cinfo;
        if (call->rgctx_arg_reg)
                cinfo->rgctx_arg = TRUE;
@@ -1976,30 +1935,7 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref,
                g_assert (ins->inst_offset % size == 0);
                index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset / size, FALSE);
 
-               /*
-                * When using the llvm mono branch, we can support IMT directly, otherwise
-                * we need to call a trampoline.
-                */
-               if (call->method && call->method->klass->flags & TYPE_ATTRIBUTE_INTERFACE && !IS_LLVM_MONO_BRANCH) {
-#ifdef MONO_ARCH_HAVE_LLVM_IMT_TRAMPOLINE
-                       if (cfg->compile_aot) {
-                               MonoJumpInfoImtTramp *imt_tramp = g_new0 (MonoJumpInfoImtTramp, 1);
-                               imt_tramp->method = call->method;
-                               imt_tramp->vt_offset = call->inst.inst_offset;
-
-                               callee = get_plt_entry (ctx, llvm_sig, MONO_PATCH_INFO_LLVM_IMT_TRAMPOLINE, imt_tramp);
-                       } else {
-                               callee = LLVMAddFunction (module, "", llvm_sig);
-                               target = mono_create_llvm_imt_trampoline (cfg->domain, call->method, call->inst.inst_offset);
-                               LLVMAddGlobalMapping (ee, callee, target);
-                       }
-#else
-                       /* No support for passing the IMT argument */
-                       LLVM_FAILURE (ctx, "imt");
-#endif
-               } else {
-                       callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
-               }
+               callee = convert (ctx, LLVMBuildLoad (builder, LLVMBuildGEP (builder, convert (ctx, values [ins->inst_basereg], LLVMPointerType (LLVMPointerType (IntPtrType (), 0), 0)), &index, 1, ""), ""), LLVMPointerType (llvm_sig, 0));
        } else if (calli) {
                callee = convert (ctx, values [ins->sreg1], LLVMPointerType (llvm_sig, 0));
        } else {
@@ -2010,25 +1946,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 (IS_LLVM_MONO_BRANCH) {
-               if (call->rgctx_arg_reg) {
-                       g_assert (values [call->rgctx_arg_reg]);
-                       args [sinfo.rgctx_arg_pindex] = values [call->rgctx_arg_reg];
-               }
-               if (call->imt_arg_reg) {
-                       g_assert (values [call->imt_arg_reg]);
-                       args [sinfo.imt_arg_pindex] = values [call->imt_arg_reg];
-               }
+       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 (), "");
        }
 
@@ -2156,10 +2094,11 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
        BBInfo *bblocks = ctx->bblocks;
        MonoInst *ins;
        LLVMBasicBlockRef cbb;
-       LLVMBuilderRef builder;
+       LLVMBuilderRef builder, starting_builder;
        gboolean has_terminator;
        LLVMValueRef v;
        LLVMValueRef lhs, rhs;
+       int nins = 0;
 
        cbb = get_bb (ctx, bb);
        builder = create_builder (ctx);
@@ -2218,14 +2157,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,
@@ -2277,11 +2222,18 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
        }
 
        has_terminator = FALSE;
+       starting_builder = builder;
        for (ins = bb->code; ins; ins = ins->next) {
                const char *spec = LLVM_INS_INFO (ins->opcode);
                char *dname = NULL;
                char dname_buf [128];
 
+               nins ++;
+               if (nins > 5000 && builder == starting_builder) {
+                       /* some steps in llc are non-linear in the size of basic blocks, see #5714 */
+                       LLVM_FAILURE (ctx, "basic block too long");
+               }
+
                if (has_terminator)
                        /* There could be instructions after a terminator, skip them */
                        break;
@@ -2827,7 +2779,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        break;
                case OP_INOT: {
                        guint32 v = 0xffffffff;
-                       values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), lhs, dname);
+                       values [ins->dreg] = LLVMBuildXor (builder, LLVMConstInt (LLVMInt32Type (), v, FALSE), convert (ctx, lhs, LLVMInt32Type ()), dname);
                        break;
                }
                case OP_LNOT: {
@@ -3093,7 +3045,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                }
 
                case OP_CHECK_THIS:
-                       emit_load (ctx, bb, &builder, sizeof (gpointer), convert (ctx, values [ins->sreg1], LLVMPointerType (IntPtrType (), 0)), "", TRUE);
+                       emit_load (ctx, bb, &builder, sizeof (gpointer), convert (ctx, lhs, LLVMPointerType (IntPtrType (), 0)), "", TRUE);
                        break;
                case OP_OUTARG_VTRETADDR:
                        break;
@@ -3208,14 +3160,14 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                         */
                        LLVM_FAILURE (ctx, "sqrt");
 #endif
-                       args [0] = lhs;
+                       args [0] = convert (ctx, lhs, LLVMDoubleType ());
                        values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.sqrt.f64"), args, 1, dname);
                        break;
                }
                case OP_ABS: {
                        LLVMValueRef args [1];
 
-                       args [0] = lhs;
+                       args [0] = convert (ctx, lhs, LLVMDoubleType ());
                        values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "fabs"), args, 1, dname);
                        break;
                }
@@ -3318,27 +3270,19 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        break;
                }
                case OP_MEMORY_BARRIER: {
-#ifdef TARGET_ARM
-                       /* Not yet supported by llc on arm */
-                       LLVM_FAILURE (ctx, "memory-barrier+arm");
-#endif
                        mono_llvm_build_fence (builder);
                        break;
                }
                case OP_RELAXED_NOP: {
 #if defined(TARGET_AMD64) || defined(TARGET_X86)
-                       if (IS_LLVM_MONO_BRANCH)
-                               emit_call (ctx, bb, &builder, LLVMGetNamedFunction (ctx->module, "llvm.x86.sse2.pause"), NULL, 0);
-                       else
-                               /* No way to get LLVM to emit this */
-                               LLVM_FAILURE (ctx, "relaxed_nop");
+                       emit_call (ctx, bb, &builder, LLVMGetNamedFunction (ctx->module, "llvm.x86.sse2.pause"), NULL, 0);
                        break;
 #else
                        break;
 #endif
                }
                case OP_TLS_GET: {
-#if defined(TARGET_AMD64) || defined(TARGET_X86)
+#if (defined(TARGET_AMD64) || defined(TARGET_X86)) && defined(__linux__)
 #ifdef TARGET_AMD64
                        // 257 == FS segment register
                        LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 257);
@@ -3431,6 +3375,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) {
@@ -3637,11 +3587,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_PSUBW_SAT_UN:
                case OP_PAVGB_UN:
                case OP_PAVGW_UN:
-               case OP_PCMPEQB:
-               case OP_PCMPEQW:
-               case OP_PCMPEQD:
-               case OP_PCMPEQQ:
-               case OP_PCMPGTB:
                case OP_PACKW:
                case OP_PACKD:
                case OP_PACKW_UN:
@@ -3656,6 +3601,17 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, simd_op_to_intrins (ins->opcode)), args, 2, dname);
                        break;
                }
+               case OP_PCMPEQB:
+               case OP_PCMPEQW:
+               case OP_PCMPEQD:
+               case OP_PCMPEQQ: {
+                       values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntEQ, lhs, rhs, ""), LLVMTypeOf (lhs), "");
+                       break;
+               }
+               case OP_PCMPGTB: {
+                       values [ins->dreg] = LLVMBuildSExt (builder, LLVMBuildICmp (builder, LLVMIntSGT, lhs, rhs, ""), LLVMTypeOf (lhs), "");
+                       break;
+               }
                case OP_EXTRACT_R8:
                case OP_EXTRACT_I8:
                case OP_EXTRACT_I4:
@@ -3814,7 +3770,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                case OP_PSHUFLEW_LOW:
                case OP_PSHUFLEW_HIGH: {
                        int mask [16];
-                       LLVMValueRef v1 = NULL, v2 = NULL, mask_values [4];
+                       LLVMValueRef v1 = NULL, v2 = NULL, mask_values [16];
                        int i, mask_size = 0;
                        int imask = ins->inst_c0;
        
@@ -4042,7 +3998,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;
                }
@@ -4171,24 +4127,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->generic_sharing_context && !IS_LLVM_MONO_BRANCH) {
-               /* No way to obtain location info for this/rgctx */
-               cfg->exception_message = g_strdup ("gshared");
-               cfg->disable_llvm = TRUE;
-       }
 
        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];
                
@@ -4308,12 +4256,8 @@ mono_llvm_emit_method (MonoCompile *cfg)
        ctx->linfo = linfo;
        CHECK_FAILURE (ctx);
 
-       if (cfg->rgctx_var) {
-               if (IS_LLVM_MONO_BRANCH)
-                       linfo->rgctx_arg = TRUE;
-               else
-                       LLVM_FAILURE (ctx, "rgctx arg");
-       }
+       if (cfg->rgctx_var)
+               linfo->rgctx_arg = TRUE;
        method_type = sig_to_llvm_sig_full (ctx, sig, linfo, &sinfo);
        CHECK_FAILURE (ctx);
 
@@ -4531,7 +4475,9 @@ mono_llvm_emit_method (MonoCompile *cfg)
                        if (ctx->unreachable [node->in_bb->block_num])
                                continue;
 
-                       g_assert (values [sreg1]);
+                       if (!values [sreg1])
+                               /* Can happen with values in EH clauses */
+                               LLVM_FAILURE (ctx, "incoming phi sreg1");
 
                        if (phi->opcode == OP_VPHI) {
                                g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
@@ -4666,15 +4612,19 @@ mono_llvm_emit_call (MonoCompile *cfg, MonoCallInst *call)
                /* Simply remember the arguments */
                switch (ainfo->storage) {
                case LLVMArgInIReg:
-                       MONO_INST_NEW (cfg, ins, OP_MOVE);
-                       ins->dreg = mono_alloc_ireg (cfg);
-                       ins->sreg1 = in->dreg;
-                       break;
-               case LLVMArgInFPReg:
-                       MONO_INST_NEW (cfg, ins, OP_FMOVE);
-                       ins->dreg = mono_alloc_freg (cfg);
+               case LLVMArgInFPReg: {
+                       MonoType *t = (sig->hasthis && i == 0) ? &mono_get_intptr_class ()->byval_arg : sig->params [i - sig->hasthis];
+
+                       if (!t->byref && (t->type == MONO_TYPE_R8 || t->type == MONO_TYPE_R4)) {
+                               MONO_INST_NEW (cfg, ins, OP_FMOVE);
+                               ins->dreg = mono_alloc_freg (cfg);
+                       } else {
+                               MONO_INST_NEW (cfg, ins, OP_MOVE);
+                               ins->dreg = mono_alloc_ireg (cfg);
+                       }
                        ins->sreg1 = in->dreg;
                        break;
+               }
                case LLVMArgVtypeByVal:
                case LLVMArgVtypeInReg:
                        MONO_INST_NEW (cfg, ins, OP_LLVM_OUTARG_VT);
@@ -4803,6 +4753,27 @@ exception_cb (void *data)
        g_free (type_info);
 }
 
+static char*
+dlsym_cb (const char *name, void **symbol)
+{
+       MonoDl *current;
+       char *err;
+
+       err = NULL;
+       if (!strcmp (name, "__bzero")) {
+               *symbol = (void*)bzero;
+       } else {
+               current = mono_dl_open (NULL, 0, NULL);
+               g_assert (current);
+
+               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
 AddFunc (LLVMModuleRef module, const char *name, LLVMTypeRef ret_type, LLVMTypeRef *param_types, int nparams)
 {
@@ -4915,7 +4886,6 @@ add_intrinsics (LLVMModuleRef module)
                arg_types [1] = ret_type;
                AddFunc (module, "llvm.x86.sse41.pminud", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse41.pmaxud", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pcmpeq.d", ret_type, arg_types, 2);
 
                ret_type = type_to_simd_type (MONO_TYPE_I2);
                arg_types [0] = ret_type;
@@ -4923,7 +4893,6 @@ add_intrinsics (LLVMModuleRef module)
                AddFunc (module, "llvm.x86.sse41.pminuw", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.pmins.w", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse41.pmaxuw", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pcmpeq.w", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.padds.w", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.psubs.w", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.paddus.w", ret_type, arg_types, 2);
@@ -4937,19 +4906,12 @@ add_intrinsics (LLVMModuleRef module)
                arg_types [1] = ret_type;
                AddFunc (module, "llvm.x86.sse2.pminu.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.pmaxu.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pcmpeq.b", ret_type, arg_types, 2);
-               AddFunc (module, "llvm.x86.sse2.pcmpgt.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.padds.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.psubs.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.paddus.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.psubus.b", ret_type, arg_types, 2);
                AddFunc (module, "llvm.x86.sse2.pavg.b", ret_type, arg_types, 2);
 
-               ret_type = type_to_simd_type (MONO_TYPE_I8);
-               arg_types [0] = ret_type;
-               arg_types [1] = ret_type;
-               AddFunc (module, "llvm.x86.sse41.pcmpeqq", ret_type, arg_types, 2);
-
                ret_type = type_to_simd_type (MONO_TYPE_R8);
                arg_types [0] = ret_type;
                arg_types [1] = ret_type;
@@ -5058,12 +5020,10 @@ add_intrinsics (LLVMModuleRef module)
                AddFunc (module, "llvm.x86.sse2.pmovmskb.128", ret_type, arg_types, 1);
        }
 
-       if (IS_LLVM_MONO_BRANCH) {
-               AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
-       }
+       AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
 
        /* Load/Store intrinsics */
-       if (IS_LLVM_MONO_BRANCH) {
+       {
                LLVMTypeRef arg_types [5];
                int i;
                char name [128];
@@ -5108,7 +5068,7 @@ init_jit_module (void)
 
        jit_module.module = LLVMModuleCreateWithName ("mono");
 
-       ee = mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (jit_module.module), alloc_cb, emitted_cb, exception_cb);
+       ee = mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (jit_module.module), alloc_cb, emitted_cb, exception_cb, dlsym_cb);
 
        add_intrinsics (jit_module.module);