gboolean *is_dead;
gboolean *unreachable;
int *pindexes;
+ LLVMValueRef imt_rgctx_loc;
char temp_name [32];
} EmitContext;
*nregs = pindex;
}
+static LLVMValueRef
+build_alloca_llvm_type (EmitContext *ctx, LLVMTypeRef t, int align)
+{
+ /*
+ * Have to place all alloca's at the end of the entry bb, since otherwise they would
+ * get executed every time control reaches them.
+ */
+ LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
+
+ ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, t, NULL, align, "");
+ return ctx->last_alloca;
+}
+
static LLVMValueRef
build_alloca (EmitContext *ctx, MonoType *t)
{
while (mono_is_power_of_two (align) == -1)
align ++;
- /*
- * Have to place all alloca's at the end of the entry bb, since otherwise they would
- * get executed every time control reaches them.
- */
- LLVMPositionBuilder (ctx->alloca_builder, get_bb (ctx, ctx->cfg->bb_entry), ctx->last_alloca);
-
- ctx->last_alloca = mono_llvm_build_alloca (ctx->alloca_builder, type_to_llvm_type (ctx, t), NULL, align, "");
- return ctx->last_alloca;
+ return build_alloca_llvm_type (ctx, type_to_llvm_type (ctx, t), align);
}
/*
if (call->rgctx_arg_reg) {
g_assert (values [call->rgctx_arg_reg]);
g_assert (sinfo.rgctx_arg_pindex < nargs);
+ /*
+ * On ARM, the imt/rgctx argument is passed in a caller save register, but some of our trampolines etc. clobber it, leading to
+ * problems is LLVM moves the arg assignment earlier. To work around this, save the argument into a stack slot and load
+ * it using a volatile load.
+ */
+#ifdef TARGET_ARM
+ if (!ctx->imt_rgctx_loc)
+ ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->lmodule->ptr_type, sizeof (gpointer));
+ LLVMBuildStore (builder, convert (ctx, ctx->values [call->rgctx_arg_reg], ctx->lmodule->ptr_type), ctx->imt_rgctx_loc);
+ args [sinfo.rgctx_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
+#else
args [sinfo.rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->lmodule->ptr_type);
+#endif
}
if (call->imt_arg_reg) {
g_assert (values [call->imt_arg_reg]);
g_assert (sinfo.imt_arg_pindex < nargs);
+#ifdef TARGET_ARM
+ if (!ctx->imt_rgctx_loc)
+ ctx->imt_rgctx_loc = build_alloca_llvm_type (ctx, ctx->lmodule->ptr_type, sizeof (gpointer));
+ LLVMBuildStore (builder, convert (ctx, ctx->values [call->imt_arg_reg], ctx->lmodule->ptr_type), ctx->imt_rgctx_loc);
+ args [sinfo.imt_arg_pindex] = mono_llvm_build_load (builder, ctx->imt_rgctx_loc, "", TRUE);
+#else
args [sinfo.imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->lmodule->ptr_type);
+#endif
}
if (vretaddr) {
case OP_TLS_GET_REG: {
#if defined(TARGET_AMD64) && defined(TARGET_OSX)
/* See emit_tls_get_reg () */
- LLVMValueRef base, shifted_offset, offset;
-
- base = LLVMConstInt (LLVMInt32Type (), mono_amd64_get_tls_gs_offset (), TRUE);
- shifted_offset = LLVMBuildMul (builder, convert (ctx, lhs, LLVMInt32Type ()), LLVMConstInt (LLVMInt32Type (), 8, TRUE), "");
- offset = LLVMBuildAdd (builder, base, shifted_offset, "");
// 256 == GS segment register
LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
- values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, offset, ptrtype, ""), "");
+ values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
#else
LLVM_FAILURE (ctx, "opcode tls-get");
#endif
g_assert (LLVMTypeOf (ctx->addresses [sreg1]) == LLVMTypeOf (values [phi->dreg]));
LLVMAddIncoming (values [phi->dreg], &ctx->addresses [sreg1], &in_bb, 1);
} else {
+ if (LLVMTypeOf (values [sreg1]) != LLVMTypeOf (values [phi->dreg]))
+ // FIXME:
+ LLVM_FAILURE (ctx, "incoming phi arg type mismatch");
g_assert (LLVMTypeOf (values [sreg1]) == LLVMTypeOf (values [phi->dreg]));
LLVMAddIncoming (values [phi->dreg], &values [sreg1], &in_bb, 1);
}