X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmini%2Fmini-llvm.c;h=fd822480af158b26346703d6b756b6642d8b67a9;hb=8170bf67b1e630a8eb7d3fa0cb7c191c38f5c663;hp=ea5072c296548a8b75945c3bbb7408079be73e8d;hpb=c160422cd3fee6df957da88ba07ed3f01be22237;p=mono.git diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index ea5072c2965..fd822480af1 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS @@ -190,7 +191,6 @@ static gboolean jit_module_inited; static int memset_param_count, memcpy_param_count; static const char *memset_func_name; static const char *memcpy_func_name; -static const char *eh_selector_name; static void init_jit_module (void); @@ -326,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 (); @@ -730,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: @@ -846,7 +839,12 @@ get_bb (EmitContext *ctx, MonoBasicBlock *bb) char bb_name [128]; if (ctx->bblocks [bb->block_num].bblock == NULL) { - sprintf (bb_name, "BB%d", bb->block_num); + if (bb->flags & BB_EXCEPTION_HANDLER) { + int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1; + sprintf (bb_name, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num); + } else { + sprintf (bb_name, "BB%d", bb->block_num); + } ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name); ctx->bblocks [bb->block_num].end_bblock = ctx->bblocks [bb->block_num].bblock; @@ -1049,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 (); @@ -1064,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 (); @@ -1176,7 +1174,7 @@ LLVMFunctionType1(LLVMTypeRef ReturnType, * * Create an LLVM function type from the arguments. */ -static LLVMTypeRef +static G_GNUC_UNUSED LLVMTypeRef LLVMFunctionType2(LLVMTypeRef ReturnType, LLVMTypeRef ParamType1, LLVMTypeRef ParamType2, @@ -1195,7 +1193,7 @@ LLVMFunctionType2(LLVMTypeRef ReturnType, * * Create an LLVM function type from the arguments. */ -static LLVMTypeRef +static G_GNUC_UNUSED LLVMTypeRef LLVMFunctionType3(LLVMTypeRef ReturnType, LLVMTypeRef ParamType1, LLVMTypeRef ParamType2, @@ -1280,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)); @@ -1350,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. @@ -1415,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"; @@ -1482,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) { @@ -1514,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); @@ -1542,9 +1520,6 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex ctx->ex_index ++; return; - - FAILURE: - return; } /* @@ -1708,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 */ @@ -1761,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) { @@ -1845,11 +1820,11 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMValueRef *addresses = ctx->addresses; MonoCallInst *call = (MonoCallInst*)ins; MonoMethodSignature *sig = call->signature; - LLVMValueRef callee, lcall; + LLVMValueRef callee = NULL, lcall; LLVMValueRef *args; LLVMCallInfo *cinfo; GSList *l; - int i, len; + int i, len, nargs; gboolean vretaddr; LLVMTypeRef llvm_sig; gpointer target; @@ -1860,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; @@ -1972,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 { @@ -2006,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 (), ""); } @@ -2152,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); @@ -2168,7 +2111,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) if (bb->flags & BB_EXCEPTION_HANDLER) { LLVMTypeRef i8ptr; - LLVMValueRef eh_selector, eh_exception, personality, args [4]; + LLVMValueRef personality; LLVMBasicBlockRef target_bb; MonoInst *exvar; static gint32 mapping_inited; @@ -2187,7 +2130,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) LLVM_FAILURE (ctx, "handler without invokes"); } - eh_selector = LLVMGetNamedFunction (module, eh_selector_name); + // = landingpad personality + if (cfg->compile_aot) { /* Use a dummy personality function */ @@ -2214,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, @@ -2236,22 +2185,28 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) LLVMAddGlobalMapping (ee, type_info, ti); } - args [0] = LLVMConstNull (i8ptr); - args [1] = LLVMConstBitCast (personality, i8ptr); - args [2] = type_info; - LLVMBuildCall (builder, eh_selector, args, 3, ""); + { + LLVMTypeRef members [2], ret_type; + LLVMValueRef landing_pad; + + members [0] = i8ptr; + members [1] = LLVMInt32Type (); + ret_type = LLVMStructType (members, 2, FALSE); + + landing_pad = LLVMBuildLandingPad (builder, ret_type, personality, 1, ""); + LLVMAddClause (landing_pad, type_info); - /* Store the exception into the exvar */ - if (bb->in_scount == 1) { - g_assert (bb->in_scount == 1); - exvar = bb->in_stack [0]; + /* Store the exception into the exvar */ + if (bb->in_scount == 1) { + g_assert (bb->in_scount == 1); + exvar = bb->in_stack [0]; - eh_exception = LLVMGetNamedFunction (module, "llvm.eh.exception"); + // FIXME: This is shared with filter clauses ? + g_assert (!values [exvar->dreg]); - // FIXME: This is shared with filter clauses ? - g_assert (!values [exvar->dreg]); - values [exvar->dreg] = LLVMBuildCall (builder, eh_exception, NULL, 0, ""); - emit_volatile_store (ctx, exvar->dreg); + values [exvar->dreg] = LLVMBuildExtractValue (builder, landing_pad, 0, "ex_obj"); + emit_volatile_store (ctx, exvar->dreg); + } } /* Start a new bblock which CALL_HANDLER can branch to */ @@ -2267,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; @@ -2817,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: { @@ -3083,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; @@ -3198,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; } @@ -3254,7 +3216,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0)); args [1] = rhs; - values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.atomic.swap.i32.p0i32"), args, 2, dname); + + values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]); break; } case OP_ATOMIC_EXCHANGE_I8: { @@ -3264,7 +3227,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0)); args [1] = convert (ctx, rhs, LLVMInt64Type ()); - values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.atomic.swap.i64.p0i64"), args, 2, 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: { @@ -3274,7 +3237,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0)); args [1] = rhs; - values [ins->dreg] = LLVMBuildAdd (builder, LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.atomic.load.add.i32.p0i32"), args, 2, ""), args [1], dname); + values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname); break; } case OP_ATOMIC_ADD_NEW_I8: { @@ -3284,21 +3247,18 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0)); args [1] = convert (ctx, rhs, LLVMInt64Type ()); - values [ins->dreg] = LLVMBuildAdd (builder, LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.atomic.load.add.i64.p0i64"), args, 2, ""), args [1], dname); + values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname); break; } case OP_ATOMIC_CAS_I4: case OP_ATOMIC_CAS_I8: { LLVMValueRef args [3]; LLVMTypeRef t; - const char *intrins; if (ins->opcode == OP_ATOMIC_CAS_I4) { t = LLVMInt32Type (); - intrins = "llvm.atomic.cmp.swap.i32.p0i32"; } else { t = LLVMInt64Type (); - intrins = "llvm.atomic.cmp.swap.i64.p0i64"; } args [0] = convert (ctx, lhs, LLVMPointerType (t, 0)); @@ -3306,37 +3266,23 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) args [1] = convert (ctx, values [ins->sreg3], t); /* new value */ args [2] = convert (ctx, values [ins->sreg2], t); - values [ins->dreg] = LLVMBuildCall (builder, LLVMGetNamedFunction (module, intrins), args, 3, dname); + values [ins->dreg] = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]); break; } case OP_MEMORY_BARRIER: { - LLVMValueRef args [5]; - -#ifdef TARGET_ARM - /* Not yet supported by llc on arm */ - LLVM_FAILURE (ctx, "memory-barrier+arm"); -#endif - - for (i = 0; i < 5; ++i) - args [i] = LLVMConstInt (LLVMInt1Type (), TRUE, TRUE); - - LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.memory.barrier"), args, 5, ""); + 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); @@ -3420,7 +3366,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) case OP_LOADV_MEMBASE: case OP_VMOVE: { MonoClass *klass = ins->klass; - LLVMValueRef src, dst, args [5]; + LLVMValueRef src = NULL, dst, args [5]; gboolean done = FALSE; if (!klass) { @@ -3429,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) { @@ -3562,7 +3514,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) case OP_ORPD: case OP_XORPD: { LLVMTypeRef t, rt; - LLVMValueRef v; + LLVMValueRef v = NULL; switch (ins->opcode) { case OP_ANDPS: @@ -3635,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: @@ -3654,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: @@ -3812,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; @@ -4040,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; } @@ -4169,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]; @@ -4306,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); @@ -4329,7 +4275,7 @@ mono_llvm_emit_method (MonoCompile *cfg) #endif LLVMSetLinkage (method, LLVMPrivateLinkage); - LLVMAddFunctionAttr (method, LLVMUWTableAttribute); + LLVMAddFunctionAttr (method, LLVMUWTable); if (cfg->compile_aot) { LLVMSetLinkage (method, LLVMInternalLinkage); @@ -4529,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])); @@ -4664,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); @@ -4801,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) { @@ -4855,18 +4828,6 @@ add_intrinsics (LLVMModuleRef module) LLVMAddFunction (module, "fabs", LLVMFunctionType (LLVMDoubleType (), params, 1, FALSE)); } - { - LLVMTypeRef membar_params [] = { LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type (), LLVMInt1Type () }; - - LLVMAddFunction (module, "llvm.atomic.swap.i32.p0i32", LLVMFunctionType2 (LLVMInt32Type (), LLVMPointerType (LLVMInt32Type (), 0), LLVMInt32Type (), FALSE)); - LLVMAddFunction (module, "llvm.atomic.swap.i64.p0i64", LLVMFunctionType2 (LLVMInt64Type (), LLVMPointerType (LLVMInt64Type (), 0), LLVMInt64Type (), FALSE)); - LLVMAddFunction (module, "llvm.atomic.load.add.i32.p0i32", LLVMFunctionType2 (LLVMInt32Type (), LLVMPointerType (LLVMInt32Type (), 0), LLVMInt32Type (), FALSE)); - LLVMAddFunction (module, "llvm.atomic.load.add.i64.p0i64", LLVMFunctionType2 (LLVMInt64Type (), LLVMPointerType (LLVMInt64Type (), 0), LLVMInt64Type (), FALSE)); - LLVMAddFunction (module, "llvm.atomic.cmp.swap.i32.p0i32", LLVMFunctionType3 (LLVMInt32Type (), LLVMPointerType (LLVMInt32Type (), 0), LLVMInt32Type (), LLVMInt32Type (), FALSE)); - LLVMAddFunction (module, "llvm.atomic.cmp.swap.i64.p0i64", LLVMFunctionType3 (LLVMInt64Type (), LLVMPointerType (LLVMInt64Type (), 0), LLVMInt64Type (), LLVMInt64Type (), FALSE)); - LLVMAddFunction (module, "llvm.memory.barrier", LLVMFunctionType (LLVMVoidType (), membar_params, 5, FALSE)); - } - { LLVMTypeRef ovf_res_i32 [] = { LLVMInt32Type (), LLVMInt1Type () }; LLVMTypeRef ovf_params_i32 [] = { LLVMInt32Type (), LLVMInt32Type () }; @@ -4908,13 +4869,8 @@ add_intrinsics (LLVMModuleRef module) arg_types [0] = LLVMPointerType (LLVMInt8Type (), 0); arg_types [1] = LLVMPointerType (LLVMInt8Type (), 0); - eh_selector_name = "llvm.eh.selector"; ret_type = LLVMInt32Type (); - LLVMAddFunction (module, eh_selector_name, LLVMFunctionType (ret_type, arg_types, 2, TRUE)); - - LLVMAddFunction (module, "llvm.eh.exception", LLVMFunctionType (LLVMPointerType (LLVMInt8Type (), 0), NULL, 0, FALSE)); - LLVMAddFunction (module, "mono_personality", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE)); LLVMAddFunction (module, "llvm_resume_unwind_trampoline", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE)); @@ -4922,7 +4878,7 @@ add_intrinsics (LLVMModuleRef module) /* SSE intrinsics */ { - LLVMTypeRef ret_type, arg_types [2]; + LLVMTypeRef ret_type, arg_types [16]; /* Binary ops */ ret_type = type_to_simd_type (MONO_TYPE_I4); @@ -4930,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; @@ -4938,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); @@ -4952,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; @@ -5073,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]; @@ -5123,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);