OSDN Git Service

Tue Aug 10 10:47:42 EDT 1999 Andrew MacLeod <amacleod@cygnus.com>
authoramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 10 Aug 1999 16:19:16 +0000 (16:19 +0000)
committeramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 10 Aug 1999 16:19:16 +0000 (16:19 +0000)
* except.h (eh_nesting_info): Add new structure defintion.
(init_eh_nesting_info, free_eh_nesting_info): Add function prototypes.
(reachable_handlers, update_rethrow_references): Add function
prototypes.
* rtl.h (struct rtvec_def): Update comments.  REG_EH_RETHROW takes
a rethrow symbol instead of an integer exception region number.
* flow.c (Make_edges): Use new exception nesting routines to determine
which handlers are reachable from a CALL or asynchronous insn.
Dont add an edge for calls with a REG_EH_REGION of -1 to non-local
goto receivers.
(delete_eh_regions): Update rethrow labels, and don't delete
regions which are the target of a rethrow.
* except.c (struct func_eh_entry): Add rethrow_ref field, now we can
avoid overloading the SYMBOL_REF_USED flag.
(rethrow_symbol_map): Use new rethrow_ref field.
(rethrow_used): Use new rethrow_ref field.
(expand_rethrow): REG_EH_RETHROW now has a SYMBOL_REF instead
of an integer.  Fix formatting.
(output_exception_table_entry): Use new rethrow_ref field.
(can_throw): Check for EH_REGION_NOTE before deciding
whether a CALL can throw or not.
(scan_region): Call rethrow_used() instead of accessing data structure.
(update_rethrow_references): New function to make sure only regions
which are still targets of a rethrow are flagged as such.
(process_nestinfo): New static function to initialize a handler
list for a specific region.
(init_eh_nesting_info): New function to allocate and initialize
the list of all EH handlers reachable from all regions.
(reachable_handlers): New function to retrieve the list of handlers
reachable from a specific region and insn.
(free_eh_nesting_info): New function to dispose of a list of
reachable handlers.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28647 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/except.c
gcc/except.h
gcc/flow.c
gcc/rtl.h

index 46c1d3c..0409461 100644 (file)
@@ -1,3 +1,38 @@
+Tue Aug 10 10:47:42 EDT 1999  Andrew MacLeod  <amacleod@cygnus.com>
+
+       * except.h (eh_nesting_info): Add new structure defintion.
+       (init_eh_nesting_info, free_eh_nesting_info): Add function prototypes.
+       (reachable_handlers, update_rethrow_references): Add function 
+       prototypes.
+       * rtl.h (struct rtvec_def): Update comments.  REG_EH_RETHROW takes
+       a rethrow symbol instead of an integer exception region number.
+       * flow.c (Make_edges): Use new exception nesting routines to determine 
+       which handlers are reachable from a CALL or asynchronous insn.
+       Dont add an edge for calls with a REG_EH_REGION of -1 to non-local
+       goto receivers.
+       (delete_eh_regions): Update rethrow labels, and don't delete 
+       regions which are the target of a rethrow.
+       * except.c (struct func_eh_entry): Add rethrow_ref field, now we can
+       avoid overloading the SYMBOL_REF_USED flag.
+       (rethrow_symbol_map): Use new rethrow_ref field.
+       (rethrow_used): Use new rethrow_ref field.
+       (expand_rethrow): REG_EH_RETHROW now has a SYMBOL_REF instead 
+       of an integer.  Fix formatting.
+       (output_exception_table_entry): Use new rethrow_ref field.
+       (can_throw): Check for EH_REGION_NOTE before deciding
+       whether a CALL can throw or not.
+       (scan_region): Call rethrow_used() instead of accessing data structure.
+       (update_rethrow_references): New function to make sure only regions
+       which are still targets of a rethrow are flagged as such.
+       (process_nestinfo): New static function to initialize a handler 
+       list for a specific region.
+       (init_eh_nesting_info): New function to allocate and initialize
+       the list of all EH handlers reachable from all regions.
+       (reachable_handlers): New function to retrieve the list of handlers
+       reachable from a specific region and insn.
+       (free_eh_nesting_info): New function to dispose of a list of
+       reachable handlers.
+
 Tue Aug 10 10:39:31 EDT 1999  Andrew MacLeod  <amacleod@cygnus.com>
 
        * flow.c (split_edge): Set JUMP_LABEL field.
