xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-iterator.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Iterator routines for manipulating GENERIC and GIMPLE tree statements.
2*8feb0f0bSmrg    Copyright (C) 2003-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Andrew MacLeod  <amacleod@redhat.com>
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful,
131debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
141debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151debfc3dSmrg GNU General Public License for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg #include "config.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "tree.h"
251debfc3dSmrg #include "tree-iterator.h"
261debfc3dSmrg 
271debfc3dSmrg 
281debfc3dSmrg /* This is a cache of STATEMENT_LIST nodes.  We create and destroy them
291debfc3dSmrg    fairly often during gimplification.  */
301debfc3dSmrg 
311debfc3dSmrg static GTY ((deletable (""))) vec<tree, va_gc> *stmt_list_cache;
321debfc3dSmrg 
331debfc3dSmrg tree
alloc_stmt_list(void)341debfc3dSmrg alloc_stmt_list (void)
351debfc3dSmrg {
361debfc3dSmrg   tree list;
371debfc3dSmrg   if (!vec_safe_is_empty (stmt_list_cache))
381debfc3dSmrg     {
391debfc3dSmrg       list = stmt_list_cache->pop ();
401debfc3dSmrg       memset (list, 0, sizeof (struct tree_base));
411debfc3dSmrg       TREE_SET_CODE (list, STATEMENT_LIST);
421debfc3dSmrg     }
431debfc3dSmrg   else
44a2dc1f3fSmrg     {
451debfc3dSmrg       list = make_node (STATEMENT_LIST);
46a2dc1f3fSmrg       TREE_SIDE_EFFECTS (list) = 0;
47a2dc1f3fSmrg     }
481debfc3dSmrg   TREE_TYPE (list) = void_type_node;
491debfc3dSmrg   return list;
501debfc3dSmrg }
511debfc3dSmrg 
521debfc3dSmrg void
free_stmt_list(tree t)531debfc3dSmrg free_stmt_list (tree t)
541debfc3dSmrg {
551debfc3dSmrg   gcc_assert (!STATEMENT_LIST_HEAD (t));
561debfc3dSmrg   gcc_assert (!STATEMENT_LIST_TAIL (t));
571debfc3dSmrg   vec_safe_push (stmt_list_cache, t);
581debfc3dSmrg }
591debfc3dSmrg 
601debfc3dSmrg /* A subroutine of append_to_statement_list{,_force}.  T is not NULL.  */
611debfc3dSmrg 
621debfc3dSmrg static void
append_to_statement_list_1(tree t,tree * list_p)631debfc3dSmrg append_to_statement_list_1 (tree t, tree *list_p)
641debfc3dSmrg {
651debfc3dSmrg   tree list = *list_p;
661debfc3dSmrg   tree_stmt_iterator i;
671debfc3dSmrg 
681debfc3dSmrg   if (!list)
691debfc3dSmrg     {
701debfc3dSmrg       if (t && TREE_CODE (t) == STATEMENT_LIST)
711debfc3dSmrg 	{
721debfc3dSmrg 	  *list_p = t;
731debfc3dSmrg 	  return;
741debfc3dSmrg 	}
751debfc3dSmrg       *list_p = list = alloc_stmt_list ();
761debfc3dSmrg     }
771debfc3dSmrg   else if (TREE_CODE (list) != STATEMENT_LIST)
781debfc3dSmrg     {
791debfc3dSmrg       tree first = list;
801debfc3dSmrg       *list_p = list = alloc_stmt_list ();
811debfc3dSmrg       i = tsi_last (list);
821debfc3dSmrg       tsi_link_after (&i, first, TSI_CONTINUE_LINKING);
831debfc3dSmrg     }
841debfc3dSmrg 
851debfc3dSmrg   i = tsi_last (list);
861debfc3dSmrg   tsi_link_after (&i, t, TSI_CONTINUE_LINKING);
871debfc3dSmrg }
881debfc3dSmrg 
891debfc3dSmrg /* Add T to the end of the list container pointed to by LIST_P.
901debfc3dSmrg    If T is an expression with no effects, it is ignored.  */
911debfc3dSmrg 
921debfc3dSmrg void
append_to_statement_list(tree t,tree * list_p)931debfc3dSmrg append_to_statement_list (tree t, tree *list_p)
941debfc3dSmrg {
95a2dc1f3fSmrg   if (t && (TREE_SIDE_EFFECTS (t) || TREE_CODE (t) == DEBUG_BEGIN_STMT))
961debfc3dSmrg     append_to_statement_list_1 (t, list_p);
971debfc3dSmrg }
981debfc3dSmrg 
991debfc3dSmrg /* Similar, but the statement is always added, regardless of side effects.  */
1001debfc3dSmrg 
1011debfc3dSmrg void
append_to_statement_list_force(tree t,tree * list_p)1021debfc3dSmrg append_to_statement_list_force (tree t, tree *list_p)
1031debfc3dSmrg {
1041debfc3dSmrg   if (t != NULL_TREE)
1051debfc3dSmrg     append_to_statement_list_1 (t, list_p);
1061debfc3dSmrg }
1071debfc3dSmrg 
1081debfc3dSmrg /* Links a statement, or a chain of statements, before the current stmt.  */
1091debfc3dSmrg 
1101debfc3dSmrg void
tsi_link_before(tree_stmt_iterator * i,tree t,enum tsi_iterator_update mode)1111debfc3dSmrg tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
1121debfc3dSmrg {
1131debfc3dSmrg   struct tree_statement_list_node *head, *tail, *cur;
1141debfc3dSmrg 
1151debfc3dSmrg   /* Die on looping.  */
1161debfc3dSmrg   gcc_assert (t != i->container);
1171debfc3dSmrg 
1181debfc3dSmrg   if (TREE_CODE (t) == STATEMENT_LIST)
1191debfc3dSmrg     {
1201debfc3dSmrg       head = STATEMENT_LIST_HEAD (t);
1211debfc3dSmrg       tail = STATEMENT_LIST_TAIL (t);
1221debfc3dSmrg       STATEMENT_LIST_HEAD (t) = NULL;
1231debfc3dSmrg       STATEMENT_LIST_TAIL (t) = NULL;
1241debfc3dSmrg 
1251debfc3dSmrg       free_stmt_list (t);
1261debfc3dSmrg 
1271debfc3dSmrg       /* Empty statement lists need no work.  */
1281debfc3dSmrg       if (!head || !tail)
1291debfc3dSmrg 	{
1301debfc3dSmrg 	  gcc_assert (head == tail);
1311debfc3dSmrg 	  return;
1321debfc3dSmrg 	}
1331debfc3dSmrg     }
1341debfc3dSmrg   else
1351debfc3dSmrg     {
1361debfc3dSmrg       head = ggc_alloc<tree_statement_list_node> ();
1371debfc3dSmrg       head->prev = NULL;
1381debfc3dSmrg       head->next = NULL;
1391debfc3dSmrg       head->stmt = t;
1401debfc3dSmrg       tail = head;
1411debfc3dSmrg     }
1421debfc3dSmrg 
143a2dc1f3fSmrg   if (TREE_CODE (t) != DEBUG_BEGIN_STMT)
1441debfc3dSmrg     TREE_SIDE_EFFECTS (i->container) = 1;
1451debfc3dSmrg 
1461debfc3dSmrg   cur = i->ptr;
1471debfc3dSmrg 
1481debfc3dSmrg   /* Link it into the list.  */
1491debfc3dSmrg   if (cur)
1501debfc3dSmrg     {
1511debfc3dSmrg       head->prev = cur->prev;
1521debfc3dSmrg       if (head->prev)
1531debfc3dSmrg 	head->prev->next = head;
1541debfc3dSmrg       else
1551debfc3dSmrg 	STATEMENT_LIST_HEAD (i->container) = head;
1561debfc3dSmrg       tail->next = cur;
1571debfc3dSmrg       cur->prev = tail;
1581debfc3dSmrg     }
1591debfc3dSmrg   else
1601debfc3dSmrg     {
1611debfc3dSmrg       head->prev = STATEMENT_LIST_TAIL (i->container);
1621debfc3dSmrg       if (head->prev)
1631debfc3dSmrg        head->prev->next = head;
1641debfc3dSmrg       else
1651debfc3dSmrg        STATEMENT_LIST_HEAD (i->container) = head;
1661debfc3dSmrg       STATEMENT_LIST_TAIL (i->container) = tail;
1671debfc3dSmrg     }
1681debfc3dSmrg 
1691debfc3dSmrg   /* Update the iterator, if requested.  */
1701debfc3dSmrg   switch (mode)
1711debfc3dSmrg     {
1721debfc3dSmrg     case TSI_NEW_STMT:
1731debfc3dSmrg     case TSI_CONTINUE_LINKING:
1741debfc3dSmrg     case TSI_CHAIN_START:
1751debfc3dSmrg       i->ptr = head;
1761debfc3dSmrg       break;
1771debfc3dSmrg     case TSI_CHAIN_END:
1781debfc3dSmrg       i->ptr = tail;
1791debfc3dSmrg       break;
1801debfc3dSmrg     case TSI_SAME_STMT:
1811debfc3dSmrg       break;
1821debfc3dSmrg     }
1831debfc3dSmrg }
1841debfc3dSmrg 
1851debfc3dSmrg /* Links a statement, or a chain of statements, after the current stmt.  */
1861debfc3dSmrg 
1871debfc3dSmrg void
tsi_link_after(tree_stmt_iterator * i,tree t,enum tsi_iterator_update mode)1881debfc3dSmrg tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
1891debfc3dSmrg {
1901debfc3dSmrg   struct tree_statement_list_node *head, *tail, *cur;
1911debfc3dSmrg 
1921debfc3dSmrg   /* Die on looping.  */
1931debfc3dSmrg   gcc_assert (t != i->container);
1941debfc3dSmrg 
1951debfc3dSmrg   if (TREE_CODE (t) == STATEMENT_LIST)
1961debfc3dSmrg     {
1971debfc3dSmrg       head = STATEMENT_LIST_HEAD (t);
1981debfc3dSmrg       tail = STATEMENT_LIST_TAIL (t);
1991debfc3dSmrg       STATEMENT_LIST_HEAD (t) = NULL;
2001debfc3dSmrg       STATEMENT_LIST_TAIL (t) = NULL;
2011debfc3dSmrg 
2021debfc3dSmrg       free_stmt_list (t);
2031debfc3dSmrg 
2041debfc3dSmrg       /* Empty statement lists need no work.  */
2051debfc3dSmrg       if (!head || !tail)
2061debfc3dSmrg 	{
2071debfc3dSmrg 	  gcc_assert (head == tail);
2081debfc3dSmrg 	  return;
2091debfc3dSmrg 	}
2101debfc3dSmrg     }
2111debfc3dSmrg   else
2121debfc3dSmrg     {
2131debfc3dSmrg       head = ggc_alloc<tree_statement_list_node> ();
2141debfc3dSmrg       head->prev = NULL;
2151debfc3dSmrg       head->next = NULL;
2161debfc3dSmrg       head->stmt = t;
2171debfc3dSmrg       tail = head;
2181debfc3dSmrg     }
2191debfc3dSmrg 
220a2dc1f3fSmrg   if (TREE_CODE (t) != DEBUG_BEGIN_STMT)
2211debfc3dSmrg     TREE_SIDE_EFFECTS (i->container) = 1;
2221debfc3dSmrg 
2231debfc3dSmrg   cur = i->ptr;
2241debfc3dSmrg 
2251debfc3dSmrg   /* Link it into the list.  */
2261debfc3dSmrg   if (cur)
2271debfc3dSmrg     {
2281debfc3dSmrg       tail->next = cur->next;
2291debfc3dSmrg       if (tail->next)
2301debfc3dSmrg 	tail->next->prev = tail;
2311debfc3dSmrg       else
2321debfc3dSmrg 	STATEMENT_LIST_TAIL (i->container) = tail;
2331debfc3dSmrg       head->prev = cur;
2341debfc3dSmrg       cur->next = head;
2351debfc3dSmrg     }
2361debfc3dSmrg   else
2371debfc3dSmrg     {
2381debfc3dSmrg       gcc_assert (!STATEMENT_LIST_TAIL (i->container));
2391debfc3dSmrg       STATEMENT_LIST_HEAD (i->container) = head;
2401debfc3dSmrg       STATEMENT_LIST_TAIL (i->container) = tail;
2411debfc3dSmrg     }
2421debfc3dSmrg 
2431debfc3dSmrg   /* Update the iterator, if requested.  */
2441debfc3dSmrg   switch (mode)
2451debfc3dSmrg     {
2461debfc3dSmrg     case TSI_NEW_STMT:
2471debfc3dSmrg     case TSI_CHAIN_START:
2481debfc3dSmrg       i->ptr = head;
2491debfc3dSmrg       break;
2501debfc3dSmrg     case TSI_CONTINUE_LINKING:
2511debfc3dSmrg     case TSI_CHAIN_END:
2521debfc3dSmrg       i->ptr = tail;
2531debfc3dSmrg       break;
2541debfc3dSmrg     case TSI_SAME_STMT:
2551debfc3dSmrg       gcc_assert (cur);
2561debfc3dSmrg       break;
2571debfc3dSmrg     }
2581debfc3dSmrg }
2591debfc3dSmrg 
2601debfc3dSmrg /* Remove a stmt from the tree list.  The iterator is updated to point to
2611debfc3dSmrg    the next stmt.  */
2621debfc3dSmrg 
2631debfc3dSmrg void
tsi_delink(tree_stmt_iterator * i)2641debfc3dSmrg tsi_delink (tree_stmt_iterator *i)
2651debfc3dSmrg {
2661debfc3dSmrg   struct tree_statement_list_node *cur, *next, *prev;
2671debfc3dSmrg 
2681debfc3dSmrg   cur = i->ptr;
2691debfc3dSmrg   next = cur->next;
2701debfc3dSmrg   prev = cur->prev;
2711debfc3dSmrg 
2721debfc3dSmrg   if (prev)
2731debfc3dSmrg     prev->next = next;
2741debfc3dSmrg   else
2751debfc3dSmrg     STATEMENT_LIST_HEAD (i->container) = next;
2761debfc3dSmrg   if (next)
2771debfc3dSmrg     next->prev = prev;
2781debfc3dSmrg   else
2791debfc3dSmrg     STATEMENT_LIST_TAIL (i->container) = prev;
2801debfc3dSmrg 
2811debfc3dSmrg   if (!next && !prev)
2821debfc3dSmrg     TREE_SIDE_EFFECTS (i->container) = 0;
2831debfc3dSmrg 
2841debfc3dSmrg   i->ptr = next;
2851debfc3dSmrg }
2861debfc3dSmrg 
287a2dc1f3fSmrg /* Return the first expression in a sequence of COMPOUND_EXPRs, or in
288a2dc1f3fSmrg    a STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a
289a2dc1f3fSmrg    STATEMENT_LIST if that's the first non-DEBUG_BEGIN_STMT.  */
2901debfc3dSmrg 
2911debfc3dSmrg tree
expr_first(tree expr)2921debfc3dSmrg expr_first (tree expr)
2931debfc3dSmrg {
2941debfc3dSmrg   if (expr == NULL_TREE)
2951debfc3dSmrg     return expr;
2961debfc3dSmrg 
2971debfc3dSmrg   if (TREE_CODE (expr) == STATEMENT_LIST)
2981debfc3dSmrg     {
2991debfc3dSmrg       struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
300a2dc1f3fSmrg       if (!n)
301a2dc1f3fSmrg 	return NULL_TREE;
302a2dc1f3fSmrg       while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT)
303a2dc1f3fSmrg 	{
304a2dc1f3fSmrg 	  n = n->next;
305a2dc1f3fSmrg 	  if (!n)
306a2dc1f3fSmrg 	    return NULL_TREE;
307a2dc1f3fSmrg 	}
308a2dc1f3fSmrg       /* If the first non-debug stmt is not a statement list, we
309a2dc1f3fSmrg 	 already know it's what we're looking for.  */
310a2dc1f3fSmrg       if (TREE_CODE (n->stmt) != STATEMENT_LIST)
311a2dc1f3fSmrg 	return n->stmt;
312a2dc1f3fSmrg 
313a2dc1f3fSmrg       return expr_first (n->stmt);
3141debfc3dSmrg     }
3151debfc3dSmrg 
3161debfc3dSmrg   while (TREE_CODE (expr) == COMPOUND_EXPR)
3171debfc3dSmrg     expr = TREE_OPERAND (expr, 0);
3181debfc3dSmrg 
3191debfc3dSmrg   return expr;
3201debfc3dSmrg }
3211debfc3dSmrg 
322a2dc1f3fSmrg /* Return the last expression in a sequence of COMPOUND_EXPRs, or in a
323a2dc1f3fSmrg    STATEMENT_LIST, disregarding DEBUG_BEGIN_STMTs, recursing into a
324a2dc1f3fSmrg    STATEMENT_LIST if that's the last non-DEBUG_BEGIN_STMT.  */
3251debfc3dSmrg 
3261debfc3dSmrg tree
expr_last(tree expr)3271debfc3dSmrg expr_last (tree expr)
3281debfc3dSmrg {
3291debfc3dSmrg   if (expr == NULL_TREE)
3301debfc3dSmrg     return expr;
3311debfc3dSmrg 
3321debfc3dSmrg   if (TREE_CODE (expr) == STATEMENT_LIST)
3331debfc3dSmrg     {
3341debfc3dSmrg       struct tree_statement_list_node *n = STATEMENT_LIST_TAIL (expr);
335a2dc1f3fSmrg       if (!n)
336a2dc1f3fSmrg 	return NULL_TREE;
337a2dc1f3fSmrg       while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT)
338a2dc1f3fSmrg 	{
339a2dc1f3fSmrg 	  n = n->prev;
340a2dc1f3fSmrg 	  if (!n)
341a2dc1f3fSmrg 	    return NULL_TREE;
342a2dc1f3fSmrg 	}
343a2dc1f3fSmrg       /* If the last non-debug stmt is not a statement list, we
344a2dc1f3fSmrg 	 already know it's what we're looking for.  */
345a2dc1f3fSmrg       if (TREE_CODE (n->stmt) != STATEMENT_LIST)
346a2dc1f3fSmrg 	return n->stmt;
347a2dc1f3fSmrg 
348a2dc1f3fSmrg       return expr_last (n->stmt);
3491debfc3dSmrg     }
3501debfc3dSmrg 
3511debfc3dSmrg   while (TREE_CODE (expr) == COMPOUND_EXPR)
3521debfc3dSmrg     expr = TREE_OPERAND (expr, 1);
3531debfc3dSmrg 
3541debfc3dSmrg   return expr;
3551debfc3dSmrg }
3561debfc3dSmrg 
357*8feb0f0bSmrg /* If EXPR is a STATEMENT_LIST containing just DEBUG_BEGIN_STMTs and
358*8feb0f0bSmrg    a single other stmt, return that other stmt (recursively).
359*8feb0f0bSmrg    If it is a STATEMENT_LIST containing no non-DEBUG_BEGIN_STMTs or
360*8feb0f0bSmrg    multiple, return NULL_TREE.
361*8feb0f0bSmrg    Otherwise return EXPR.  */
362*8feb0f0bSmrg 
363*8feb0f0bSmrg tree
expr_single(tree expr)364*8feb0f0bSmrg expr_single (tree expr)
365*8feb0f0bSmrg {
366*8feb0f0bSmrg   if (expr == NULL_TREE)
367*8feb0f0bSmrg     return expr;
368*8feb0f0bSmrg 
369*8feb0f0bSmrg   if (TREE_CODE (expr) == STATEMENT_LIST)
370*8feb0f0bSmrg     {
371*8feb0f0bSmrg       /* With -gstatement-frontiers we could have a STATEMENT_LIST with
372*8feb0f0bSmrg 	 DEBUG_BEGIN_STMT(s) and only a single other stmt, which with
373*8feb0f0bSmrg 	 -g wouldn't be present and we'd have that single other stmt
374*8feb0f0bSmrg 	 directly instead.  */
375*8feb0f0bSmrg       struct tree_statement_list_node *n = STATEMENT_LIST_HEAD (expr);
376*8feb0f0bSmrg       if (!n)
377*8feb0f0bSmrg 	return NULL_TREE;
378*8feb0f0bSmrg       while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT)
379*8feb0f0bSmrg 	{
380*8feb0f0bSmrg 	  n = n->next;
381*8feb0f0bSmrg 	  if (!n)
382*8feb0f0bSmrg 	    return NULL_TREE;
383*8feb0f0bSmrg 	}
384*8feb0f0bSmrg       expr = n->stmt;
385*8feb0f0bSmrg       do
386*8feb0f0bSmrg 	{
387*8feb0f0bSmrg 	  n = n->next;
388*8feb0f0bSmrg 	  if (!n)
389*8feb0f0bSmrg 	    return expr_single (expr);
390*8feb0f0bSmrg 	}
391*8feb0f0bSmrg       while (TREE_CODE (n->stmt) == DEBUG_BEGIN_STMT);
392*8feb0f0bSmrg       return NULL_TREE;
393*8feb0f0bSmrg     }
394*8feb0f0bSmrg 
395*8feb0f0bSmrg   return expr;
396*8feb0f0bSmrg }
397*8feb0f0bSmrg 
3981debfc3dSmrg #include "gt-tree-iterator.h"
399