[tree-ssa]: Generic link routines and some insert infrastructure

Andrew MacLeod amacleod@redhat.com
Wed Mar 5 20:19:00 GMT 2003


This is the first patch which provides some generalized routines which the
insert routines build upon.

First, there is a set of routines for the tsi_stmt_iterator to add and 
remove statements as well as start new statement lists. These are intended to
be a generic interface which all tree's are constructed through. If all the
front ends are later modified to build trees through this mechanism, then we are
free to modify the implementation of trees. This in turn will allow us to get 
rid of CE nodes as a linking mechanism, for instance.  All we'd need to 
change is the implementation of the tsi_ routines.

That said, anyone actually trying to do this may discover there are weaknesses
or problems with this interface, and we may have to extend or change it. We
have to start somewhere, and these seems like a reasonable place to begin. The
insert routines use these to link in any new statements created as well.

The interface basically consists of:

  enum tsi_iterator_update
  {
    TSI_NEW_STMT,
    TSI_SAME_STMT
  };

  void tsi_link_before (tree_stmt_iterator *, tree, enum tsi_iterator_update)
  void tsi_link_after  (tree_stmt_iterator *, tree, enum tsi_iterator_update)

The third parameter indicates how we want the iterator passed in to be modified.
It can either be 'left alone' and point to the same stmt, or it can point to the
new stmt which was created. I thought about seperate routines, but couldn't 
think of decent concise names, so this seemed reasonably clear.

  void tsi_delink (tree_stmt_iterator *)

The iterator is updated to point to the next statement after the one delinked.

  typedef tree tree_stmt_anchor;
  tree_stmt_iterator tsi_new_stmt_list  (tree, tree_stmt_anchor *)

An anchor is simply something which starts a stmt list. Currently, its simply
a tree pointer, but down the road, an implementation of trees could 
conceivably have the links outside the tree node. In this case an anchor would 
be something else. At some point, child stmt lists will have to be 
tree_anchor's instead of trees as they are now. But for the moment I haven't 
done anything about it, thats an issue to deal with once we have an interface
we like.  The routine tsi_new_stmt_list initializes a tree_stmt_anchor to 
an initial tree stmt.

  tree_stmt_iterator tsi_stmt_list_head (tree_stmt_anchor)

Given an anchor, returns an iterator to the first stmt.


These routines have been modestly tested, but not extensively. So far, they 
aren't actually being used by anything. Its important to note that using these
routines and the tsi_stmt_iterator, you will never see a CE node, it should
always be under the covers.

---------

I modified bsi_remove() to pass in the address of the iterator, and
update it to the next statement. Previously, stmts were being removed,
and the iterator bumped after removal... If we actually delinked the
stmt under the covers when removing it, then our bumping would then be
broken. I think its cleaner to have the bsi_remove routine update the
iterator itself.

I've added a sbitmap_realloc routine. When we add basic blocks or new
variables during insertion, we have some bitmaps that need to grow as well. I
was suprised there wasn't a realloc routine already, but oh well.

Although the implementation's aren't included in this patch, the prototypes
for the bsi_insert routines are present. The implementations will follow 
before long.

Anyway, this all bootstraps, and doesn't seem to cause any new errors.

So, is this OK, or are there a few things we'd like to change? :-)

Andrew


	* Makefile.in (tree.o): Add tree-iterator.h dependancy.
	* sbitmap.c (sbitmap_realloc): Grow a sbitmap structure. 
	* sbitmap.h (sbitmap_realloc): New Prototype.
	* tree-cfg.c (remove_bb): Use new format for bsi_remove.
	(bsi_remove): Update iterator to refer to the next stmt.
	(bsi_prev): Implement previous stmt routine.
	(bsi_from_tsi): Create a block iterator from a tree iterator.
	* tree-flow-inline.h (bsi_prev): Remove.
	(tsi_from_bsi): Create a tree iterator from a block iterator.
	* tree-flow.h (bsi_prev,bsi_remove): Update prototypes.
	(bsi_from_tsi, tsi_from_bsi, bsi_insert_*): New prototypes.
	(bsi_iterator_update): New enum type.
	* tree-iterator.h (tree_stmt_anchor, tsi_iterator_update): New type.
	(tsi_link_before, tsi_link_after, tsi_delink, tsi_new_stmt_list,
	tsi_stmt_list_head): New prototypes.
	* tree-ssa-dce.c (remove_dead_stmts): Update removal loop to allow
	that remove_dead_stmt update's the iterator.
	(remove_dead_stmt): Use a pointer to the iterator since bsi_remove
	requires it.
	* tree.c (tsi_link_before): New function to link a stmt before an
	iterator.
	(tsi_link_after): New function links stmt after an iterator.
	(tsi_delink): Removes a stmt from a list.
	(tsi_new_stmt_list): New function to begin a new stmt list.
	(tsi_stmt_list_head): New function to get the first stmt in a list.





Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.77
diff -c -p -r1.903.2.77 Makefile.in
*** Makefile.in	2 Mar 2003 19:58:40 -0000	1.903.2.77
--- Makefile.in	5 Mar 2003 19:05:49 -0000
*************** langhooks.o : langhooks.c $(CONFIG_H) $(
*** 1430,1436 ****
     $(LANGHOOKS_DEF_H) flags.h
  tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h function.h \
     toplev.h $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
!    real.h gt-tree.h
  tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     $(C_TREE_H) flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
     $(EXPR_H) $(SPLAY_TREE_H) $(TREE_DUMP_H)
--- 1430,1436 ----
     $(LANGHOOKS_DEF_H) flags.h
  tree.o : tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) flags.h function.h \
     toplev.h $(GGC_H) $(HASHTAB_H) $(TARGET_H) output.h $(TM_P_H) langhooks.h \
!    real.h gt-tree.h tree-iterator.h
  tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     $(C_TREE_H) flags.h langhooks.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
     $(EXPR_H) $(SPLAY_TREE_H) $(TREE_DUMP_H)
Index: sbitmap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sbitmap.c,v
retrieving revision 1.21.2.4
diff -c -p -r1.21.2.4 sbitmap.c
*** sbitmap.c	23 Feb 2003 22:03:06 -0000	1.21.2.4
--- sbitmap.c	5 Mar 2003 19:05:50 -0000
*************** sbitmap_resize (bmap, n_elms, def)
*** 107,112 ****
--- 107,140 ----
    return bmap;
  }
  
+ /* Re-allocate a simple bitmap of N_ELMS bits. New storage is uninitialized.   */
+ 
+ sbitmap
+ sbitmap_realloc (src, n_elms)
+      sbitmap src;
+      unsigned int n_elms;
+ {
+   unsigned int bytes, size, amt;
+   sbitmap bmap;
+ 
+   size = SBITMAP_SET_SIZE (n_elms);
+   bytes = size * sizeof (SBITMAP_ELT_TYPE);
+   amt = (sizeof (struct simple_bitmap_def)
+ 	 + bytes - sizeof (SBITMAP_ELT_TYPE));
+ 
+   if (src->bytes  >= bytes)
+     {
+       src->n_bits = n_elms;
+       return src;
+     }
+ 
+   bmap = (sbitmap) xrealloc (src, amt);
+   bmap->n_bits = n_elms;
+   bmap->size = size;
+   bmap->bytes = bytes;
+   return bmap;
+ }
+ 
  /* Allocate a vector of N_VECS bitmaps of N_ELMS bits.  */
  
  sbitmap *
Index: sbitmap.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sbitmap.h,v
retrieving revision 1.17.2.2
diff -c -p -r1.17.2.2 sbitmap.h
*** sbitmap.h	23 Feb 2003 22:03:06 -0000	1.17.2.2
--- sbitmap.h	5 Mar 2003 19:05:50 -0000
*************** extern void dump_sbitmap_vector 	PARAMS 
*** 124,129 ****
--- 124,130 ----
  						 const char *, sbitmap *,
  						 int));
  extern sbitmap sbitmap_alloc		PARAMS ((unsigned int));
+ extern sbitmap sbitmap_realloc		PARAMS ((sbitmap, unsigned int));
  extern sbitmap *sbitmap_vector_alloc	PARAMS ((unsigned int, unsigned int));
  extern sbitmap sbitmap_resize		PARAMS ((sbitmap, unsigned int, int));
  extern void sbitmap_copy 		PARAMS ((sbitmap, sbitmap));
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.57
diff -c -p -r1.1.4.57 tree-cfg.c
*** tree-cfg.c	25 Feb 2003 13:28:24 -0000	1.1.4.57
--- tree-cfg.c	5 Mar 2003 19:05:51 -0000
*************** remove_bb (bb, remove_stmts)
*** 1015,1027 ****
      }
  
    /* Remove all the instructions in the block.  */
!   for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
      {
        tree stmt = bsi_stmt (i);
  
        set_bb_for_stmt (stmt, NULL);
        if (remove_stmts)
! 	bsi_remove (i);
      }
  
    set_bb_for_stmt (*bb->head_tree_p, NULL);
--- 1015,1029 ----
      }
  
    /* Remove all the instructions in the block.  */
!   for (i = bsi_start (bb); !bsi_end_p (i); )
      {
        tree stmt = bsi_stmt (i);
  
        set_bb_for_stmt (stmt, NULL);
        if (remove_stmts)
! 	bsi_remove (&i);
!       else
!         bsi_next (&i);
      }
  
    set_bb_for_stmt (*bb->head_tree_p, NULL);
*************** is_parent (bb, child_bb)
*** 1173,1181 ****
  
  void
  bsi_remove (i)
!      block_stmt_iterator i;
  {
!   tree t = *(i.tp);
  
    STRIP_NOPS (t);
  
--- 1175,1183 ----
  
  void
  bsi_remove (i)
!      block_stmt_iterator *i;
  {
!   tree t = *(i->tp);
  
    STRIP_NOPS (t);
  
*************** bsi_remove (i)
*** 1188,1197 ****
  
        /* If both operands are empty, delete the whole COMPOUND_EXPR.  */
        if (TREE_OPERAND (t, 1) == empty_stmt_node)
! 	remove_stmt (i.tp);
      }
    else
!     remove_stmt (i.tp);
  }
  
  
--- 1190,1201 ----
  
        /* If both operands are empty, delete the whole COMPOUND_EXPR.  */
        if (TREE_OPERAND (t, 1) == empty_stmt_node)
! 	remove_stmt (i->tp);
      }
    else
!     remove_stmt (i->tp);
! 
!   bsi_next (i);
  }
  
  
*************** bsi_start (bb)
*** 2414,2419 ****
--- 2418,2475 ----
    return i;
  }
  
+ /* Find the previous iterator value.  */
+ 
+ void
+ bsi_prev (i)
+      block_stmt_iterator *i;
+ {
+   block_stmt_iterator bi, next;
+ 
+   bi = bsi_start (bb_for_stmt (bsi_stmt (*i))); 
+   if (bi.tp != i->tp)
+     {
+       for ( ; !bsi_end_p (bi); bi = next)
+ 	{
+ 	  next = bi; 
+ 	  bsi_next (&next);
+ 	  if (next.tp == i->tp)
+ 	    {
+ 	      i->tp = bi.tp;
+ 	      return;
+ 	    }
+ 	}
+     }
+ 
+   i->tp = NULL;
+   bi.context = NULL_TREE;
+   return;
+ }
+ 
+ 
+ /* Initialize a block_stmt_iterator with a statement pointed to by a tree
+    iterator. If this cannot be done, a NULL iterator is returned.  */
+ 
+ block_stmt_iterator
+ bsi_from_tsi (ti)
+      tree_stmt_iterator ti;
+ {
+   basic_block bb;
+   tree stmt;
+   block_stmt_iterator bi;
+ 
+   stmt = tsi_stmt (ti);
+   if (stmt)
+     {
+       bb = bb_for_stmt (stmt);
+       if (bb)
+ 	return bsi_init (ti.tp, bb);
+     }
+ 
+   bi.tp = NULL;
+   bi.context = NULL_TREE;
+   return bi;
+ }
  
  /* Insert statement T into basic block BB.  */
  
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.28
diff -c -p -r1.1.2.28 tree-flow-inline.h
*** tree-flow-inline.h	25 Feb 2003 13:28:24 -0000	1.1.2.28
--- tree-flow-inline.h	5 Mar 2003 19:05:51 -0000
*************** bsi_next (i)
*** 355,368 ****
    bsi_next_in_bb (i, bb);
  }
  
- static inline void
- bsi_prev (i)
-      block_stmt_iterator *i;
- {
-   printf (" bsi_prev (%p) is not implemented yet\n",(void *)i);
-   abort();
- }
- 
  static inline tree *
  bsi_stmt_ptr (i)
       block_stmt_iterator i;
--- 355,360 ----
*************** bsi_container (i)
*** 399,404 ****
--- 391,405 ----
       block_stmt_iterator i;
  {
    return i.tp;
+ }
+ 
+ /* Return a tree_stmt_iterator for the stmt a block iterator refers to.  */
+ 
+ static inline tree_stmt_iterator
+ tsi_from_bsi (bi)
+      block_stmt_iterator bi;
+ {
+   return tsi_start (bi.tp);
  }
  
  static inline bool
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.60
diff -c -p -r1.1.4.60 tree-flow.h
*** tree-flow.h	1 Mar 2003 00:09:07 -0000	1.1.4.60
--- tree-flow.h	5 Mar 2003 19:05:51 -0000
*************** typedef struct {
*** 275,286 ****
  extern block_stmt_iterator bsi_start 	PARAMS ((basic_block));
  static inline bool bsi_end_p		PARAMS ((block_stmt_iterator));
  static inline void bsi_next		PARAMS ((block_stmt_iterator *));
! static inline void bsi_prev		PARAMS ((block_stmt_iterator *));
  static inline tree bsi_stmt		PARAMS ((block_stmt_iterator));
  static inline tree *bsi_stmt_ptr	PARAMS ((block_stmt_iterator));
  static inline tree *bsi_container	PARAMS ((block_stmt_iterator));
  
! extern void bsi_remove			PARAMS ((block_stmt_iterator));
  
  void bsi_next_in_bb			PARAMS ((block_stmt_iterator *, basic_block));
  
--- 275,307 ----
  extern block_stmt_iterator bsi_start 	PARAMS ((basic_block));
  static inline bool bsi_end_p		PARAMS ((block_stmt_iterator));
  static inline void bsi_next		PARAMS ((block_stmt_iterator *));
! extern void bsi_prev			PARAMS ((block_stmt_iterator *));
  static inline tree bsi_stmt		PARAMS ((block_stmt_iterator));
  static inline tree *bsi_stmt_ptr	PARAMS ((block_stmt_iterator));
  static inline tree *bsi_container	PARAMS ((block_stmt_iterator));
  
! extern block_stmt_iterator bsi_from_tsi	PARAMS ((tree_stmt_iterator));
! static inline tree_stmt_iterator tsi_from_bsi	PARAMS ((block_stmt_iterator));
! 
! extern void bsi_remove			PARAMS ((block_stmt_iterator *));
! 
! enum bsi_iterator_update
! {
!   BSI_NEW_STMT,
!   BSI_SAME_STMT
! };
! 
! /* Single stmt insertion routines.  */
! 
! extern void bsi_insert_before	PARAMS ((block_stmt_iterator *, tree, enum bsi_iterator_update));
! extern void bsi_insert_after	PARAMS ((block_stmt_iterator *, tree, enum bsi_iterator_update));
! extern block_stmt_iterator bsi_insert_on_edge	PARAMS ((edge, tree));
! 
! /* Stmt list insertion routines.  */
! 
! extern void bsi_insert_list_before	PARAMS ((block_stmt_iterator *, tree_stmt_anchor));
! extern void bsi_insert_list_after	PARAMS ((block_stmt_iterator *, tree_stmt_anchor));
! extern block_stmt_iterator bsi_insert_list_on_edge	PARAMS ((edge, tree_stmt_anchor));
  
  void bsi_next_in_bb			PARAMS ((block_stmt_iterator *, basic_block));
  
Index: tree-iterator.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-iterator.h,v
retrieving revision 1.1.2.1
diff -c -p -r1.1.2.1 tree-iterator.h
*** tree-iterator.h	6 Feb 2003 04:41:05 -0000	1.1.2.1
--- tree-iterator.h	5 Mar 2003 19:05:51 -0000
*************** tsi_container (i)
*** 127,130 ****
--- 127,149 ----
    return i.tp;
  }
  