index 40e912f..952021b 100644 (file)
@@ -677,8 +677,9 @@ receive_exception_label (handler_label)
 
 struct func_eh_entry 
 {
-  int range_number;   /* EH region number from EH NOTE insn's */
-  rtx rethrow_label;  /* Label for rethrow */
+  int range_number;   /* EH region number from EH NOTE insn's.  */
+  rtx rethrow_label;  /* Label for rethrow.  */
+  int rethrow_ref;    /* Is rethrow referenced?  */
   struct handler_info *handlers;
 };
 
@@ -981,7 +982,7 @@ rethrow_symbol_map (sym, map)
           {
             x = duplicate_eh_handlers (CODE_LABEL_NUMBER (l1), y, map);
             /* Since we're mapping it, it must be used. */
-            SYMBOL_REF_USED (function_eh_regions[x].rethrow_label) = 1;
+            function_eh_regions[x].rethrow_ref = 1;
           }
         return function_eh_regions[x].rethrow_label;
       }
@@ -994,8 +995,8 @@ rethrow_used (region)
 {
   if (flag_new_exceptions)
     {
-      rtx lab = function_eh_regions[find_func_region (region)].rethrow_label;
-      return (SYMBOL_REF_USED (lab));
+      int ret = function_eh_regions[find_func_region (region)].rethrow_ref;
+      return ret;
     }
   return 0;
 }
@@ -1900,23 +1901,24 @@ expand_rethrow (label)
   else
     if (flag_new_exceptions)
       {
-        rtx insn, val;
-        if (label == NULL_RTX)
-          label = last_rethrow_symbol;
-        emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
-        SYMBOL_REF_USED (label) = 1;
+       rtx insn, val;
+       int region;
+       if (label == NULL_RTX)
+         label = last_rethrow_symbol;
+       emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
+       region = find_func_region (eh_region_from_symbol (label));
+       function_eh_regions[region].rethrow_ref = 1;
 
        /* Search backwards for the actual call insn.  */
-        insn = get_last_insn ();
+       insn = get_last_insn ();
        while (GET_CODE (insn) != CALL_INSN)
          insn = PREV_INSN (insn);
        delete_insns_since (insn);
-       
-        /* Mark the label/symbol on the call. */
-        val = GEN_INT (eh_region_from_symbol (label));
-        REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, val,
+
+       /* Mark the label/symbol on the call. */
+       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, label,
                                              REG_NOTES (insn));
-        emit_barrier ();
+       emit_barrier ();
       }
     else
       emit_jump (label);
@@ -2062,7 +2064,7 @@ output_exception_table_entry (file, n)
   if (rethrow != NULL_RTX && !flag_new_exceptions)
       rethrow = NULL_RTX;
   if (rethrow != NULL_RTX && handler == NULL)
-    if (! SYMBOL_REF_USED (rethrow))
+    if (! function_eh_regions[index].rethrow_ref)
       rethrow = NULL_RTX;
 
 
@@ -2373,9 +2375,14 @@ static int
 can_throw (insn)
      rtx insn;
 {
-  /* Calls can always potentially throw exceptions.  */
+  /* Calls can always potentially throw exceptions, unless they have
+     a REG_EH_REGION note with a value of 0 or less.  */
   if (GET_CODE (insn) == CALL_INSN)
-    return 1;
+    {
+      rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+      if (!note || XINT (XEXP (note, 0), 0) > 0)
+       return 1;
+    }
 
   if (asynchronous_exceptions)
     {
@@ -2416,9 +2423,8 @@ scan_region (insn, n, delete_outer)
   /* Assume we can delete the region.  */
   int delete = 1;
 
-  int r = find_func_region (n);
   /* Can't delete something which is rethrown to. */
-  if (SYMBOL_REF_USED((function_eh_regions[r].rethrow_label)))
+  if (rethrow_used (n))
     delete = 0;
 
   if (insn == NULL_RTX
@@ -2533,6 +2539,53 @@ exception_optimize ()
        }
     }
 }
