Commit 1e4ceb6f by Mark Mitchell Committed by Mark Mitchell

except.h (struct eh_entry): Add goto_entry_p.

	* except.h (struct eh_entry): Add goto_entry_p.
	(eh_region_from_symbol): Remove prototype.
	* except.c (find_func_region_from_symbol): New function.
	(emit_cleanup_handler): Likewise.
	(eh_region_from_symbol): Make it static.
	(add_new_handler): Verify the argument.
	(find_func_region): Update comment.
	(expand_eh_region_end): Expand handlers here, rater than waiting
	until expand_leftover_cleanups or start_all_catch.
	(expand_leftover_cleanups): Don't expand here.
	(expand_start_all_catch): Or here.
	(expand_rethrow): Check the return value from find_func_region.
	* function.c (expand_function_end): Emit the catch_clauses.

From-SVN: r30576
parent 0e6b2107
1999-11-17 Mark Mitchell <mark@codesourcery.com>
* except.h (struct eh_entry): Add goto_entry_p.
(eh_region_from_symbol): Remove prototype.
* except.c (find_func_region_from_symbol): New function.
(emit_cleanup_handler): Likewise.
(eh_region_from_symbol): Make it static.
(add_new_handler): Verify the argument.
(find_func_region): Update comment.
(expand_eh_region_end): Expand handlers here, rater than waiting
until expand_leftover_cleanups or start_all_catch.
(expand_leftover_cleanups): Don't expand here.
(expand_start_all_catch): Or here.
(expand_rethrow): Check the return value from find_func_region.
* function.c (expand_function_end): Emit the catch_clauses.
1999-11-18 Gavin Romig-Koch <gavin@cygnus.com> 1999-11-18 Gavin Romig-Koch <gavin@cygnus.com>
* integrate.c (expand_inline_function): Add necessary check for NULL. * integrate.c (expand_inline_function): Add necessary check for NULL.
......
...@@ -479,10 +479,14 @@ static void push_entry PROTO ((struct eh_stack *, struct eh_entry*)); ...@@ -479,10 +479,14 @@ static void push_entry PROTO ((struct eh_stack *, struct eh_entry*));
static void receive_exception_label PROTO ((rtx)); static void receive_exception_label PROTO ((rtx));
static int new_eh_region_entry PROTO ((int, rtx)); static int new_eh_region_entry PROTO ((int, rtx));
static int find_func_region PROTO ((int)); static int find_func_region PROTO ((int));
static int find_func_region_from_symbol PROTO ((rtx));
static void clear_function_eh_region PROTO ((void)); static void clear_function_eh_region PROTO ((void));
static void process_nestinfo PROTO ((int, eh_nesting_info *, int *)); static void process_nestinfo PROTO ((int, eh_nesting_info *, int *));
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx)); rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
static void emit_cleanup_handler PROTO ((struct eh_entry *));
static int eh_region_from_symbol PROTO((rtx));
/* Various support routines to manipulate the various data structures /* Various support routines to manipulate the various data structures
used by the exception handling code. */ used by the exception handling code. */
...@@ -590,6 +594,7 @@ push_eh_entry (stack) ...@@ -590,6 +594,7 @@ push_eh_entry (stack)
else else
entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab)); entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab));
entry->rethrow_label = entry->outer_context; entry->rethrow_label = entry->outer_context;
entry->goto_entry_p = 0;
node->entry = entry; node->entry = entry;
node->chain = stack->top; node->chain = stack->top;
...@@ -705,10 +710,8 @@ static int current_func_eh_entry = 0; ...@@ -705,10 +710,8 @@ static int current_func_eh_entry = 0;
#define SIZE_FUNC_EH(X) (sizeof (struct func_eh_entry) * X) #define SIZE_FUNC_EH(X) (sizeof (struct func_eh_entry) * X)
/* Add a new eh_entry for this function, and base it off of the information /* Add a new eh_entry for this function. The number returned is an
in the EH_ENTRY parameter. A NULL parameter is invalid. number which uniquely identifies this exception range. */
OUTER_CONTEXT is a label which is used for rethrowing. The number
returned is an number which uniquely identifies this exception range. */
static int static int
new_eh_region_entry (note_eh_region, rethrow) new_eh_region_entry (note_eh_region, rethrow)
...@@ -755,6 +758,12 @@ add_new_handler (region, newhandler) ...@@ -755,6 +758,12 @@ add_new_handler (region, newhandler)
{ {
struct handler_info *last; struct handler_info *last;
/* If find_func_region returns -1, callers might attempt to pass us
this region number. If that happens, something has gone wrong;
-1 is never a valid region. */
if (region == -1)
abort ();
newhandler->next = NULL; newhandler->next = NULL;
last = function_eh_regions[region].handlers; last = function_eh_regions[region].handlers;
if (last == NULL) if (last == NULL)
...@@ -883,7 +892,7 @@ get_new_handler (handler, typeinfo) ...@@ -883,7 +892,7 @@ get_new_handler (handler, typeinfo)
/* Find the index in function_eh_regions associated with a NOTE region. If /* Find the index in function_eh_regions associated with a NOTE region. If
the region cannot be found, a -1 is returned. This should never happen! */ the region cannot be found, a -1 is returned. */
static int static int
find_func_region (insn_region) find_func_region (insn_region)
...@@ -960,7 +969,7 @@ duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map) ...@@ -960,7 +969,7 @@ duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map)
/* Given a rethrow symbol, find the EH region number this is for. */ /* Given a rethrow symbol, find the EH region number this is for. */
int static int
eh_region_from_symbol (sym) eh_region_from_symbol (sym)
rtx sym; rtx sym;
{ {
...@@ -973,6 +982,14 @@ eh_region_from_symbol (sym) ...@@ -973,6 +982,14 @@ eh_region_from_symbol (sym)
return -1; return -1;
} }
/* 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;
{
return find_func_region (eh_region_from_symbol (sym));
}
/* When inlining/unrolling, we have to map the symbols passed to /* When inlining/unrolling, we have to map the symbols passed to
__rethrow as well. This performs the remap. If a symbol isn't foiund, __rethrow as well. This performs the remap. If a symbol isn't foiund,
...@@ -1475,6 +1492,7 @@ expand_eh_region_end (handler) ...@@ -1475,6 +1492,7 @@ expand_eh_region_end (handler)
tree handler; tree handler;
{ {
struct eh_entry *entry; struct eh_entry *entry;
struct eh_node *node;
rtx note; rtx note;
int ret, r; int ret, r;
...@@ -1523,6 +1541,21 @@ expand_eh_region_end (handler) ...@@ -1523,6 +1541,21 @@ expand_eh_region_end (handler)
expand_end_bindings (NULL_TREE, 0, 0); expand_end_bindings (NULL_TREE, 0, 0);
} }
/* Go through the goto handlers in the queue, emitting their
handlers if we now have enough information to do so. */
for (node = ehqueue.head; node; node = node->chain)
if (node->entry->goto_entry_p
&& node->entry->outer_context == entry->rethrow_label)
emit_cleanup_handler (node->entry);
/* We can't emit handlers for goto entries until their scopes are
complete because we don't know where they need to rethrow to,
yet. */
if (entry->finalization != integer_zero_node
&& (!entry->goto_entry_p
|| find_func_region_from_symbol (entry->outer_context) != -1))
emit_cleanup_handler (entry);
} }
/* End the EH region for a goto fixup. We only need them in the region-based /* End the EH region for a goto fixup. We only need them in the region-based
...@@ -1535,6 +1568,8 @@ expand_fixup_region_start () ...@@ -1535,6 +1568,8 @@ expand_fixup_region_start ()
return; return;
expand_eh_region_start (); expand_eh_region_start ();
/* Mark this entry as the entry for a goto. */
ehstack.top->entry->goto_entry_p = 1;
} }
/* End the EH region for a goto fixup. CLEANUP is the cleanup we just /* End the EH region for a goto fixup. CLEANUP is the cleanup we just
...@@ -1636,33 +1671,14 @@ expand_leftover_cleanups () ...@@ -1636,33 +1671,14 @@ expand_leftover_cleanups ()
{ {
struct eh_entry *entry; struct eh_entry *entry;
while ((entry = dequeue_eh_entry (&ehqueue)) != 0) for (entry = dequeue_eh_entry (&ehqueue);
entry;
entry = dequeue_eh_entry (&ehqueue))
{ {
rtx prev; /* A leftover try bock. Shouldn't be one here. */
/* A leftover try block. Shouldn't be one here. */
if (entry->finalization == integer_zero_node) if (entry->finalization == integer_zero_node)
abort (); abort ();
/* Output the label for the start of the exception handler. */
receive_exception_label (entry->exception_handler_label);
/* register a handler for this cleanup region */
add_new_handler (
find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)),
get_new_handler (entry->exception_handler_label, NULL));
/* And now generate the insns for the handler. */
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
prev = get_last_insn ();
if (prev == NULL || GET_CODE (prev) != BARRIER)
/* Emit code to throw to the outer context if we fall off
the end of the handler. */
expand_rethrow (entry->outer_context);
do_pending_stack_adjust ();
free (entry); free (entry);
} }
} }
...@@ -1764,6 +1780,56 @@ end_catch_handler () ...@@ -1764,6 +1780,56 @@ end_catch_handler ()
catchstack.top->entry->false_label = NULL_RTX; catchstack.top->entry->false_label = NULL_RTX;
} }
/* Emit the handler specified by ENTRY. */
static void
emit_cleanup_handler (entry)
struct eh_entry *entry;
{
rtx prev;
rtx handler_insns;
/* Put these handler instructions in a sequence. */
do_pending_stack_adjust ();
start_sequence ();
/* Emit the label for the cleanup handler for this region, and
expand the code for the handler.
Note that a catch region is handled as a side-effect here; for a
try block, entry->finalization will contain integer_zero_node, so
no code will be generated in the expand_expr call below. But, the
label for the handler will still be emitted, so any code emitted
after this point will end up being the handler. */
receive_exception_label (entry->exception_handler_label);
/* register a handler for this cleanup region */
add_new_handler (find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)),
get_new_handler (entry->exception_handler_label, NULL));
/* And now generate the insns for the cleanup handler. */
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
prev = get_last_insn ();
if (prev == NULL || GET_CODE (prev) != BARRIER)
/* Code to throw out to outer context when we fall off end of the
handler. We can't do this here for catch blocks, so it's done
in expand_end_all_catch instead. */
expand_rethrow (entry->outer_context);
/* Finish this sequence. */
do_pending_stack_adjust ();
handler_insns = get_insns ();
end_sequence ();
/* And add it to the CATCH_CLAUSES. */
push_to_sequence (catch_clauses);
emit_insns (handler_insns);
catch_clauses = get_insns ();
end_sequence ();
}
/* Generate RTL for the start of a group of catch clauses. /* Generate RTL for the start of a group of catch clauses.
It is responsible for starting a new instruction sequence for the It is responsible for starting a new instruction sequence for the
...@@ -1802,48 +1868,15 @@ expand_start_all_catch () ...@@ -1802,48 +1868,15 @@ expand_start_all_catch ()
the handlers in this handler-seq. */ the handlers in this handler-seq. */
start_sequence (); start_sequence ();
entry = dequeue_eh_entry (&ehqueue); for (entry = dequeue_eh_entry (&ehqueue);
for ( ; entry->finalization != integer_zero_node; entry->finalization != integer_zero_node;
entry = dequeue_eh_entry (&ehqueue)) entry = dequeue_eh_entry (&ehqueue))
{ free (entry);
rtx prev;
/* Emit the label for the cleanup handler for this region, and
expand the code for the handler.
Note that a catch region is handled as a side-effect here;
for a try block, entry->finalization will contain
integer_zero_node, so no code will be generated in the
expand_expr call below. But, the label for the handler will
still be emitted, so any code emitted after this point will
end up being the handler. */
receive_exception_label (entry->exception_handler_label);
/* register a handler for this cleanup region */
add_new_handler (
find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)),
get_new_handler (entry->exception_handler_label, NULL));
/* And now generate the insns for the cleanup handler. */
expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
prev = get_last_insn ();
if (prev == NULL || GET_CODE (prev) != BARRIER)
/* Code to throw out to outer context when we fall off end
of the handler. We can't do this here for catch blocks,
so it's done in expand_end_all_catch instead. */
expand_rethrow (entry->outer_context);
do_pending_stack_adjust ();
free (entry);
}
/* At this point, all the cleanups are done, and the ehqueue now has /* At this point, all the cleanups are done, and the ehqueue now has
the current exception region at its head. We dequeue it, and put it the current exception region at its head. We dequeue it, and put it
on the catch stack. */ on the catch stack. */
push_entry (&catchstack, entry);
push_entry (&catchstack, entry);
/* If we are not doing setjmp/longjmp EH, because we are reordered /* If we are not doing setjmp/longjmp EH, because we are reordered
out of line, we arrange to rethrow in the outer context. We need to out of line, we arrange to rethrow in the outer context. We need to
...@@ -1935,6 +1968,10 @@ expand_rethrow (label) ...@@ -1935,6 +1968,10 @@ expand_rethrow (label)
label = last_rethrow_symbol; label = last_rethrow_symbol;
emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode); emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
region = find_func_region (eh_region_from_symbol (label)); region = find_func_region (eh_region_from_symbol (label));
/* If the region is -1, it doesn't exist yet. We should be
trying to rethrow there yet. */
if (region == -1)
abort ();
function_eh_regions[region].rethrow_ref = 1; function_eh_regions[region].rethrow_ref = 1;
/* Search backwards for the actual call insn. */ /* Search backwards for the actual call insn. */
......
...@@ -62,6 +62,9 @@ struct eh_entry { ...@@ -62,6 +62,9 @@ struct eh_entry {
int label_used; int label_used;
rtx false_label; rtx false_label;
rtx rethrow_label; rtx rethrow_label;
/* If non-zero, this entry is for a handler created when we left an
exception-region via goto. */
unsigned goto_entry_p : 1;
}; };
#else #else
struct label_node; struct label_node;
...@@ -108,16 +111,10 @@ struct eh_status ...@@ -108,16 +111,10 @@ struct eh_status
/* This stack is used to represent what the current eh region is /* This stack is used to represent what the current eh region is
for the catch blocks beings processed */ for the catch blocks beings processed */
struct eh_stack x_catchstack; struct eh_stack x_catchstack;
/* A queue used for tracking which exception regions have closed but /* A queue used for tracking which exception regions have closed.
whose handlers have not yet been expanded. Regions are emitted in
groups in an attempt to improve paging performance.
As we exit a region, we enqueue a new entry. The entries are then As we exit a region, we enqueue a new entry. The entries are then
dequeued during expand_leftover_cleanups and expand_start_all_catch, dequeued during expand_leftover_cleanups and
expand_start_all_catch. */
We should redo things so that we either take RTL for the handler,
or we expand the handler expressed as a tree immediately at region
end time. */
struct eh_queue x_ehqueue; struct eh_queue x_ehqueue;
/* Insns for all of the exception handlers for the current function. /* Insns for all of the exception handlers for the current function.
They are currently emitted by the frontend code. */ They are currently emitted by the frontend code. */
...@@ -271,10 +268,6 @@ int rethrow_used PROTO((int)); ...@@ -271,10 +268,6 @@ int rethrow_used PROTO((int));
void update_rethrow_references PROTO((void)); void update_rethrow_references PROTO((void));
/* Return the region number a this is the rethrow label for. */
int eh_region_from_symbol PROTO((rtx));
/* Get a pointer to the first handler in an exception region's list. */ /* Get a pointer to the first handler in an exception region's list. */
struct handler_info *get_first_handler PROTO((int)); struct handler_info *get_first_handler PROTO((int));
......
...@@ -6436,6 +6436,9 @@ expand_function_end (filename, line, end_bindings) ...@@ -6436,6 +6436,9 @@ expand_function_end (filename, line, end_bindings)
expand_leftover_cleanups (); expand_leftover_cleanups ();
/* If there are any catch_clauses remaining, output them now. */
emit_insns (catch_clauses);
catch_clauses = NULL_RTX;
/* If the above emitted any code, may sure we jump around it. */ /* If the above emitted any code, may sure we jump around it. */
if (last != get_last_insn ()) if (last != get_last_insn ())
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment