extern struct obstack permanent_obstack;
/* Generate a SYMBOL_REF for rethrow to use */
+
static rtx
create_rethrow_ref (region_num)
int region_num;
return (*stack)->u.tlabel;
}
-/* get an exception label. These must be on the permanent obstack */
+/* Get an exception label. */
rtx
gen_exception_label ()
stack->top = node;
}
-/* push an existing entry onto a stack. */
+/* Push an existing entry onto a stack. */
+
static void
push_entry (stack, entry)
struct eh_stack *stack;
{
int range_number; /* EH region number from EH NOTE insn's. */
rtx rethrow_label; /* Label for rethrow. */
- int rethrow_ref; /* Is rethrow referenced? */
+ int rethrow_ref; /* Is rethrow_label referenced? */
struct handler_info *handlers;
};
/* Given a rethrow symbol, find the EH region number this is for. */
+
static int
eh_region_from_symbol (sym)
rtx sym;
/* Like find_func_region, but using the rethrow symbol for the region
rather than the region number itself. */
+
static int
find_func_region_from_symbol (sym)
rtx sym;
__rethrow as well. This performs the remap. If a symbol isn't foiund,
the original one is returned. This is not an efficient routine,
so don't call it on everything!! */
+
rtx
rethrow_symbol_map (sym, map)
rtx sym;
rtx (*map) PARAMS ((rtx));
{
int x, y;
+
+ if (! flag_new_exceptions)
+ return sym;
+
for (x = 0; x < current_func_eh_entry; x++)
if (function_eh_regions[x].rethrow_label == sym)
{
return sym;
}
+/* Returns nonzero if the rethrow label for REGION is referenced
+ somewhere (i.e. we rethrow out of REGION or some other region
+ masquerading as REGION). */
+
int
rethrow_used (region)
int region;
label = last_rethrow_symbol;
emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
region = find_func_region (eh_region_from_symbol (label));
- /* If the region is -1, it doesn't exist yet. We should be
+ /* If the region is -1, it doesn't exist yet. We shouldn't be
trying to rethrow there yet. */
if (region == -1)
abort ();
int index = find_func_region (n);
rtx rethrow;
- /* form and emit the rethrow label, if needed */
- rethrow = function_eh_regions[index].rethrow_label;
- if (rethrow != NULL_RTX && !flag_new_exceptions)
- rethrow = NULL_RTX;
- if (rethrow != NULL_RTX && handler == NULL)
- if (! function_eh_regions[index].rethrow_ref)
- rethrow = NULL_RTX;
-
+ /* Form and emit the rethrow label, if needed */
+ if (flag_new_exceptions
+ && (handler || function_eh_regions[index].rethrow_ref))
+ rethrow = function_eh_regions[index].rethrow_label;
+ else
+ rethrow = NULL_RTX;
for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
{
if (i != 0)
assemble_integer (const0_rtx, i , 1);
- /* Generate the label for offset calculations on rethrows */
+ /* Generate the label for offset calculations on rethrows. */
ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
assemble_label(buf);
}
assemble_label(buf);
assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
- /* for binary compatability, the old __throw checked the second
+ /* For binary compatibility, the old __throw checked the second
position for a -1, so we should output at least 2 -1's */
if (! flag_new_exceptions)
assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
/* Assume we can delete the region. */
int delete = 1;
- /* Can't delete something which is rethrown to. */
+ /* Can't delete something which is rethrown from. */
if (rethrow_used (n))
delete = 0;
}
}
-/* 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. */
+/* This function determines whether the rethrow labels for any of the
+ exception regions in the current function are used or not, and set
+ the reference flag according. */
+
void
update_rethrow_references ()
{
saw_rethrow = (int *) xcalloc (current_func_eh_entry, sizeof (int));
/* Determine what regions exist, and whether there are any rethrows
- to those regions or not. */
+ from those regions or not. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == CALL_INSN)
{
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
+ This means we won't 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. */
prev_call = insn;
call_had_abnormal_edge = 0;
- /* If there is a specified EH region, we have an edge. */
- if (eh_region && region > 0)
+ /* If there is an EH region or rethrow, we have an edge. */
+ if ((eh_region && region > 0)
+ || find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
call_had_abnormal_edge = 1;
else
{
int region = (note ? XWINT (XEXP (note, 0), 0) : 1);
call_has_abnormal_edge = 0;
- /* If there is an EH region, we have an edge. */
- if (eh_list && region > 0)
+ /* If there is an EH region or rethrow, we have an edge. */
+ if ((eh_list && region > 0)
+ || find_reg_note (insn, REG_EH_RETHROW, NULL_RTX))
call_has_abnormal_edge = 1;
else
{
if (code == CALL_INSN || asynchronous_exceptions)
{
- /* If there's an EH region active at the end of a block,
- add the appropriate edges. */
- if (bb->eh_end >= 0)
- make_eh_edge (edge_cache, eh_nest_info, bb, insn, bb->eh_end);
+ /* Add any appropriate EH edges. We do this unconditionally
+ since there may be a REG_EH_REGION or REG_EH_RETHROW note
+ on the call, and this needn't be within an EH region. */
+ make_eh_edge (edge_cache, eh_nest_info, bb, insn, bb->eh_end);
/* If we have asynchronous exceptions, do the same for *all*
exception regions active in the block. */
{
int num = NOTE_EH_HANDLER (insn);
/* A NULL handler indicates a region is no longer needed,
- as long as it isn't the target of a rethrow. */
+ as long as its rethrow label isn't used. */
if (get_first_handler (num) == NULL && ! rethrow_used (num))
{
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;