+
+/* This function determines whether any of the exception regions in the
+   current function are targets of a rethrow or not, and set the 
+   reference flag according.  */
+void
+update_rethrow_references ()
+{
+  rtx insn;
+  int x, region;
+  int *saw_region, *saw_rethrow;
+
+  if (!flag_new_exceptions)
+    return;
+
+  saw_region = (int *) alloca (current_func_eh_entry * sizeof (int));
+  saw_rethrow = (int *) alloca (current_func_eh_entry * sizeof (int));
+  bzero ((char *) saw_region, (current_func_eh_entry * sizeof (int)));
+  bzero ((char *) saw_rethrow, (current_func_eh_entry * sizeof (int)));
+
+  /* Determine what regions exist, and whether there are any rethrows
+     to those regions or not.  */
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    if (GET_CODE (insn) == CALL_INSN)
+      {
+       rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
+       if (note)
+         {
+            region = eh_region_from_symbol (XEXP (note, 0));
+           region = find_func_region  (region);
+           saw_rethrow[region] = 1;
+         }
+      }
+    else
+      if (GET_CODE (insn) == NOTE)
+        {
+         if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+           {
+             region = find_func_region (NOTE_BLOCK_NUMBER (insn));
+             saw_region[region] = 1;
+           }
+       }
+
+  /* For any regions we did see, set the referenced flag.  */
+  for (x = 0; x < current_func_eh_entry; x++)
+    if (saw_region[x])
+      function_eh_regions[x].rethrow_ref = saw_rethrow[x];
+}
 \f
 /* Various hooks for the DWARF 2 __throw routine.  */
 
@@ -2853,4 +2906,249 @@ in_same_eh_region (insn1, insn2)
   ret = (insn_eh_region[uid1] == insn_eh_region[uid2]);
   return ret;
 }