+ 
+ /* Abstract interface for linking and chaining stmts.  Declared in tree.c.  */
+ 
+ /* A tree_stmt_anchor is used as the root of a stmt list.  */
+ typedef tree tree_stmt_anchor;
+ #define EMPTY_ANCHOR	NULL_TREE
+ 
+ enum tsi_iterator_update
+ {
+   TSI_NEW_STMT,
+   TSI_SAME_STMT
+ };
+ 
+ void tsi_link_before			PARAMS ((tree_stmt_iterator *, tree, enum tsi_iterator_update));
+ void tsi_link_after			PARAMS ((tree_stmt_iterator *, tree, enum tsi_iterator_update));
+ void tsi_delink				PARAMS ((tree_stmt_iterator *));
+ tree_stmt_iterator tsi_new_stmt_list	PARAMS ((tree, tree_stmt_anchor *));
+ tree_stmt_iterator tsi_stmt_list_head	PARAMS ((tree_stmt_anchor));
+ 
  #endif /* _TREE_ITERATOR_H  */
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.29
diff -c -p -r1.1.2.29 tree-ssa-dce.c
*** tree-ssa-dce.c	25 Feb 2003 13:28:25 -0000	1.1.2.29
--- tree-ssa-dce.c	5 Mar 2003 19:05:51 -0000
*************** static void find_useful_stmts			PARAMS (
*** 91,97 ****
  static bool stmt_useful_p			PARAMS ((tree));
  static void process_worklist			PARAMS ((void));
  static void remove_dead_stmts			PARAMS ((void));
! static void remove_dead_stmt			PARAMS ((block_stmt_iterator,
        							 basic_block));
  static void remove_dead_phis			PARAMS ((basic_block));
  
--- 91,97 ----
  static bool stmt_useful_p			PARAMS ((tree));
  static void process_worklist			PARAMS ((void));
  static void remove_dead_stmts			PARAMS ((void));
! static void remove_dead_stmt			PARAMS ((block_stmt_iterator *,
        							 basic_block));
  static void remove_dead_phis			PARAMS ((basic_block));
  
*************** remove_dead_stmts ()
*** 413,426 ****
        remove_dead_phis (bb);
  
        /* Remove dead statements.  */
!       for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
  	{
  	  t = bsi_stmt (i);
  	  stats.total++;
  
  	  /* If `i' is not in `necessary' then remove from B.  */
  	  if (!necessary_p (t))
! 	    remove_dead_stmt (i, bb);
  	}
      }
  
--- 413,428 ----
        remove_dead_phis (bb);
  
        /* Remove dead statements.  */
!       for (i = bsi_start (bb); !bsi_end_p (i); )
  	{
  	  t = bsi_stmt (i);
  	  stats.total++;
  
  	  /* If `i' is not in `necessary' then remove from B.  */
  	  if (!necessary_p (t))
! 	    remove_dead_stmt (&i, bb);
! 	  else
! 	    bsi_next (&i);
  	}
      }
  
*************** remove_dead_phis (bb)
*** 464,475 ****
  
  static void
  remove_dead_stmt (i, bb)
