[c++] bug with new inlining mechanism on v-3, commentary

Mark Mitchell mark@codesourcery.com
Fri Dec 31 20:54:00 GMT 1999


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 ();



More information about the Gcc-bugs mailing list