+\f
+
+/* This function will initialize the handler list for a specified block.
+   It may recursively call itself if the outer block hasn't been processed
+   yet.  At some point in the future we can trim out handlers which we
+   know cannot be called. (ie, if a block has an INT type handler,
+   control will never be passed to an outer INT type handler).  */
+static void 
+process_nestinfo (block, info, nested_eh_region)
+     int block;
+     eh_nesting_info *info;
+     int *nested_eh_region;
+{
+  handler_info *ptr, *last_ptr = NULL;
+  int x, y, count = 0;
+  int extra = 0;
+  handler_info **extra_handlers;
+  int index = info->region_index[block];
+
+  /* If we've already processed this block, simply return. */
+  if (info->num_handlers[index] > 0)
+    return;
+
+  for (ptr = get_first_handler (block); ptr; last_ptr = ptr, ptr = ptr->next)
+    count++;
+
+ /* pick up any information from the next outer region.  It will already
+    contain a summary of itself and all outer regions to it.  */
+
+  if (nested_eh_region [block] != 0) 
+    {
+      int nested_index = info->region_index[nested_eh_region[block]];
+      process_nestinfo (nested_eh_region[block], info, nested_eh_region);
+      extra = info->num_handlers[nested_index];
+      extra_handlers = info->handlers[nested_index];
+      info->outer_index[index] = nested_index;
+    }
+
+  /* If the last handler is either a CATCH_ALL or a cleanup, then we
+     won't use the outer ones since we know control will not go past the
+     catch-all or cleanup.  */
+
+  if (last_ptr != NULL && (last_ptr->type_info == NULL 
+                          || last_ptr->type_info == CATCH_ALL_TYPE))
+    extra = 0;
+
+  info->num_handlers[index] = count + extra;
+  info->handlers[index] = (handler_info **) malloc ((count + extra) 
+                                                   * sizeof (handler_info **));
+
+  /* First put all our handlers into the list.  */
+  ptr = get_first_handler (block);
+  for (x = 0; x < count; x++)
+    {
+      info->handlers[index][x] = ptr;
+      ptr = ptr->next;
+    }
+
+  /* Now add all the outer region handlers, if they aren't they same as 
+     one of the types in the current block.  We won't worry about
+     derived types yet, we'll just look for the exact type.  */
+  for (y =0, x = 0; x < extra ; x++)
+    {
+      int i, ok;
+      ok = 1;
+      /* Check to see if we have a type duplication.  */
+      for (i = 0; i < count; i++)
+        if (info->handlers[index][i]->type_info == extra_handlers[x]->type_info)
+         {
+           ok = 0;
+           /* Record one less handler.  */
+           (info->num_handlers[index])--;
+           break;
+         }
+      if (ok)
+        {
+         info->handlers[index][y + count] = extra_handlers[x];
+         y++;
+       }
+    }
+}
+
+/* This function will allocate and initialize an eh_nesting_info structure. 
+   It returns a pointer to the completed data structure.  If there are
+   no exception regions, a NULL value is returned.  */
+eh_nesting_info *
+init_eh_nesting_info ()
+{
+  int *nested_eh_region;
+  int region_count = 0;
+  rtx eh_note = NULL_RTX;
+  eh_nesting_info *info;
+  rtx insn;
+  int x;
+
+  info = (eh_nesting_info *) malloc (sizeof (eh_nesting_info));
+  info->region_index = (int *) malloc ((max_label_num () + 1) * sizeof (int));
+  bzero ((char *) info->region_index, (max_label_num () + 1) * sizeof (int));
+
+  nested_eh_region = (int *) alloca ((max_label_num () + 1) * sizeof (int));
+  bzero ((char *) nested_eh_region, (max_label_num () + 1) * sizeof (int));
 
+  /* Create the nested_eh_region list.  If indexed with a block number, it 
+     returns the block number of the next outermost region, if any. 
+     We can count the number of regions and initialize the region_index
+     vector at the same time.  */
+  for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) == NOTE)
+       {
+          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+            {
+             int block = NOTE_BLOCK_NUMBER (insn);
+             region_count++;
+             info->region_index[block] = region_count;
+              if (eh_note)
+                nested_eh_region [block] =
+                                     NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
+              else
+                nested_eh_region [block] = 0;
+              eh_note = gen_rtx_EXPR_LIST (VOIDmode, insn, eh_note);
+            }
+          else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+            eh_note = XEXP (eh_note, 1);
+        }
+    }
+  
+  /* If there are no regions, wrap it up now.  */
+  if (region_count == 0)
+    {
+      free (info->region_index);
+      free (info);
+      return NULL;
+    }
+
+  region_count++;
+  info->handlers = (handler_info ***) malloc (region_count 
+                                             * sizeof (handler_info ***));
+  info->num_handlers = (int *) malloc (region_count * sizeof (int));
+  info->outer_index = (int *) malloc (region_count * sizeof (int));
+
+  bzero ((char *) info->handlers, region_count * sizeof (rtx *));
+  bzero ((char *) info->num_handlers, region_count * sizeof (int));
+  bzero ((char *) info->outer_index, region_count * sizeof (int));
+
+ /* Now initialize the handler lists for all exception blocks.  */
+  for (x = 0; x <= max_label_num (); x++)
+    {
+      if (info->region_index[x] != 0)
+       process_nestinfo (x, info, nested_eh_region);
+    }
+  info->region_count = region_count;
+  return info;
+}
+
+
+/* This function is used to retreive the vector of handlers which 
+   can be reached by a given insn in a given exception region.
+   BLOCK is the exception block the insn is in.
+   INFO is the eh_nesting_info structure.
+   INSN is the (optional) insn within the block.  If insn is not NULL_RTX,
+   it may contain reg notes which modify its throwing behavior, and
+   these will be obeyed.  If NULL_RTX is passed, then we simply return the
+   handlers for block.
+   HANDLERS is the address of a pointer to a vector of handler_info pointers.
+   Upon return, this will have the handlers which can be reached by block.
+   This function returns the number of elements in the handlers vector.  */
+int 
+reachable_handlers (block, info, insn, handlers)
+     int block;
+     eh_nesting_info *info;
+     rtx insn ;
+     handler_info ***handlers;
+{
+  int index = 0;
+  *handlers = NULL;
+
+  if (info == NULL)
+    return 0;
+  if (block > 0)
+    index = info->region_index[block];
+
+  if (insn && GET_CODE (insn) == CALL_INSN)
+    {
+      /* RETHROWs specify a region number from which we are going to rethrow.
+        This means we wont pass control to handlers in the specified
+        region, but rather any region OUTSIDE the specified region.
+        We accomplish this by setting block to the outer_index of the
+        specified region.  */
+      rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
+      if (note)
+       {
+          index = eh_region_from_symbol (XEXP (note, 0));
+         index = info->region_index[index];
+         if (index)
+           index = info->outer_index[index];
+       }
+      else
+        {
+         /* If there is no rethrow, we look for a REG_EH_REGION, and
+            we'll throw from that block.  A value of 0 or less
+            indicates that this insn cannot throw.  */
+         note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+         if (note)
+           {
+             int b = XINT (XEXP (note, 0), 0);
+             if (b <= 0)
+               index = 0;
+             else
+               index = info->region_index[b];
+           }
+       }
+    }
+  /* If we reach this point, and index is 0, there is no throw.  */
+  if (index == 0)
+    return 0;
+  
+  *handlers = info->handlers[index];
+  return info->num_handlers[index];
+}
+
+
+/* This function will free all memory associated with the eh_nesting info.  */
+
+void 
+free_eh_nesting_info (info)
+     eh_nesting_info *info;
+{
+  int x;
+  if (info != NULL)
+    {
+      if (info->region_index)
+        free (info->region_index);
+      if (info->num_handlers)
+        free (info->num_handlers);
+      if (info->outer_index)
+        free (info->outer_index);
+      if (info->handlers)
+        {
+         for (x = 0; x < info->region_count; x++)
+           if (info->handlers[x])
+             free (info->handlers[x]);
+         free (info->handlers);
+       }
+    }
+}
index 2e3e794..73bbe4d 100644 (file)
@@ -266,6 +266,11 @@ rtx rethrow_symbol_map                          PROTO((rtx, rtx (*)(rtx)));
 
 int rethrow_used                                PROTO((int));
 
