aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/except.c340
-rw-r--r--gcc/except.h45
-rw-r--r--gcc/flow.c62
-rw-r--r--gcc/rtl.h12
5 files changed, 429 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 46c1d3c..0409461 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/except.c b/gcc/except.c
index 40e912f..952021b 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -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];
+}
/* 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;
}
+
+
+/* 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);
+ }
+ }
+}
diff --git a/gcc/except.h b/gcc/except.h
index 2e3e794..73bbe4d 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -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. */
diff --git a/gcc/flow.c b/gcc/flow.c
index 7838416..ccec792 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -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;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 508aac3..705da5e 100644
--- 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)