* aot-compiler.c aot-runtime.c: Fix LLVM support.
* mini-llvm.c: When emitting OP_CALL_HANDLER, avoid branching directly to the landing
pad, branch to a new bblock instead.
svn path=/trunk/mono/; revision=159154
2010-06-18 Zoltan Varga <vargaz@gmail.com>
+ * aot-compiler.c aot-runtime.c: Fix LLVM support.
+
+ * mini-llvm.c: When emitting OP_CALL_HANDLER, avoid branching directly to the landing
+ pad, branch to a new bblock instead.
+
* aot-compiler.c (emit_method_code): Use cfg->header instead of the header of
orig_method.
2010-06-17 Geoff Norton <gnorton@novell.com>
* mini-arm.h:
- * exceptions-arm.c: Move the UCONTEXT macros to mono-sigcontext.h so they
+ * exceptions-arm.c: Move the UCONTEXT macros to mono-sigcontext.h so they
can be used by sgen.
2010-06-17 Zoltan Varga <vargaz@gmail.com>
method = cfg->orig_method;
code = cfg->native_code;
- header = mono_method_get_header (method);
+ header = cfg->header;
method_index = get_method_index (acfg, method);
/* Exception table */
if (cfg->compile_llvm) {
+ /*
+ * When using LLVM, we can't emit some data, like pc offsets, this reg/offset etc.,
+ * since the information is only available to llc. Instead, we let llc save the data
+ * into the LSDA, and read it from there at runtime.
+ */
/* The assembly might be CIL stripped so emit the data ourselves */
if (header->num_clauses)
encode_value (header->num_clauses, p, &p);
if (jinfo->has_generic_jit_info) {
MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (jinfo);
- encode_value (gi->has_this ? 1 : 0, p, &p);
- encode_value (gi->this_reg, p, &p);
- encode_value (gi->this_offset, p, &p);
+ if (!cfg->compile_llvm) {
+ encode_value (gi->has_this ? 1 : 0, p, &p);
+ encode_value (gi->this_reg, p, &p);
+ encode_value (gi->this_offset, p, &p);
+ }
/*
* Need to encode jinfo->method too, since it is not equal to 'method'
* a lot of time, and doesn't seem to save much space.
* The following optimizations cannot be enabled:
* - 'tailcallelim'
+ * - 'jump-threading' changes our blockaddress references to int constants.
* The opt list below was produced by taking the output of:
* llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
* then removing tailcallelim + the global opts, and adding a second gvn.
*/
opts = g_strdup ("-instcombine -simplifycfg");
- opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -jump-threading -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -jump-threading -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify");
+ opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -prune-eh -inline -functionattrs -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify");
#if 1
command = g_strdup_printf ("opt -f %s -o temp.opt.bc temp.bc", opts);
printf ("Executing opt: %s\n", command);
static G_GNUC_UNUSED MonoJitInfo*
decode_eh_frame (MonoAotModule *amodule, MonoDomain *domain,
MonoMethod *method, guint8 *code, MonoJitInfo *orig_jinfo,
- int extra_size)
+ int extra_size, int *this_reg, int *this_offset)
{
eh_frame_hdr *hdr;
guint8 *p;
guint32 eh_frame_ptr;
int fde_count;
gint32 *table;
- int i, pos, left, right, offset, offset1, offset2, this_reg, this_offset;
+ int i, pos, left, right, offset, offset1, offset2;
guint32 unw_len, code_len;
MonoJitExceptionInfo *ei;
guint32 ei_len;
eh_frame = amodule->eh_frame_hdr + table [(pos * 2) + 1];
- unwind_info = mono_unwind_decode_fde (eh_frame, &unw_len, &code_len, &ei, &ei_len, &type_info, &this_reg, &this_offset);
+ unwind_info = mono_unwind_decode_fde (eh_frame, &unw_len, &code_len, &ei, &ei_len, &type_info, this_reg, this_offset);
/*
* LLVM might represent one IL region with multiple regions, so have to
gboolean has_generic_jit_info, has_dwarf_unwind_info, has_clauses, has_seq_points, has_try_block_holes;
gboolean from_llvm;
guint8 *p;
- int generic_info_size, try_holes_info_size, num_holes;
+ int generic_info_size, try_holes_info_size, num_holes, this_reg, this_offset;
/* Load the method info from the AOT file */
if (from_llvm) {
/* LLVM compiled method */
/* The info is in the .eh_frame section */
- jinfo = decode_eh_frame (amodule, domain, method, code, jinfo, generic_info_size);
+ jinfo = decode_eh_frame (amodule, domain, method, code, jinfo, generic_info_size, &this_reg, &this_offset);
jinfo->from_llvm = 1;
} else {
jinfo->code_size = code_len;
gi = mono_jit_info_get_generic_jit_info (jinfo);
g_assert (gi);
- gi->has_this = decode_value (p, &p);
- gi->this_reg = decode_value (p, &p);
- gi->this_offset = decode_value (p, &p);
+ if (from_llvm) {
+ gi->has_this = this_reg != -1;
+ gi->this_reg = this_reg;
+ gi->this_offset = this_offset;
+ } else {
+ gi->has_this = decode_value (p, &p);
+ gi->this_reg = decode_value (p, &p);
+ gi->this_offset = decode_value (p, &p);
+ }
/* This currently contains no data */
gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
* needs to branch to in ENDFINALLY.
*/
GSList *call_handler_return_bbs;
+ /*
+ * If this bblock is the start of a finally clause, this is the bblock that
+ * CALL_HANDLER needs to branch to.
+ */
+ LLVMBasicBlockRef call_handler_target_bb;
/* The list of switch statements generated by ENDFINALLY instructions */
GSList *endfinally_switch_ins_list;
GSList *phi_nodes;
if (bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER))
g_hash_table_insert (ctx->region_to_handler, GUINT_TO_POINTER (mono_get_block_region_notry (cfg, bb->region)), bb);
if (bb->region != -1 && (bb->flags & BB_EXCEPTION_HANDLER) && bb->in_scount == 0) {
- LLVMValueRef val = LLVMBuildAlloca (builder, LLVMInt32Type (), "");
+ char name [128];
+ LLVMValueRef val;
+
+ sprintf (name, "finally_ind_bb%d", bb->block_num);
+ val = LLVMBuildAlloca (builder, LLVMInt32Type (), name);
LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), 0, FALSE), val);
ctx->bblocks [bb->block_num].finally_ind = val;
+
+ /*
+ * Create a new bblock which CALL_HANDLER can branch to, because branching to the
+ * LLVM bblock containing the call to llvm.eh.selector causes problems for the
+ * LLVM optimizer passes.
+ */
+ sprintf (name, "BB_%d_CALL_HANDLER_TARGET", bb->block_num);
+ ctx->bblocks [bb->block_num].call_handler_target_bb = LLVMAppendBasicBlock (ctx->lmethod, name);
}
}
if (bb->flags & BB_EXCEPTION_HANDLER) {
LLVMTypeRef i8ptr;
LLVMValueRef eh_selector, eh_exception, personality, args [4];
+ LLVMBasicBlockRef target_bb;
MonoInst *exvar;
static gint32 mapping_inited;
static int ti_generator;
* Enabling this causes llc to crash:
* http://llvm.org/bugs/show_bug.cgi?id=6102
*/
- LLVM_FAILURE (ctx, "aot+clauses");
+ //LLVM_FAILURE (ctx, "aot+clauses");
} else {
/* exception_cb will decode this */
ti = g_malloc (sizeof (gint32));
values [exvar->dreg] = LLVMBuildCall (builder, eh_exception, NULL, 0, "");
emit_volatile_store (ctx, exvar->dreg);
}
+
+ /* Start a new bblock which CALL_HANDLER can branch to */
+ target_bb = bblocks [bb->block_num].call_handler_target_bb;
+ if (target_bb) {
+ LLVMBuildBr (builder, target_bb);
+
+ ctx->builder = builder = create_builder (ctx);
+ LLVMPositionBuilderAtEnd (ctx->builder, target_bb);
+
+ ctx->bblocks [bb->block_num].end_bblock = target_bb;
+ }
}
has_terminator = FALSE;
* We don't 'call' handlers, but instead simply branch to them.
* The code generated by ENDFINALLY will branch back to us.
*/
- LLVMBasicBlockRef finally_bb, noex_bb;
+ LLVMBasicBlockRef noex_bb;
GSList *bb_list;
BBInfo *info = &bblocks [ins->inst_target_bb->block_num];
- finally_bb = get_bb (ctx, ins->inst_target_bb);
-
bb_list = info->call_handler_return_bbs;
/*
LLVMBuildStore (builder, LLVMConstInt (LLVMInt32Type (), g_slist_length (bb_list) + 1, FALSE), lhs);
/* Branch to the finally clause */
- LLVMBuildBr (builder, finally_bb);
+ LLVMBuildBr (builder, info->call_handler_target_bb);
noex_bb = gen_bb (ctx, "CALL_HANDLER_CONT_BB");
info->call_handler_return_bbs = g_slist_append_mempool (cfg->mempool, info->call_handler_return_bbs, noex_bb);