+/* Update the rethrow references to reflect rethrows which have been
+   optimized away.  */
+
+void update_rethrow_references                 PROTO((void));
+
 /* Return the region number a this is the rethrow label for. */
 
 int eh_region_from_symbol                       PROTO((rtx));
@@ -278,6 +283,46 @@ struct handler_info *get_first_handler          PROTO((int));
 
 int find_all_handler_type_matches               PROTO((void ***));
 
+/* The eh_nesting_info structure is used to find a list of valid handlers
+   for any arbitrary exception region.  When init_eh_nesting_info is called,
+   the information is all pre-calculated and entered in this structure.
+   REGION_INDEX is a vector over all possible region numbers.  Since the
+   number of regions is typically much smaller than the range of block
+   numbers, this is a sparse vector and the other data structures are 
+   represented as dense vectors.  Indexed with an exception region number, this
+   returns the index to use in the other data structures to retreive the
+   correct information.
+   HANDLERS is an array of vectors which point to handler_info structures.
+   when indexed, it gives the list of all possible handlers which can 
+   be reached by a throw from this exception region.
+   NUM_HANDLERS is the equivilent array indicating how many handler
+   pointers there are in the HANDLERS vector.
+   OUTER_INDEX indicates which index represents the information for the
+   outer block.  0 indicates there is no outer context.
+   REGION_COUNT is the number of regions.  */
+
+typedef struct eh_nesting 
+{
+  int *region_index;
+  handler_info ***handlers;
+  int *num_handlers;
+  int *outer_index;
+  int region_count;
+} eh_nesting_info;
+
+/* Initialize the eh_nesting_info structure.  */
+
+eh_nesting_info *init_eh_nesting_info          PROTO((void));
+
+/* Get a list of handlers reachable from a an exception region/insn.  */
+
+int reachable_handlers                         PROTO((int, eh_nesting_info *, rtx, 
+                                              handler_info ***handlers));
+
+/* Free the eh_nesting_info structure.  */
+
+void free_eh_nesting_info                      PROTO((eh_nesting_info *));
+
 extern void init_eh                            PROTO((void));
 
 /* Initialization for the per-function EH data.  */
