const char *got_symbol;
GHashTable *plt_entries;
char **bb_names;
+ int bb_names_len;
GPtrArray *used;
LLVMTypeRef ptr_type;
+ MonoEERef *mono_ee;
+ LLVMExecutionEngineRef ee;
} MonoLLVMModule;
/*
gboolean *is_dead;
gboolean *unreachable;
int *pindexes;
+ LLVMValueRef imt_rgctx_loc;
+ GHashTable *llvm_types;
char temp_name [32];
} EmitContext;
LLVMRealUGT,
};
-static LLVMExecutionEngineRef ee;
static MonoNativeTlsKey current_cfg_tls_id;
-static MonoLLVMModule jit_module, aot_module;
-static gboolean jit_module_inited;
+static MonoLLVMModule aot_module;
static int memset_param_count, memcpy_param_count;
static const char *memset_func_name;
static const char *memcpy_func_name;
-static void init_jit_module (void);
+static void init_jit_module (MonoDomain *domain);
/*
* IntPtrType:
static LLVMTypeRef
type_to_llvm_type (EmitContext *ctx, MonoType *t)
{
+ t = mini_replace_type (t);
+
if (t->byref)
return LLVMPointerType (LLVMInt8Type (), 0);
switch (t->type) {
if (klass->enumtype)
return type_to_llvm_type (ctx, mono_class_enum_basetype (klass));
+
ltype = g_hash_table_lookup (ctx->lmodule->llvm_types, klass);
if (!ltype) {
int i, size;
LLVMStructSetBody (ltype, eltypes, size, FALSE);
g_hash_table_insert (ctx->lmodule->llvm_types, klass, ltype);
g_free (eltypes);
+ g_free (name);
}
return ltype;
}
sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
bb_name = bb_name_buf;
} else if (bb->block_num < 256) {
- if (!ctx->lmodule->bb_names)
- ctx->lmodule->bb_names = g_new0 (char*, 256);
+ if (!ctx->lmodule->bb_names) {
+ ctx->lmodule->bb_names_len = 256;
+ ctx->lmodule->bb_names = g_new0 (char*, ctx->lmodule->bb_names_len);
+ }
if (!ctx->lmodule->bb_names [bb->block_num]) {
char *n;
int i, j, pindex, vret_arg_pindex = 0;
int *pindexes;
gboolean vretaddr = FALSE;
+ MonoType *rtype;
if (sinfo)
memset (sinfo, 0, sizeof (LLVMSigInfo));
- ret_type = type_to_llvm_type (ctx, sig->ret);
+ rtype = mini_replace_type (sig->ret);
+ ret_type = type_to_llvm_type (ctx, rtype);
CHECK_FAILURE (ctx);
if (cinfo && cinfo->ret.storage == LLVMArgVtypeInReg) {
} else {
g_assert_not_reached ();
}
- } else if (cinfo && mini_type_is_vtype (ctx->cfg, sig->ret)) {
+ } else if (cinfo && mini_type_is_vtype (ctx->cfg, rtype)) {
g_assert (cinfo->ret.storage == LLVMArgVtypeRetAddr);
vretaddr = TRUE;
ret_type = LLVMVoidType ();
* - On x86, LLVM generated code doesn't push the arguments
* - The trampoline takes the throw address as an arguments, not a pc offset.
*/
- LLVMAddGlobalMapping (ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
}
mono_memory_barrier ();
*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);
}
/*
target =
mono_create_jit_trampoline_in_domain (mono_domain_get (),
call->method);
- LLVMAddGlobalMapping (ee, callee, target);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, target);
}
}
} else {
callee = LLVMAddFunction (module, "", llvm_sig);
target = (gpointer)mono_icall_get_wrapper (info);
- LLVMAddGlobalMapping (ee, callee, target);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, target);
}
} else {
if (cfg->compile_aot) {
LLVM_FAILURE (ctx, "trampoline with own cconv");
#endif
target = mono_resolve_patch_target (cfg->method, cfg->domain, NULL, abs_ji, FALSE);
- LLVMAddGlobalMapping (ee, callee, target);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, target);
}
}
if (!target)
- LLVMAddGlobalMapping (ee, callee, (gpointer)call->fptr);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, (gpointer)call->fptr);
}
}
}
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) {
} else {
personality = LLVMGetNamedFunction (module, "mono_personality");
if (InterlockedCompareExchange (&mapping_inited, 1, 0) == 0)
- LLVMAddGlobalMapping (ee, personality, mono_personality);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, personality, mono_personality);
}
i8ptr = LLVMPointerType (LLVMInt8Type (), 0);
type_info = LLVMAddGlobal (module, i8ptr, ti_name);
- LLVMAddGlobalMapping (ee, type_info, ti);
+ LLVMAddGlobalMapping (ctx->lmodule->ee, type_info, ti);
}
{
case OP_R4CONST:
values [ins->dreg] = LLVMConstFPExt (LLVMConstReal (LLVMFloatType (), *(float*)ins->inst_p0), LLVMDoubleType ());
break;
+ case OP_DUMMY_ICONST:
+ values [ins->dreg] = LLVMConstInt (LLVMInt32Type (), 0, FALSE);
+ break;
+ case OP_DUMMY_I8CONST:
+ values [ins->dreg] = LLVMConstInt (LLVMInt64Type (), 0, FALSE);
+ break;
+ case OP_DUMMY_R8CONST:
+ values [ins->dreg] = LLVMConstReal (LLVMDoubleType (), 0.0f);
+ break;
case OP_BR:
LLVMBuildBr (builder, get_bb (ctx, ins->inst_target_bb));
has_terminator = TRUE;
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: {
+ case OP_ATOMIC_ADD_I4:
+ case OP_ATOMIC_ADD_I8: {
LLVMValueRef args [2];
LLVMTypeRef t;
- if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+ if (ins->opcode == OP_ATOMIC_ADD_I4)
t = LLVMInt32Type ();
else
t = LLVMInt64Type ();
}
case OP_ATOMIC_CAS_I4:
case OP_ATOMIC_CAS_I8: {
- LLVMValueRef args [3];
+ LLVMValueRef args [3], val;
LLVMTypeRef t;
if (ins->opcode == OP_ATOMIC_CAS_I4)
args [1] = convert (ctx, values [ins->sreg3], t);
/* new value */
args [2] = convert (ctx, values [ins->sreg2], t);
- values [ins->dreg] = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
+ val = mono_llvm_build_cmpxchg (builder, args [0], args [1], args [2]);
+#if LLVM_API_VERSION >= 1
+ /* cmpxchg returns a pair */
+ values [ins->dreg] = LLVMBuildExtractValue (builder, val, 0, "");
+#else
+ values [ins->dreg] = val;
+#endif
break;
}
case OP_MEMORY_BARRIER: {
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
LLVMBuildCall (builder, LLVMGetNamedFunction (module, memset_func_name), args, memset_param_count, "");
break;
}
+ case OP_DUMMY_VZERO:
+ break;
case OP_STOREV_MEMBASE:
case OP_LOADV_MEMBASE:
* LLVM doesn't push the exception argument, so we need a different
* trampoline.
*/
- LLVMAddGlobalMapping (ee, callee, resolve_patch (cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline"));
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, resolve_patch (cfg, MONO_PATCH_INFO_INTERNAL_METHOD, rethrow ? "llvm_rethrow_exception_trampoline" : "llvm_throw_exception_trampoline"));
#else
- LLVMAddGlobalMapping (ee, callee, resolve_patch (cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
+ LLVMAddGlobalMapping (ctx->lmodule->ee, callee, resolve_patch (cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
#endif
}
cfg->exception_message = g_strdup ("lmf");
cfg->disable_llvm = TRUE;
}
+ if (cfg->disable_llvm)
+ return;
#if 1
for (i = 0; i < header->num_clauses; ++i) {
*/
cfg->exception_message = g_strdup ("nested clauses");
cfg->disable_llvm = TRUE;
+ break;
}
}
+ if (cfg->disable_llvm)
+ return;
#endif
/* FIXME: */
cfg->exception_message = g_strdup ("dynamic.");
cfg->disable_llvm = TRUE;
}
+ if (cfg->disable_llvm)
+ return;
}
/*
method_name = mono_aot_get_method_name (cfg);
cfg->llvm_method_name = g_strdup (method_name);
} else {
- init_jit_module ();
- ctx->lmodule = &jit_module;
+ init_jit_module (cfg->domain);
+ ctx->lmodule = domain_jit_info (cfg->domain)->llvm_module;
method_name = mono_method_full_name (cfg->method, TRUE);
}
-
+
module = ctx->module = ctx->lmodule->module;
if (cfg->gsharedvt)
if (cfg->compile_aot) {
LLVMSetLinkage (method, LLVMInternalLinkage);
+#if LLVM_API_VERSION == 0
+ /* This causes an assertion in later LLVM versions */
LLVMSetVisibility (method, LLVMHiddenVisibility);
+#endif
} else {
LLVMSetLinkage (method, LLVMPrivateLinkage);
}
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);
}
//LLVMVerifyFunction(method, 0);
} else {
- mono_llvm_optimize_method (method);
+ mono_llvm_optimize_method (ctx->lmodule->mono_ee, method);
if (cfg->verbose_level > 1)
mono_llvm_dump_value (method);
- cfg->native_code = LLVMGetPointerToGlobal (ee, method);
+ cfg->native_code = LLVMGetPointerToGlobal (ctx->lmodule->ee, method);
/* Set by emit_cb */
g_assert (cfg->code_len);
case LLVMArgInIReg:
case LLVMArgInFPReg: {
MonoType *t = (sig->hasthis && i == 0) ? &mono_get_intptr_class ()->byval_arg : sig->params [i - sig->hasthis];
+ int opcode;
- if (!t->byref && (t->type == MONO_TYPE_R8 || t->type == MONO_TYPE_R4)) {
+ opcode = mono_type_to_regmove (cfg, t);
+ if (opcode == OP_FMOVE) {
MONO_INST_NEW (cfg, ins, OP_FMOVE);
ins->dreg = mono_alloc_freg (cfg);
+ } else if (opcode == OP_LMOVE) {
+ MONO_INST_NEW (cfg, ins, OP_LMOVE);
+ ins->dreg = mono_alloc_lreg (cfg);
} else {
MONO_INST_NEW (cfg, ins, OP_MOVE);
ins->dreg = mono_alloc_ireg (cfg);
g_assert (current);
err = mono_dl_symbol (current, name, symbol);
+
+ mono_dl_close (current);
}
#ifdef MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK
*symbol = (char*)mono_arch_create_llvm_native_thunk (mono_domain_get (), (guint8*)(*symbol));
}
static void
-init_jit_module (void)
+init_jit_module (MonoDomain *domain)
{
MonoJitICallInfo *info;
+ MonoJitDomainInfo *dinfo;
+ MonoLLVMModule *module;
+ char *name;
- if (jit_module_inited)
+ dinfo = domain_jit_info (domain);
+ if (dinfo->llvm_module)
return;
mono_loader_lock ();
- if (jit_module_inited) {
+ if (dinfo->llvm_module) {
mono_loader_unlock ();
return;
}
- jit_module.module = LLVMModuleCreateWithName ("mono");
+ module = g_new0 (MonoLLVMModule, 1);
+
+ name = g_strdup_printf ("mono-%s", domain->friendly_name);
+ module->module = LLVMModuleCreateWithName (name);
- ee = mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (jit_module.module), alloc_cb, emitted_cb, exception_cb, dlsym_cb);
+ module->mono_ee = mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (module->module), alloc_cb, emitted_cb, exception_cb, dlsym_cb, &module->ee);
- add_intrinsics (jit_module.module);
- add_types (&jit_module);
+ add_intrinsics (module->module);
+ add_types (module);
- jit_module.llvm_types = g_hash_table_new (NULL, NULL);
+ module->llvm_types = g_hash_table_new (NULL, NULL);
info = mono_find_jit_icall_by_name ("llvm_resume_unwind_trampoline");
g_assert (info);
- LLVMAddGlobalMapping (ee, LLVMGetNamedFunction (jit_module.module, "llvm_resume_unwind_trampoline"), (void*)info->func);
+ LLVMAddGlobalMapping (module->ee, LLVMGetNamedFunction (module->module, "llvm_resume_unwind_trampoline"), (void*)info->func);
- jit_module_inited = TRUE;
+ mono_memory_barrier ();
+
+ dinfo->llvm_module = module;
mono_loader_unlock ();
}
void
mono_llvm_cleanup (void)
{
- if (ee)
- mono_llvm_dispose_ee (ee);
-
- if (jit_module.llvm_types)
- g_hash_table_destroy (jit_module.llvm_types);
-
if (aot_module.module)
LLVMDisposeModule (aot_module.module);
LLVMContextDispose (LLVMGetGlobalContext ());
}
+void
+mono_llvm_free_domain_info (MonoDomain *domain)
+{
+ MonoJitDomainInfo *info = domain_jit_info (domain);
+ MonoLLVMModule *module = info->llvm_module;
+ int i;
+
+ if (!module)
+ return;
+
+ if (module->llvm_types)
+ g_hash_table_destroy (module->llvm_types);
+
+ mono_llvm_dispose_ee (module->mono_ee);
+
+ if (module->bb_names) {
+ for (i = 0; i < module->bb_names_len; ++i)
+ g_free (module->bb_names [i]);
+ g_free (module->bb_names);
+ }
+ //LLVMDisposeModule (module->module);
+
+ g_free (module);
+
+ info->llvm_module = NULL;
+}
+
void
mono_llvm_create_aot_module (const char *got_symbol)
{