return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
}
+static LLVMTypeRef
+ObjRefType (void)
+{
+ return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
+}
+
/*
* get_vtype_size:
*
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;
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: {
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, "");
} 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 ();
{
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:
*
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 */
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) {
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);
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.
*/
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) {
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:
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') {
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:
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);
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");
}
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:
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;
}
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 */
// 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
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) {
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;
}
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, "");
}
}
method = LLVMAddFunction (module, method_name, method_type);
ctx->lmethod = method;
-#ifdef LLVM_MONO_BRANCH
LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
-#endif
LLVMSetLinkage (method, LLVMPrivateLinkage);
LLVMAddFunctionAttr (method, LLVMUWTable);
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)
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];
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);