!      block_stmt_iterator i;
       basic_block bb;
  {
    tree t;
  
!   t = bsi_stmt (i);
    STRIP_NOPS (t);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
--- 466,477 ----
  
  static void
  remove_dead_stmt (i, bb)
!      block_stmt_iterator *i;
       basic_block bb;
  {
    tree t;
  
!   t = bsi_stmt (*i);
    STRIP_NOPS (t);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.263.2.24
diff -c -p -r1.263.2.24 tree.c
*** tree.c	23 Feb 2003 22:03:06 -0000	1.263.2.24
--- tree.c	5 Mar 2003 19:05:54 -0000
*************** Software Foundation, 59 Temple Place - S
*** 45,50 ****
--- 45,51 ----
  #include "output.h"
  #include "target.h"
  #include "langhooks.h"
+ #include "tree-iterator.h"
  
  /* obstack.[ch] explicitly declined to prototype this.  */
  extern int _obstack_allocated_p PARAMS ((struct obstack *h, PTR obj));
*************** build_vdef_expr (var)
*** 4957,4962 ****
--- 4958,5092 ----
      abort ();
  
    return build (VDEF_EXPR, TREE_TYPE (var), var, var);
+ }
+ 
+ 
+ 
+ /* Links a stmt before the current stmt.  */
+ 
+ void
+ tsi_link_before (i, t, mode)
+      tree_stmt_iterator *i;
+      tree t;
+      enum tsi_iterator_update mode;
+ {
+   tree ce;
+ 
+   /* Build a new CE which points to the current node.  */
+   ce = build (COMPOUND_EXPR, void_type_node, t, *(i->tp));
+ 
+   /* Make the parent pointer point to this new node.  At this point, the
+      iterator will be pointing to the new node we just inserted.  */
+   *(i->tp) = ce;
+ 
+   /* Update the iterator to points to the address of the next ptr in our new 
+      node, which is the current stmt again.  */
+   if (mode == TSI_SAME_STMT)
+     i->tp = &(TREE_OPERAND (*(i->tp), 1));
+ 
+ }
+ 
+ /* Links a stmt after the current stmt.  */
+ 
+ void
+ tsi_link_after (i, t, mode)
+      tree_stmt_iterator *i;
+      tree t;
+      enum tsi_iterator_update mode;
+ {
+   tree ce;
+   tree next;
+ 
+   /* If this node isnt a COMPUND_EXPR, we need to insert a CE node. */
+   if (TREE_CODE (*(i->tp)) != COMPOUND_EXPR)
+     {
+       /* Create a new node with the current stmt on the left, and the new
+ 	 stmt on the right.  */
+       ce = build (COMPOUND_EXPR, void_type_node, *(i->tp), t);
+ 
+       /* Update link to point to this CE node.  */
+       *(i->tp) = ce;
+ 
+       /* Change new iterator to point to the new stmt.  */
+       if (mode == TSI_NEW_STMT)
+ 	i->tp = &(TREE_OPERAND (ce, 1));
+     }
+   else
+     {
+       next  = TREE_OPERAND (*(i->tp), 1);
+ 
+       /* Create a new node with the same 'next' link as the current one.  */
+       ce = build (COMPOUND_EXPR, void_type_node, t, next);
+ 
+       /* Make the current one's 'next' link point to our new stmt.  */
+       TREE_OPERAND (*(i->tp), 1) = ce;
+ 
+       /* Update the iterator to the new stmt.  */
+       if (mode == TSI_NEW_STMT)
+ 	i->tp = &(TREE_OPERAND (*(i->tp), 1));
+     }
+ 
+   
+ }
+ 
+ /* Remove a stmt from the tree list.  The iterator is updated to point to
+    the next stmt.  */
+ 
+ void
+ tsi_delink (i)
+      tree_stmt_iterator *i;
+ {
+ 
+   if (TREE_CODE (*(i->tp)) == COMPOUND_EXPR)
+     {
+       /* All that is needed here is to change the parent to point to the next 
+ 	 stmt in the chain.  */
+       *(i->tp) = TREE_OPERAND (*(i->tp), 1);
+     }
+   else
+     {
+       /* This stmt is the last link in the CE chain, but we're screwed because
+          there isn't access to the node itself. the choices are either adding a
+ 	 NULL link to the right side of the CE node, which is bad, or replacing
+ 	 this node with an empty_stmt_node. Choose the latter for now, and 
+ 	 make the iterator return NULL, so that no further iterating takes 
+ 	 place.  */
+       *(i->tp) = empty_stmt_node;
+       i->tp = NULL;
+     }
+ }
+ 
+ /* Create a new stmt list beginning with this stmt.  The anchor is used mostly
+    to keep the garbage collector from collecting the root node, and to give 
+    the list a place to start.  */
+ 
+ tree_stmt_iterator 
+ tsi_new_stmt_list (t, anchor)
+      tree t;
+      tree_stmt_anchor *anchor;
+ {
+   tree_stmt_iterator i;
+ 
+   *anchor = t;
+   i.tp = anchor;
+ 
+   return i;
+ }
+ 
+ /* Return an iterator which begins at this anchor.  */
+ 
+ tree_stmt_iterator
+ tsi_stmt_list_head (anchor)
+      tree_stmt_anchor anchor;
+ {
+   tree_stmt_iterator i;
+ 
+   if (anchor == EMPTY_ANCHOR)
+     i.tp = NULL;
+   else
+     i.tp = &anchor;
+ 
+   return i;
  }
  
  #include "gt-tree.h"





More information about the Gcc-patches mailing list