/*
* mini-llvm.c: llvm "Backend" for the mono JIT
*
- * (C) 2009 Novell, Inc.
+ * Copyright 2009-2011 Novell Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
*/
#include "mini.h"
#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
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);
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 */
if (!ltype) {
int i, size;
LLVMTypeRef *eltypes;
+ char *name;
size = get_vtype_size (t);
for (i = 0; i < size; ++i)
eltypes [i] = LLVMInt8Type ();
- /* We couldn't name these types since LLVM uses structural type equality */
- ltype = LLVMStructType (eltypes, size, FALSE);
+ name = mono_type_full_name (&klass->byval_arg);
+ ltype = LLVMStructCreateNamed (LLVMGetGlobalContext (), name);
+ LLVMStructSetBody (ltype, eltypes, size, FALSE);
g_hash_table_insert (ctx->lmodule->llvm_types, klass, ltype);
g_free (eltypes);
}
simd_op_to_intrins (int opcode)
{
switch (opcode) {
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
+#ifdef MONO_ARCH_SIMD_INTRINSICS
case OP_MINPD:
return "llvm.x86.sse2.min.pd";
case OP_MINPS:
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:
static LLVMTypeRef
simd_op_to_llvm_type (int opcode)
{
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
+#ifdef MONO_ARCH_SIMD_INTRINSICS
switch (opcode) {
case OP_EXTRACT_R8:
case OP_EXPAND_R8:
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;
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 ();
*
* Create an LLVM function type from the arguments.
*/
-static LLVMTypeRef
+static G_GNUC_UNUSED LLVMTypeRef
LLVMFunctionType2(LLVMTypeRef ReturnType,
LLVMTypeRef ParamType1,
LLVMTypeRef ParamType2,
*
* Create an LLVM function type from the arguments.
*/
-static LLVMTypeRef
+static G_GNUC_UNUSED LLVMTypeRef
LLVMFunctionType3(LLVMTypeRef ReturnType,
LLVMTypeRef ParamType1,
LLVMTypeRef ParamType2,
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));
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.
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";
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) {
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);
ctx->ex_index ++;
return;
-
- FAILURE:
- return;
}
/*
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;
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;
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 {
/*
* 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 (), "");
}
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);
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;
LLVM_FAILURE (ctx, "handler without invokes");
}
- eh_selector = LLVMGetNamedFunction (module, eh_selector_name);
+ // <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
if (cfg->compile_aot) {
/* Use a dummy personality function */
* 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,
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 */
}
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;
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: {
}
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;
*/
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;
}
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: {
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: {
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: {
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));
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);
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) {
/*
* SIMD
*/
-#if defined(TARGET_X86) || defined(TARGET_AMD64)
+#ifdef MONO_ARCH_SIMD_INTRINSICS
case OP_XZERO: {
values [ins->dreg] = LLVMConstNull (type_to_llvm_type (ctx, &ins->klass->byval_arg));
break;
case OP_ORPD:
case OP_XORPD: {
LLVMTypeRef t, rt;
- LLVMValueRef v;
+ LLVMValueRef v = NULL;
switch (ins->opcode) {
case OP_ANDPS:
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:
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:
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;
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];
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);
#endif
LLVMSetLinkage (method, LLVMPrivateLinkage);
- LLVMAddFunctionAttr (method, LLVMUWTableAttribute);
+ LLVMAddFunctionAttr (method, LLVMUWTable);
if (cfg->compile_aot) {
LLVMSetLinkage (method, LLVMInternalLinkage);
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]));
/* 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);
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)
{
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 () };
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));
/* 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);
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;
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);
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;
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];
void
mono_llvm_init (void)
{
- mono_native_tls_alloc (current_cfg_tls_id, NULL);
+ mono_native_tls_alloc (¤t_cfg_tls_id, NULL);
}
static 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);