clause = get_most_deep_clause (cfg, ctx, bb);
if (clause) {
- g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+ g_assert (clause->flags == MONO_EXCEPTION_CLAUSE_NONE || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT);
/*
* Have to use an invoke instead of a call, branching to the
* handler bblock of the clause containing this bblock.
*/
- g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY);
+ g_assert (ec->flags == MONO_EXCEPTION_CLAUSE_NONE || ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY || ec->flags == MONO_EXCEPTION_CLAUSE_FAULT);
tblock = cfg->cil_offset_to_bb [ec->handler_offset];
g_assert (tblock);
func = LLVMAddFunction (lmodule, module->get_method_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
LLVMSetLinkage (func, LLVMExternalLinkage);
LLVMSetVisibility (func, LLVMHiddenVisibility);
- LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+ mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
module->get_method = func;
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
LLVMSetLinkage (func, LLVMExternalLinkage);
LLVMSetVisibility (func, LLVMHiddenVisibility);
- LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+ mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
module->get_unbox_tramp = func;
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
func = LLVMAddFunction (lmodule, "llvm_code_start", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
LLVMSetLinkage (func, LLVMInternalLinkage);
- LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+ mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
module->code_start = func;
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
builder = LLVMCreateBuilder ();
g_assert_not_reached ();
}
LLVMSetLinkage (func, LLVMInternalLinkage);
- LLVMAddFunctionAttr (func, LLVMNoInlineAttribute);
+ mono_llvm_add_func_attr (func, LLVM_ATTR_NO_INLINE);
mono_llvm_set_preserveall_cc (func);
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
builder = LLVMCreateBuilder ();
func = LLVMAddFunction (lmodule, "llvm_code_end", LLVMFunctionType (LLVMVoidType (), NULL, 0, FALSE));
LLVMSetLinkage (func, LLVMInternalLinkage);
- LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
+ mono_llvm_add_func_attr (func, LLVM_ATTR_NO_UNWIND);
module->code_end = func;
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
builder = LLVMCreateBuilder ();
tramp_name = g_strdup_printf ("ut_%s", method_name);
tramp = LLVMAddFunction (ctx->module->lmodule, tramp_name, method_type);
LLVMSetLinkage (tramp, LLVMInternalLinkage);
- LLVMAddFunctionAttr (tramp, LLVMOptimizeForSizeAttribute);
- //LLVMAddFunctionAttr (tramp, LLVMNoUnwindAttribute);
+ mono_llvm_add_func_attr (tramp, LLVM_ATTR_OPTIMIZE_FOR_SIZE);
+ //mono_llvm_add_func_attr (tramp, LLVM_ATTR_NO_UNWIND);
linfo = ctx->linfo;
// FIXME: Reduce code duplication with mono_llvm_compile_method () etc.
if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
- LLVMAddAttribute (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVMInRegAttribute);
+ mono_llvm_add_param_attr (LLVMGetParam (tramp, ctx->rgctx_arg_pindex), LLVM_ATTR_IN_REG);
if (ctx->cfg->vret_addr) {
LLVMSetValueName (LLVMGetParam (tramp, linfo->vret_arg_pindex), "vret");
if (linfo->ret.storage == LLVMArgVtypeByRef) {
- LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMStructRetAttribute);
- LLVMAddAttribute (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
+ mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
+ mono_llvm_add_param_attr (LLVMGetParam (tramp, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
}
}
}
call = LLVMBuildCall (builder, method, args, nargs, "");
if (!ctx->llvm_only && ctx->rgctx_arg_pindex != -1)
- LLVMAddInstrAttribute (call, 1 + ctx->rgctx_arg_pindex, LLVMInRegAttribute);
+ mono_llvm_add_instr_attr (call, 1 + ctx->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
if (linfo->ret.storage == LLVMArgVtypeByRef)
- LLVMAddInstrAttribute (call, 1 + linfo->vret_arg_pindex, LLVMStructRetAttribute);
+ mono_llvm_add_instr_attr (call, 1 + linfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
// FIXME: This causes assertions in clang
//mono_llvm_set_must_tail (call);
mono_llvm_set_call_preserveall_cc (lcall);
if (cinfo->ret.storage == LLVMArgVtypeByRef)
- LLVMAddInstrAttribute (lcall, 1 + cinfo->vret_arg_pindex, LLVMStructRetAttribute);
+ mono_llvm_add_instr_attr (lcall, 1 + cinfo->vret_arg_pindex, LLVM_ATTR_STRUCT_RET);
if (!ctx->llvm_only && call->rgctx_arg_reg)
- LLVMAddInstrAttribute (lcall, 1 + cinfo->rgctx_arg_pindex, LLVMInRegAttribute);
+ mono_llvm_add_instr_attr (lcall, 1 + cinfo->rgctx_arg_pindex, LLVM_ATTR_IN_REG);
if (call->imt_arg_reg)
- LLVMAddInstrAttribute (lcall, 1 + cinfo->imt_arg_pindex, LLVMInRegAttribute);
+ mono_llvm_add_instr_attr (lcall, 1 + cinfo->imt_arg_pindex, LLVM_ATTR_IN_REG);
/* Add byval attributes if needed */
for (i = 0; i < sig->param_count; ++i) {
LLVMArgInfo *ainfo = &call->cinfo->args [i + sig->hasthis];
if (ainfo && ainfo->storage == LLVMArgVtypeByVal)
- LLVMAddInstrAttribute (lcall, 1 + ainfo->pindex, LLVMByValAttribute);
+ mono_llvm_add_instr_attr (lcall, 1 + ainfo->pindex, LLVM_ATTR_BY_VAL);
}
/*
MonoExceptionClause *group_cursor = group_start;
for (int i = 0; i < group_size; i ++) {
- if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY))
+ if (!(group_cursor->flags & MONO_EXCEPTION_CLAUSE_FINALLY || group_cursor->flags & MONO_EXCEPTION_CLAUSE_FAULT))
finally_only = FALSE;
group_cursor++;
MonoExceptionClause *clause = &ctx->cfg->header->clauses [clause_index];
// Make exception available to catch blocks
- if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
+ if (!(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
LLVMValueRef mono_exc = mono_llvm_emit_load_exception_call (ctx, ctx->builder);
g_assert (ctx->ex_var);
g_assert (personality);
} else {
#if LLVM_API_VERSION > 100
- personality = ctx->module->personality;
- if (!personality) {
- LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
- personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
- LLVMAddFunctionAttr (personality, LLVMNoUnwindAttribute);
- LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
- LLVMBuilderRef builder2 = LLVMCreateBuilder ();
- LLVMPositionBuilderAtEnd (builder2, entry_bb);
- LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
- ctx->module->personality = personality;
- LLVMDisposeBuilder (builder2);
- }
+ /* Can't cache this as each method is in its own llvm module */
+ LLVMTypeRef personality_type = LLVMFunctionType (LLVMInt32Type (), NULL, 0, TRUE);
+ personality = LLVMAddFunction (ctx->lmodule, "mono_personality", personality_type);
+ mono_llvm_add_func_attr (personality, LLVM_ATTR_NO_UNWIND);
+ LLVMBasicBlockRef entry_bb = LLVMAppendBasicBlock (personality, "ENTRY");
+ LLVMBuilderRef builder2 = LLVMCreateBuilder ();
+ LLVMPositionBuilderAtEnd (builder2, entry_bb);
+ LLVMBuildRet (builder2, LLVMConstInt (LLVMInt32Type (), 0, FALSE));
+ LLVMDisposeBuilder (builder2);
#else
static gint32 mapping_inited;
}
/* Start a new bblock which CALL_HANDLER can branch to */
- target_bb = bblocks [bb->block_num].call_handler_target_bb;
- if (target_bb) {
- ctx->builder = builder = create_builder (ctx);
- LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
+ ctx->builder = builder = create_builder (ctx);
+ LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
- ctx->bblocks [bb->block_num].end_bblock = target_bb;
+ ctx->bblocks [bb->block_num].end_bblock = target_bb;
- /* Store the exception into the IL level exvar */
- if (bb->in_scount == 1) {
- g_assert (bb->in_scount == 1);
- exvar = bb->in_stack [0];
+ /* Store the exception into the IL level exvar */
+ if (bb->in_scount == 1) {
+ g_assert (bb->in_scount == 1);
+ exvar = bb->in_stack [0];
- // FIXME: This is shared with filter clauses ?
- g_assert (!values [exvar->dreg]);
+ // FIXME: This is shared with filter clauses ?
+ g_assert (!values [exvar->dreg]);
- g_assert (ctx->ex_var);
- values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
- emit_volatile_store (ctx, exvar->dreg);
- }
+ g_assert (ctx->ex_var);
+ values [exvar->dreg] = LLVMBuildLoad (builder, ctx->ex_var, "");
+ emit_volatile_store (ctx, exvar->dreg);
}
+
+ /* Make normal branches to the start of the clause branch to the new bblock */
+ bblocks [bb->block_num].bblock = target_bb;
}
static void
args [0] = lhs;
args [1] = rhs;
/* 0xf1 == multiply all 4 elements, add them together, and store the result to the lowest element */
+#if LLVM_API_VERSION >= 500
+ args [2] = LLVMConstInt (LLVMInt8Type (), 0xf1, FALSE);
+#else
args [2] = LLVMConstInt (LLVMInt32Type (), 0xf1, FALSE);
+#endif
values [ins->dreg] = LLVMBuildCall (builder, get_intrinsic (ctx, simd_op_to_intrins (ins->opcode)), args, 3, dname);
break;
LLVMValueRef val, switch_ins, callee;
GSList *bb_list;
BBInfo *info;
+ gboolean is_fault = MONO_REGION_FLAGS (bb->region) == MONO_EXCEPTION_CLAUSE_FAULT;
- handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
- g_assert (handler_bb);
- info = &bblocks [handler_bb->block_num];
- lhs = info->finally_ind;
- g_assert (lhs);
+ /*
+ * Fault clauses are like finally clauses, but they are only called if an exception is thrown.
+ */
+ if (!is_fault) {
+ handler_bb = (MonoBasicBlock*)g_hash_table_lookup (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)));
+ g_assert (handler_bb);
+ info = &bblocks [handler_bb->block_num];
+ lhs = info->finally_ind;
+ g_assert (lhs);
- bb_list = info->call_handler_return_bbs;
+ bb_list = info->call_handler_return_bbs;
- resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
+ resume_bb = gen_bb (ctx, "ENDFINALLY_RESUME_BB");
- /* Load the finally variable */
- val = LLVMBuildLoad (builder, lhs, "");
+ /* Load the finally variable */
+ val = LLVMBuildLoad (builder, lhs, "");
- /* Reset the variable */
- LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
+ /* Reset the variable */
+ LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), lhs);
- /* Branch to either resume_bb, or to the bblocks in bb_list */
- switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
- /*
- * The other targets are added at the end to handle OP_CALL_HANDLER
- * opcodes processed later.
- */
- info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
+ /* Branch to either resume_bb, or to the bblocks in bb_list */
+ switch_ins = LLVMBuildSwitch (builder, val, resume_bb, g_slist_length (bb_list));
+ /*
+ * The other targets are added at the end to handle OP_CALL_HANDLER
+ * opcodes processed later.
+ */
+ info->endfinally_switch_ins_list = g_slist_append_mempool (cfg->mempool, info->endfinally_switch_ins_list, switch_ins);
- builder = ctx->builder = create_builder (ctx);
- LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+ builder = ctx->builder = create_builder (ctx);
+ LLVMPositionBuilderAtEnd (ctx->builder, resume_bb);
+ }
if (ctx->llvm_only) {
emit_resume_eh (ctx, bb);
if (cfg->compile_aot)
ctx->lmodule = ctx->module->lmodule;
else
- ctx->lmodule = LLVMModuleCreateWithName ("jit-module");
+ ctx->lmodule = LLVMModuleCreateWithName (g_strdup_printf ("jit-module-%s", cfg->method->name));
#else
ctx->lmodule = ctx->module->lmodule;
#endif
LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
LLVMSetLinkage (method, LLVMPrivateLinkage);
- LLVMAddFunctionAttr (method, LLVMUWTable);
+ mono_llvm_add_func_attr (method, LLVM_ATTR_UW_TABLE);
if (cfg->compile_aot) {
LLVMSetLinkage (method, LLVMInternalLinkage);
header = cfg->header;
for (i = 0; i < header->num_clauses; ++i) {
clause = &header->clauses [i];
- if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
- set_failure (ctx, "non-finally/catch clause.");
+ if (clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FAULT && clause->flags != MONO_EXCEPTION_CLAUSE_NONE) {
+ set_failure (ctx, "non-finally/catch/fault clause.");
return;
}
}
if (header->num_clauses || (cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) || cfg->no_inline)
/* We can't handle inlined methods with clauses */
- LLVMAddFunctionAttr (method, LLVMNoInlineAttribute);
+ mono_llvm_add_func_attr (method, LLVM_ATTR_NO_INLINE);
if (linfo->rgctx_arg) {
ctx->rgctx_arg = LLVMGetParam (method, linfo->rgctx_arg_pindex);
* CC_X86_64_Mono in X86CallingConv.td.
*/
if (!ctx->llvm_only)
- LLVMAddAttribute (ctx->rgctx_arg, LLVMInRegAttribute);
+ mono_llvm_add_param_attr (ctx->rgctx_arg, LLVM_ATTR_IN_REG);
LLVMSetValueName (ctx->rgctx_arg, "rgctx");
} else {
ctx->rgctx_arg_pindex = -1;
values [cfg->vret_addr->dreg] = LLVMGetParam (method, linfo->vret_arg_pindex);
LLVMSetValueName (values [cfg->vret_addr->dreg], "vret");
if (linfo->ret.storage == LLVMArgVtypeByRef) {
- LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMStructRetAttribute);
- LLVMAddAttribute (LLVMGetParam (method, linfo->vret_arg_pindex), LLVMNoAliasAttribute);
+ mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_STRUCT_RET);
+ mono_llvm_add_param_attr (LLVMGetParam (method, linfo->vret_arg_pindex), LLVM_ATTR_NO_ALIAS);
}
}
LLVMSetValueName (values [cfg->args [i + sig->hasthis]->dreg], name);
g_free (name);
if (ainfo->storage == LLVMArgVtypeByVal)
- LLVMAddAttribute (LLVMGetParam (method, pindex), LLVMByValAttribute);
+ mono_llvm_add_param_attr (LLVMGetParam (method, pindex), LLVM_ATTR_BY_VAL);
if (ainfo->storage == LLVMArgVtypeByRef) {
/* For OP_LDADDR */
}
}
- /*
- * The INDIRECT flag added by OP_LDADDR inhibits optimizations, even if the LDADDR
- * was later optimized away, so clear these flags, and add them back for the still
- * present OP_LDADDR instructions.
- */
- for (i = 0; i < cfg->next_vreg; ++i) {
- MonoInst *ins;
-
- ins = get_vreg_to_inst (cfg, i);
- if (ins && ins != cfg->rgctx_var)
- ins->flags &= ~MONO_INST_INDIRECT;
- }
-
/*
* Make a first pass over the code to precreate PHI nodes/set INDIRECT flags.
*/
ret_type = type_to_simd_type (MONO_TYPE_R4);
arg_types [0] = type_to_simd_type (MONO_TYPE_R4);
arg_types [1] = type_to_simd_type (MONO_TYPE_R4);
+#if LLVM_API_VERSION >= 500
+ arg_types [2] = LLVMInt8Type ();
+#else
arg_types [2] = LLVMInt32Type ();
+#endif
AddFunc (module, name, ret_type, arg_types, 3);
break;
#endif
}
void
-mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
+mono_llvm_create_aot_module (MonoAssembly *assembly, const char *global_prefix, int initial_got_size, gboolean emit_dwarf, gboolean static_link, gboolean llvm_only)
{
MonoLLVMModule *module = &aot_module;
module->static_link = static_link;
module->llvm_only = llvm_only;
/* The first few entries are reserved */
- module->max_got_offset = 16;
+ module->max_got_offset = initial_got_size;
module->context = LLVMGetGlobalContext ();
if (llvm_only)
LLVMSetVisibility (d, LLVMHiddenVisibility);
LLVMSetLinkage (d, LLVMInternalLinkage);
LLVMSetInitializer (d, mono_llvm_create_constant_data_array (data, data_len));
+ LLVMSetAlignment (d, 8);
mono_llvm_set_is_constant (d);
}
The mono JIT uses pointer sized iregs/double fregs, while LLVM uses precisely
typed registers, so we have to keep track of the precise LLVM type of each vreg.
This is made easier because the IR is already in SSA form.
- An additional problem is that our IR is not consistent with types, i.e. i32/ia64
+ An additional problem is that our IR is not consistent with types, i.e. i32/i64
types are frequently used incorrectly.
*/