index 7838416..ccec792 100644 (file)
@@ -867,6 +867,7 @@ make_edges (label_value_list, bb_eh_end)
      rtx *bb_eh_end;
 {
   int i;
+  eh_nesting_info *eh_nest_info = init_eh_nesting_info ();
 
   /* Assume no computed jump; revise as we create edges.  */
   current_function_has_computed_jump = 0;
@@ -976,41 +977,19 @@ make_edges (label_value_list, bb_eh_end)
       if (code == CALL_INSN || asynchronous_exceptions)
        {
          int is_call = (code == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
-         handler_info *ptr;
+         handler_info **handler_list;
+         int eh_region = -1;
+         int num;
 
-         /* Use REG_EH_RETHROW and REG_EH_REGION if available.  */
-         /* ??? REG_EH_REGION is not generated presently.  Is it
-            inteded that there be multiple notes for the regions?
-            or is my eh_list collection redundant with handler linking?  */
+         if (eh_list)
+           eh_region = NOTE_BLOCK_NUMBER (XEXP (eh_list, 0));
 
-         x = find_reg_note (insn, REG_EH_RETHROW, 0);
-         if (!x)
-           x = find_reg_note (insn, REG_EH_REGION, 0);
-         if (x)
+         num = reachable_handlers (eh_region, eh_nest_info,
+                                   insn, &handler_list);
+         for ( ; num > 0; num--)
            {
-             if (XINT (XEXP (x, 0), 0) > 0)
-               {
-                 ptr = get_first_handler (XINT (XEXP (x, 0), 0));
-                 while (ptr)
-                   {
-                     make_label_edge (bb, ptr->handler_label,
-                                      EDGE_ABNORMAL | EDGE_EH | is_call);
-                     ptr = ptr->next;
-                   }
-               }
-           }
-         else
-           {
-             for (x = eh_list; x; x = XEXP (x, 1))
-               {
-                 ptr = get_first_handler (NOTE_BLOCK_NUMBER (XEXP (x, 0)));
-                 while (ptr)
-                   {
-                     make_label_edge (bb, ptr->handler_label,
-                                      EDGE_ABNORMAL | EDGE_EH | is_call);
-                     ptr = ptr->next;
-                   }
-               }
+             make_label_edge (bb, handler_list[num - 1]->handler_label,
+                              EDGE_ABNORMAL | EDGE_EH | is_call);
            }
 
          if (code == CALL_INSN && nonlocal_goto_handler_labels)
@@ -1022,10 +1001,13 @@ make_edges (label_value_list, bb_eh_end)
                 gotos do not have their addresses taken, then only calls to
                 those functions or to other nested functions that use them
                 could possibly do nonlocal gotos.  */
-
-             for (x = nonlocal_goto_handler_labels; x ; x = XEXP (x, 1))
-               make_label_edge (bb, XEXP (x, 0),
-                                EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
+             /* We do know that a REG_EH_REGION note with a value less
+                than 0 is guaranteed not to perform a non-local goto.  */
+             rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+             if (!note || XINT (XEXP (note, 0), 0) >=  0)
+               for (x = nonlocal_goto_handler_labels; x ; x = XEXP (x, 1))
+                 make_label_edge (bb, XEXP (x, 0),
+                                  EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
            }
        }
 
@@ -1050,6 +1032,7 @@ make_edges (label_value_list, bb_eh_end)
            make_edge (bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU);
        }
     }
+  free_eh_nesting_info (eh_nest_info);
 }
 
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
@@ -1615,6 +1598,8 @@ delete_eh_regions ()
 {
   rtx insn;
 
+  update_rethrow_references ();
+
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == NOTE)
       {
@@ -1622,8 +1607,9 @@ delete_eh_regions ()
            (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)) 
          {
            int num = CODE_LABEL_NUMBER (insn);
-           /* A NULL handler indicates a region is no longer needed */
-           if (get_first_handler (num) == NULL)
+           /* A NULL handler indicates a region is no longer needed,
+              as long as it isn't the target of a rethrow.  */
+           if (get_first_handler (num) == NULL && ! rethrow_used (num))
              {
                NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
                NOTE_SOURCE_FILE (insn) = 0;
index 508aac3..705da5e 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -344,13 +344,13 @@ typedef struct rtvec_def{
    rtx is used instead of intuition.  */
 /*   REG_EH_REGION is used to indicate what exception region an INSN
    belongs in.  This can be used to indicate what region a call may throw
-   to.  A REGION of 0 indicates that a call cannot throw at all.
-   A REGION  of -1 indicates that it cannot throw, nor will it execute
+   to. a REGION of 0 indicates that a call cannot throw at all.
+   a REGION  of -1 indicates that it cannot throw, nor will it execute
    a non-local goto.
-     REG_EH_RETHROW is used to indicate what that a call is actually a
-   call to rethrow, and specifies which region the rethrow is targetting.
-   This provides a way to generate the non standard flow edges required 
-   for a rethrow.  */
+     REG_EH_RETHROW is used to indicate that a call is actually a
+   call to rethrow, and specifies the rethrow symbol for the region 
+   the rethrow is targetting.  This provides a way to generate the 
+   non standard flow edges required for a rethrow. */
    
 
 #define REG_NOTES(INSN)        ((INSN)->fld[6].rtx)