From a1bb6bde4f5867f5aee106aa0102157ef0829f11 Mon Sep 17 00:00:00 2001 From: zoltan Date: Fri, 18 Jun 2010 20:51:35 +0000 Subject: [PATCH] 2010-06-18 Zoltan Varga * 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. git-svn-id: svn+ssh://mono-cvs.ximian.com/source/trunk/mono@159154 e3ebcda4-bce8-0310-ba0a-eca2169e7518 --- mono/mini/ChangeLog | 7 ++++++- mono/mini/aot-compiler.c | 18 +++++++++++++----- mono/mini/aot-runtime.c | 22 ++++++++++++++-------- mono/mini/mini-llvm.c | 39 +++++++++++++++++++++++++++++++++------ 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index 469d0b0de..0bfaf8e27 100755 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,5 +1,10 @@ 2010-06-18 Zoltan Varga + * 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. @@ -10,7 +15,7 @@ 2010-06-17 Geoff Norton * 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 diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 93f090076..9356c213d 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -3416,7 +3416,7 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) method = cfg->orig_method; code = cfg->native_code; - header = mono_method_get_header (method); + header = cfg->header; method_index = get_method_index (acfg, method); @@ -3463,6 +3463,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) /* 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); @@ -3510,9 +3515,11 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg) 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' @@ -4686,12 +4693,13 @@ emit_llvm_file (MonoAotCompile *acfg) * 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); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 3c2fa2993..393e92b38 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1515,7 +1515,7 @@ typedef struct 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; @@ -1523,7 +1523,7 @@ decode_eh_frame (MonoAotModule *amodule, MonoDomain *domain, 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; @@ -1575,7 +1575,7 @@ decode_eh_frame (MonoAotModule *amodule, MonoDomain *domain, 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 @@ -1633,7 +1633,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, 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 */ @@ -1708,7 +1708,7 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, 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; @@ -1727,9 +1727,15 @@ decode_exception_debug_info (MonoAotModule *amodule, MonoDomain *domain, 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); diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 46f8e329e..684f743d0 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -46,6 +46,11 @@ typedef struct { * 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; @@ -1562,10 +1567,22 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) 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); } } @@ -1903,6 +1920,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) 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; @@ -1953,7 +1971,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) * 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)); @@ -1981,6 +1999,17 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) 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; @@ -3415,12 +3444,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) * 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; /* @@ -3431,7 +3458,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) 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); -- 2.11.4.GIT