This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: [c++] bug with new inlining mechanism on v-3, commentary
- To: nathan at cs dot bris dot ac dot uk, nathan at acm dot org
- Subject: Re: [c++] bug with new inlining mechanism on v-3, commentary
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 12 Dec 1999 10:47:38 -0800
- Cc: Gabriel dot Dos_Reis at sophia dot inria dot fr, bkoz at cygnus dot com, gcc-bugs at gcc dot gnu dot org, bkoz at nabi dot net
- Organization: CodeSourcery, LLC
- References: <199912110046.QAA26866@haight.constant.com><xajk8mm5cjl.fsf@korrigan.inria.fr><38522DC0.CF3F4263@acm.org>
I fixed the bug in this test-case with this patch. Hopefully this
will fix the V3 failure as well, since this test-case was distilled
(by Nathan) from the original V3 code.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-12-12 Mark Mitchell <mark@codesourcery.com>
* except.h (struct eh_queue): Add `next' pointer.
(struct eh_status): Make x_ehqueue a pointer.
(push_ehqueue): Declare.
(pop_ehqueue): Likewise.
* except.c (expand_eh_region_end): Adjust now that ehqueue is a
pointer.
(expand_fixup_region_end): Likewise.
(expand_leftover_cleanups): Likewise.
(push_ehqueue): Define.
(pop_ehqueue): Likewise.
(emit_cleanup_handler): Use push_ehqueue and pop_ehqueue rather
than doing it inline.
(expand_start_all_catch): Adjust now that ehqueue is a
pointer.
(mark_eh_queue): Mark all level of the queue.
(mark_eh_status): Adjust now that ehqueue is a
pointer.
(init_eh_for_function): Allocate ehqueue.
(free_eh_status): Free it.
* stmt.c (expand_cleanups): Save the ehqueue around the cleanup
expansion for a fixup.
Index: except.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/except.c,v
retrieving revision 1.108
diff -c -p -r1.108 except.c
*** except.c 1999/11/25 20:06:25 1.108
--- except.c 1999/12/12 18:24:14
*************** expand_eh_region_end (handler)
*** 1533,1539 ****
/* create region entry in final exception table */
r = new_eh_region_entry (NOTE_EH_HANDLER (note), entry->rethrow_label);
! enqueue_eh_entry (&ehqueue, entry);
/* If we have already started ending the bindings, don't recurse. */
if (is_eh_region ())
--- 1533,1539 ----
/* create region entry in final exception table */
r = new_eh_region_entry (NOTE_EH_HANDLER (note), entry->rethrow_label);
! enqueue_eh_entry (ehqueue, entry);
/* If we have already started ending the bindings, don't recurse. */
if (is_eh_region ())
*************** expand_eh_region_end (handler)
*** 1551,1557 ****
/* 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);
--- 1551,1557 ----
/* 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);
*************** expand_fixup_region_end (cleanup)
*** 1596,1602 ****
for (node = ehstack.top; node && node->entry->finalization != cleanup; )
node = node->chain;
if (node == 0)
! for (node = ehqueue.head; node && node->entry->finalization != cleanup; )
node = node->chain;
if (node == 0)
abort ();
--- 1596,1602 ----
for (node = ehstack.top; node && node->entry->finalization != cleanup; )
node = node->chain;
if (node == 0)
! for (node = ehqueue->head; node && node->entry->finalization != cleanup; )
node = node->chain;
if (node == 0)
abort ();
*************** expand_leftover_cleanups ()
*** 1678,1686 ****
{
struct eh_entry *entry;
! for (entry = dequeue_eh_entry (&ehqueue);
entry;
! entry = dequeue_eh_entry (&ehqueue))
{
/* A leftover try block. Shouldn't be one here. */
if (entry->finalization == integer_zero_node)
--- 1678,1686 ----
{
struct eh_entry *entry;
! for (entry = dequeue_eh_entry (ehqueue);
entry;
! entry = dequeue_eh_entry (ehqueue))
{
/* A leftover try block. Shouldn't be one here. */
if (entry->finalization == integer_zero_node)
*************** end_catch_handler ()
*** 1787,1792 ****
--- 1787,1815 ----
catchstack.top->entry->false_label = NULL_RTX;
}
+ /* Save away the current ehqueue. */
+
+ void
+ push_ehqueue ()
+ {
+ struct eh_queue *q;
+ q = xcalloc (1, sizeof (struct eh_queue));
+ q->next = ehqueue;
+ ehqueue = q;
+ }
+
+ /* Restore a previously pushed ehqueue. */
+
+ void
+ pop_ehqueue ()
+ {
+ struct eh_queue *q;
+ expand_leftover_cleanups ();
+ q = ehqueue->next;
+ free (ehqueue);
+ ehqueue = q;
+ }
+
/* Emit the handler specified by ENTRY. */
static void
*************** emit_cleanup_handler (entry)
*** 1795,1807 ****
{
rtx prev;
rtx handler_insns;
- struct eh_queue q;
/* Since the cleanup could itself contain try-catch blocks, we
squirrel away the current queue and replace it when we are done
with this function. */
! q = ehqueue;
! ehqueue.head = ehqueue.tail = NULL;
/* Put these handler instructions in a sequence. */
do_pending_stack_adjust ();
--- 1818,1828 ----
{
rtx prev;
rtx handler_insns;
/* Since the cleanup could itself contain try-catch blocks, we
squirrel away the current queue and replace it when we are done
with this function. */
! push_ehqueue ();
/* Put these handler instructions in a sequence. */
do_pending_stack_adjust ();
*************** emit_cleanup_handler (entry)
*** 1844,1851 ****
end_sequence ();
/* Now we've left the handler. */
! expand_leftover_cleanups ();
! ehqueue = q;
}
/* Generate RTL for the start of a group of catch clauses.
--- 1865,1871 ----
end_sequence ();
/* Now we've left the handler. */
! pop_ehqueue ();
}
/* Generate RTL for the start of a group of catch clauses.
*************** expand_start_all_catch ()
*** 1889,1897 ****
/* Throw away entries in the queue that we won't need anymore. We
need entries for regions that have ended but to which there might
still be gotos pending. */
! for (entry = dequeue_eh_entry (&ehqueue);
entry->finalization != integer_zero_node;
! entry = dequeue_eh_entry (&ehqueue))
free (entry);
/* At this point, all the cleanups are done, and the ehqueue now has
--- 1909,1917 ----
/* Throw away entries in the queue that we won't need anymore. We
need entries for regions that have ended but to which there might
still be gotos pending. */
! for (entry = dequeue_eh_entry (ehqueue);
entry->finalization != integer_zero_node;
! entry = dequeue_eh_entry (ehqueue))
free (entry);
/* At this point, all the cleanups are done, and the ehqueue now has
*************** static void
*** 2477,2484 ****
mark_eh_queue (q)
struct eh_queue *q;
{
! if (q)
! mark_eh_node (q->head);
}
/* Mark NODE for GC. A label_node contains a union containing either
--- 2497,2507 ----
mark_eh_queue (q)
struct eh_queue *q;
{
! while (q)
! {
! mark_eh_node (q->head);
! q = q->next;
! }
}
/* Mark NODE for GC. A label_node contains a union containing either
*************** mark_eh_status (eh)
*** 2506,2512 ****
mark_eh_stack (&eh->x_ehstack);
mark_eh_stack (&eh->x_catchstack);
! mark_eh_queue (&eh->x_ehqueue);
ggc_mark_rtx (eh->x_catch_clauses);
lang_mark_false_label_stack (eh->x_false_label_stack);
--- 2529,2535 ----
mark_eh_stack (&eh->x_ehstack);
mark_eh_stack (&eh->x_catchstack);
! mark_eh_queue (eh->x_ehqueue);
ggc_mark_rtx (eh->x_catch_clauses);
lang_mark_false_label_stack (eh->x_false_label_stack);
*************** init_eh_for_function ()
*** 2577,2582 ****
--- 2600,2606 ----
{
current_function->eh
= (struct eh_status *) xcalloc (1, sizeof (struct eh_status));
+ ehqueue = (struct eh_queue *) xcalloc (1, sizeof (struct eh_queue));
eh_return_context = NULL_RTX;
eh_return_stack_adjust = NULL_RTX;
eh_return_handler = NULL_RTX;
*************** void
*** 2586,2591 ****
--- 2610,2616 ----
free_eh_status (f)
struct function *f;
{
+ free (f->eh->x_ehqueue);
free (f->eh);
f->eh = NULL;
}
Index: except.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/except.h,v
retrieving revision 1.33
diff -c -p -r1.33 except.h
*** except.h 1999/11/25 19:21:27 1.33
--- except.h 1999/12/12 18:24:17
*************** struct eh_stack {
*** 93,98 ****
--- 93,99 ----
struct eh_queue {
struct eh_node *head;
struct eh_node *tail;
+ struct eh_queue *next;
};
/* Used to save exception handling status for each function. */
*************** struct eh_status
*** 115,121 ****
As we exit a region, we enqueue a new entry. The entries are then
dequeued during expand_leftover_cleanups and
expand_start_all_catch. */
! struct eh_queue x_ehqueue;
/* Insns for all of the exception handlers for the current function.
They are currently emitted by the frontend code. */
rtx x_catch_clauses;
--- 116,122 ----
As we exit a region, we enqueue a new entry. The entries are then
dequeued during expand_leftover_cleanups and
expand_start_all_catch. */
! struct eh_queue *x_ehqueue;
/* Insns for all of the exception handlers for the current function.
They are currently emitted by the frontend code. */
rtx x_catch_clauses;
*************** extern rtx get_dynamic_cleanup_chain PR
*** 442,447 ****
--- 443,454 ----
/* Throw an exception. */
extern void emit_throw PROTO((void));
+
+ /* Save away the current ehqueue. */
+ extern void push_ehqueue PROTO((void));
+
+ /* Restore a previously pushed ehqueue. */
+ extern void pop_ehqueue PROTO((void));
/* One to use setjmp/longjmp method of generating code. */
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stmt.c,v
retrieving revision 1.110
diff -c -p -r1.110 stmt.c
*** stmt.c 1999/12/05 00:10:31 1.110
--- stmt.c 1999/12/12 18:24:19
*************** expand_cleanups (list, dont_do, in_fixup
*** 4270,4276 ****
--- 4270,4280 ----
if (protect)
expand_fixup_region_start ();
+ /* The cleanup might contain try-blocks, so we have to
+ preserve our current queue. */
+ push_ehqueue ();
expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
+ pop_ehqueue ();
if (protect)
expand_fixup_region_end (TREE_VALUE (tail));
free_temp_slots ();