OSDN Git Service

* config/mips/mips.md (*extenddi_truncate<mode>,
[pf3gnuchains/gcc-fork.git] / gcc / except.c
index 0e207d5..06e5529 100644 (file)
@@ -440,12 +440,16 @@ void
 expand_resx_expr (tree exp)
 {
   int region_nr = TREE_INT_CST_LOW (TREE_OPERAND (exp, 0));
+  rtx insn;
   struct eh_region_d *reg = VEC_index (eh_region,
                                       cfun->eh->region_array, region_nr);
 
-  gcc_assert (!reg->resume);
   do_pending_stack_adjust ();
-  reg->resume = emit_jump_insn (gen_rtx_RESX (VOIDmode, region_nr));
+  insn = emit_jump_insn (gen_rtx_RESX (VOIDmode, region_nr));
+  if (reg->resume)
+    reg->resume = gen_rtx_INSN_LIST (VOIDmode, insn, reg->resume);
+  else
+    reg->resume = insn;
   emit_barrier ();
 }
 
@@ -565,7 +569,7 @@ can_be_reached_by_runtime (sbitmap contains_stmt, struct eh_region_d *r)
       if (i->type != ERT_MUST_NOT_THROW)
        {
          bool found = TEST_BIT (contains_stmt, i->region_number);
-         if (!found)
+         if (!found && i->aka)
            EXECUTE_IF_SET_IN_BITMAP (i->aka, 0, n, bi)
              if (TEST_BIT (contains_stmt, n))
              {
@@ -2012,6 +2016,7 @@ build_post_landing_pads (void)
          /* We delay the generation of the _Unwind_Resume until we generate
             landing pads.  We emit a marker here so as to get good control
             flow data in the meantime.  */
+         gcc_assert (!region->resume);
          region->resume
            = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
          emit_barrier ();
@@ -2040,6 +2045,7 @@ build_post_landing_pads (void)
          /* We delay the generation of the _Unwind_Resume until we generate
             landing pads.  We emit a marker here so as to get good control
             flow data in the meantime.  */
+         gcc_assert (!region->resume);
          region->resume
            = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
          emit_barrier ();
@@ -2080,6 +2086,7 @@ connect_post_landing_pads (void)
       struct eh_region_d *outer;
       rtx seq;
       rtx barrier;
+      rtx resume_list;
 
       region = VEC_index (eh_region, cfun->eh->region_array, i);
       /* Mind we don't process a region more than once.  */
@@ -2088,7 +2095,7 @@ connect_post_landing_pads (void)
 
       /* If there is no RESX, or it has been deleted by flow, there's
         nothing to fix up.  */
-      if (! region->resume || INSN_DELETED_P (region->resume))
+      if (! region->resume)
        continue;
 
       /* Search for another landing pad in this function.  */
@@ -2096,46 +2103,55 @@ connect_post_landing_pads (void)
        if (outer->post_landing_pad)
          break;
 
-      start_sequence ();
-
-      if (outer)
+      for (resume_list = region->resume; resume_list;
+          resume_list = (GET_CODE (resume_list) == INSN_LIST
+                         ? XEXP (resume_list, 1) : NULL_RTX))
        {
-         edge e;
-         basic_block src, dest;
-
-         emit_jump (outer->post_landing_pad);
-         src = BLOCK_FOR_INSN (region->resume);
-         dest = BLOCK_FOR_INSN (outer->post_landing_pad);
-         while (EDGE_COUNT (src->succs) > 0)
-           remove_edge (EDGE_SUCC (src, 0));
-         e = make_edge (src, dest, 0);
-         e->probability = REG_BR_PROB_BASE;
-         e->count = src->count;
-       }
-      else
-       {
-         emit_library_call (unwind_resume_libfunc, LCT_THROW,
-                            VOIDmode, 1, crtl->eh.exc_ptr, ptr_mode);
-
-         /* What we just emitted was a throwing libcall, so it got a
-            barrier automatically added after it.  If the last insn in
-            the libcall sequence isn't the barrier, it's because the
-            target emits multiple insns for a call, and there are insns
-            after the actual call insn (which are redundant and would be
-            optimized away).  The barrier is inserted exactly after the
-            call insn, so let's go get that and delete the insns after
-            it, because below we need the barrier to be the last insn in
-            the sequence.  */
-         delete_insns_since (NEXT_INSN (last_call_insn ()));
-       }
+         rtx resume = (GET_CODE (resume_list) == INSN_LIST
+                       ? XEXP (resume_list, 0) : resume_list);
+          if (INSN_DELETED_P (resume))
+           continue;
+         start_sequence ();
 
-      seq = get_insns ();
-      end_sequence ();
-      barrier = emit_insn_before (seq, region->resume);
-      /* Avoid duplicate barrier.  */
-      gcc_assert (BARRIER_P (barrier));
-      delete_insn (barrier);
-      delete_insn (region->resume);
+         if (outer)
+           {
+             edge e;
+             basic_block src, dest;
+
+             emit_jump (outer->post_landing_pad);
+             src = BLOCK_FOR_INSN (resume);
+             dest = BLOCK_FOR_INSN (outer->post_landing_pad);
+             while (EDGE_COUNT (src->succs) > 0)
+               remove_edge (EDGE_SUCC (src, 0));
+             e = make_edge (src, dest, 0);
+             e->probability = REG_BR_PROB_BASE;
+             e->count = src->count;
+           }
+         else
+           {
+             emit_library_call (unwind_resume_libfunc, LCT_THROW,
+                                VOIDmode, 1, crtl->eh.exc_ptr, ptr_mode);
+
+             /* What we just emitted was a throwing libcall, so it got a
+                barrier automatically added after it.  If the last insn in
+                the libcall sequence isn't the barrier, it's because the
+                target emits multiple insns for a call, and there are insns
+                after the actual call insn (which are redundant and would be
+                optimized away).  The barrier is inserted exactly after the
+                call insn, so let's go get that and delete the insns after
+                it, because below we need the barrier to be the last insn in
+                the sequence.  */
+             delete_insns_since (NEXT_INSN (last_call_insn ()));
+           }
+
+         seq = get_insns ();
+         end_sequence ();
+         barrier = emit_insn_before (seq, resume);
+         /* Avoid duplicate barrier.  */
+         gcc_assert (BARRIER_P (barrier));
+         delete_insn (barrier);
+         delete_insn (resume);
+       }
 
       /* ??? From tree-ssa we can wind up with catch regions whose
         label is not instantiated, but whose resx is present.  Now
@@ -2820,7 +2836,7 @@ for_each_eh_label (void (*callback) (rtx))
     {
       struct eh_region_d *r = VEC_index (eh_region, cfun->eh->region_array, i);
       if (r && r->region_number == i && r->label
-          && GET_CODE (r->label) == CODE_LABEL)
+          && LABEL_P (r->label))
        (*callback) (r->label);
     }
 }
@@ -4408,19 +4424,28 @@ dump_eh_tree (FILE * out, struct function *fun)
       if (i->landing_pad)
        {
           fprintf (out, " landing_pad:%i", INSN_UID (i->landing_pad));
-         if (GET_CODE (i->landing_pad) == NOTE)
+         if (NOTE_P (i->landing_pad))
            fprintf (out, " (deleted)");
         }
       if (i->post_landing_pad)
        {
           fprintf (out, " post_landing_pad:%i", INSN_UID (i->post_landing_pad));
-         if (GET_CODE (i->post_landing_pad) == NOTE)
+         if (NOTE_P (i->post_landing_pad))
            fprintf (out, " (deleted)");
        }
       if (i->resume)
        {
+         rtx resume_list = i->resume;
+          fprintf (out, " resume:");
+         while (GET_CODE (resume_list) == INSN_LIST)
+           {
+             fprintf (out, "%i,", INSN_UID (XEXP (resume_list, 0)));
+             if (NOTE_P (XEXP (resume_list, 0)))
+               fprintf (out, " (deleted)");
+             resume_list = XEXP (resume_list, 1);
+           }
           fprintf (out, " resume:%i", INSN_UID (i->resume));
-         if (GET_CODE (i->resume) == NOTE)
+         if (NOTE_P (i->resume))
            fprintf (out, " (deleted)");
        }
       if (i->may_contain_throw)