2010-06-18 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Fri, 18 Jun 2010 20:51:35 +0000 (20:51 -0000)
committerZoltan Varga <vargaz@gmail.com>
Fri, 18 Jun 2010 20:51:35 +0000 (20:51 -0000)
* 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

mono/mini/ChangeLog
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/mini-llvm.c

index 469d0b0de8d4cc7bf88277035785d797876bf8b8..0bfaf8e27d2636fa12eb465ef13c0abe66bd739c 100755 (executable)
@@ -1,5 +1,10 @@
 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.
 
@@ -10,7 +15,7 @@
 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>
index 93f09007666425b33bbce7706bfd1f69a9c32606..9356c213d955c8c1aaa7d711226e9b853a0919af 100644 (file)
@@ -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);
index 3c2fa2993687179c25a5175018968e8e7837af0e..393e92b38606dded08e428e8d6500a09a68a1ba3 100644 (file)
@@ -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);
index 46f8e329ebcb449678a3c35a8d5160a6b8d3de2c..684f743d04adedfa290dbde122fe75f83593eed8 100644 (file)
@@ -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);