xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/lists.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* List management for the GCC expander.
2*8feb0f0bSmrg    Copyright (C) 1987-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3.  If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>.  */
191debfc3dSmrg 
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "tm.h"
241debfc3dSmrg #include "rtl.h"
251debfc3dSmrg 
261debfc3dSmrg static void free_list (rtx *, rtx *);
271debfc3dSmrg 
281debfc3dSmrg /* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs.  */
291debfc3dSmrg 
301debfc3dSmrg /* An INSN_LIST containing all INSN_LISTs allocated but currently unused.  */
311debfc3dSmrg static GTY ((deletable)) rtx unused_insn_list;
321debfc3dSmrg 
331debfc3dSmrg /* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused.  */
341debfc3dSmrg static GTY ((deletable)) rtx unused_expr_list;
351debfc3dSmrg 
361debfc3dSmrg /* This function will free an entire list of either EXPR_LIST, INSN_LIST
371debfc3dSmrg    or DEPS_LIST nodes.  This is to be used only on lists that consist
381debfc3dSmrg    exclusively of nodes of one type only.  This is only called by
391debfc3dSmrg    free_EXPR_LIST_list, free_INSN_LIST_list and free_DEPS_LIST_list.  */
401debfc3dSmrg static void
free_list(rtx * listp,rtx * unused_listp)411debfc3dSmrg free_list (rtx *listp, rtx *unused_listp)
421debfc3dSmrg {
431debfc3dSmrg   rtx link, prev_link;
441debfc3dSmrg 
451debfc3dSmrg   prev_link = *listp;
461debfc3dSmrg   link = XEXP (prev_link, 1);
471debfc3dSmrg 
481debfc3dSmrg   gcc_assert (unused_listp != &unused_insn_list
491debfc3dSmrg 	      || GET_CODE (prev_link) == INSN_LIST);
501debfc3dSmrg 
511debfc3dSmrg   while (link)
521debfc3dSmrg     {
531debfc3dSmrg       gcc_assert (unused_listp != &unused_insn_list
541debfc3dSmrg 		  || GET_CODE (prev_link) == INSN_LIST);
551debfc3dSmrg 
561debfc3dSmrg       prev_link = link;
571debfc3dSmrg       link = XEXP (link, 1);
581debfc3dSmrg     }
591debfc3dSmrg 
601debfc3dSmrg   XEXP (prev_link, 1) = *unused_listp;
611debfc3dSmrg   *unused_listp = *listp;
621debfc3dSmrg   *listp = 0;
631debfc3dSmrg }
641debfc3dSmrg 
651debfc3dSmrg /* Find corresponding to ELEM node in the list pointed to by LISTP.
661debfc3dSmrg    This node must exist in the list.  Returns pointer to that node.  */
671debfc3dSmrg static rtx *
find_list_elem(rtx elem,rtx * listp)681debfc3dSmrg find_list_elem (rtx elem, rtx *listp)
691debfc3dSmrg {
701debfc3dSmrg   while (XEXP (*listp, 0) != elem)
711debfc3dSmrg     listp = &XEXP (*listp, 1);
721debfc3dSmrg   return listp;
731debfc3dSmrg }
741debfc3dSmrg 
751debfc3dSmrg /* Remove the node pointed to by LISTP from the list.  */
761debfc3dSmrg static void
remove_list_node(rtx * listp)771debfc3dSmrg remove_list_node (rtx *listp)
781debfc3dSmrg {
791debfc3dSmrg   rtx node;
801debfc3dSmrg 
811debfc3dSmrg   node = *listp;
821debfc3dSmrg   *listp = XEXP (node, 1);
831debfc3dSmrg   XEXP (node, 1) = 0;
841debfc3dSmrg }
851debfc3dSmrg 
861debfc3dSmrg /* Removes corresponding to ELEM node from the list pointed to by LISTP.
871debfc3dSmrg    Returns that node.  */
881debfc3dSmrg rtx
remove_list_elem(rtx elem,rtx * listp)891debfc3dSmrg remove_list_elem (rtx elem, rtx *listp)
901debfc3dSmrg {
911debfc3dSmrg   rtx node;
921debfc3dSmrg 
931debfc3dSmrg   listp = find_list_elem (elem, listp);
941debfc3dSmrg   node = *listp;
951debfc3dSmrg   remove_list_node (listp);
961debfc3dSmrg   return node;
971debfc3dSmrg }
981debfc3dSmrg 
991debfc3dSmrg /* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached
1001debfc3dSmrg    node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
1011debfc3dSmrg    is made.  */
1021debfc3dSmrg rtx_insn_list *
alloc_INSN_LIST(rtx val,rtx next)1031debfc3dSmrg alloc_INSN_LIST (rtx val, rtx next)
1041debfc3dSmrg {
1051debfc3dSmrg   rtx_insn_list *r;
1061debfc3dSmrg 
1071debfc3dSmrg   if (unused_insn_list)
1081debfc3dSmrg     {
1091debfc3dSmrg       r = as_a <rtx_insn_list *> (unused_insn_list);
1101debfc3dSmrg       unused_insn_list = r->next ();
1111debfc3dSmrg       XEXP (r, 0) = val;
1121debfc3dSmrg       XEXP (r, 1) = next;
1131debfc3dSmrg       PUT_REG_NOTE_KIND (r, VOIDmode);
1141debfc3dSmrg 
1151debfc3dSmrg       gcc_assert (GET_CODE (r) == INSN_LIST);
1161debfc3dSmrg     }
1171debfc3dSmrg   else
1181debfc3dSmrg     r = gen_rtx_INSN_LIST (VOIDmode, val, next);
1191debfc3dSmrg 
1201debfc3dSmrg   return r;
1211debfc3dSmrg }
1221debfc3dSmrg 
1231debfc3dSmrg /* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
1241debfc3dSmrg    node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
1251debfc3dSmrg    is made.  */
1261debfc3dSmrg rtx_expr_list *
alloc_EXPR_LIST(int kind,rtx val,rtx next)1271debfc3dSmrg alloc_EXPR_LIST (int kind, rtx val, rtx next)
1281debfc3dSmrg {
1291debfc3dSmrg   rtx_expr_list *r;
1301debfc3dSmrg 
1311debfc3dSmrg   if (unused_expr_list)
1321debfc3dSmrg     {
1331debfc3dSmrg       r = as_a <rtx_expr_list *> (unused_expr_list);
1341debfc3dSmrg       unused_expr_list = XEXP (r, 1);
1351debfc3dSmrg       XEXP (r, 0) = val;
1361debfc3dSmrg       XEXP (r, 1) = next;
1371debfc3dSmrg       PUT_REG_NOTE_KIND (r, kind);
1381debfc3dSmrg     }
1391debfc3dSmrg   else
1401debfc3dSmrg     r = gen_rtx_EXPR_LIST ((machine_mode) kind, val, next);
1411debfc3dSmrg 
1421debfc3dSmrg   return r;
1431debfc3dSmrg }
1441debfc3dSmrg 
1451debfc3dSmrg /* This function will free up an entire list of EXPR_LIST nodes.  */
1461debfc3dSmrg void
free_EXPR_LIST_list(rtx_expr_list ** listp)1471debfc3dSmrg free_EXPR_LIST_list (rtx_expr_list **listp)
1481debfc3dSmrg {
1491debfc3dSmrg   if (*listp == 0)
1501debfc3dSmrg     return;
1511debfc3dSmrg   free_list ((rtx *)listp, &unused_expr_list);
1521debfc3dSmrg }
1531debfc3dSmrg 
1541debfc3dSmrg /* This function will free up an entire list of INSN_LIST nodes.  */
1551debfc3dSmrg void
free_INSN_LIST_list(rtx_insn_list ** listp)1561debfc3dSmrg free_INSN_LIST_list (rtx_insn_list **listp)
1571debfc3dSmrg {
1581debfc3dSmrg   if (*listp == 0)
1591debfc3dSmrg     return;
1601debfc3dSmrg   free_list ((rtx *)listp, &unused_insn_list);
1611debfc3dSmrg }
1621debfc3dSmrg 
1631debfc3dSmrg /* Make a copy of the INSN_LIST list LINK and return it.  */
1641debfc3dSmrg rtx_insn_list *
copy_INSN_LIST(rtx_insn_list * link)1651debfc3dSmrg copy_INSN_LIST (rtx_insn_list *link)
1661debfc3dSmrg {
1671debfc3dSmrg   rtx_insn_list *new_queue;
1681debfc3dSmrg   rtx_insn_list **pqueue = &new_queue;
1691debfc3dSmrg 
1701debfc3dSmrg   for (; link; link = link->next ())
1711debfc3dSmrg     {
1721debfc3dSmrg       rtx_insn *x = link->insn ();
1731debfc3dSmrg       rtx_insn_list *newlink = alloc_INSN_LIST (x, NULL);
1741debfc3dSmrg       *pqueue = newlink;
1751debfc3dSmrg       pqueue = (rtx_insn_list **)&XEXP (newlink, 1);
1761debfc3dSmrg     }
1771debfc3dSmrg   *pqueue = NULL;
1781debfc3dSmrg   return new_queue;
1791debfc3dSmrg }
1801debfc3dSmrg 
1811debfc3dSmrg /* Duplicate the INSN_LIST elements of COPY and prepend them to OLD.  */
1821debfc3dSmrg rtx_insn_list *
concat_INSN_LIST(rtx_insn_list * copy,rtx_insn_list * old)1831debfc3dSmrg concat_INSN_LIST (rtx_insn_list *copy, rtx_insn_list *old)
1841debfc3dSmrg {
1851debfc3dSmrg   rtx_insn_list *new_rtx = old;
1861debfc3dSmrg   for (; copy ; copy = copy->next ())
1871debfc3dSmrg     {
1881debfc3dSmrg       new_rtx = alloc_INSN_LIST (copy->insn (), new_rtx);
1891debfc3dSmrg       PUT_REG_NOTE_KIND (new_rtx, REG_NOTE_KIND (copy));
1901debfc3dSmrg     }
1911debfc3dSmrg   return new_rtx;
1921debfc3dSmrg }
1931debfc3dSmrg 
1941debfc3dSmrg /* This function will free up an individual EXPR_LIST node.  */
1951debfc3dSmrg void
free_EXPR_LIST_node(rtx ptr)1961debfc3dSmrg free_EXPR_LIST_node (rtx ptr)
1971debfc3dSmrg {
1981debfc3dSmrg   XEXP (ptr, 1) = unused_expr_list;
1991debfc3dSmrg   unused_expr_list = ptr;
2001debfc3dSmrg }
2011debfc3dSmrg 
2021debfc3dSmrg /* This function will free up an individual INSN_LIST node.  */
2031debfc3dSmrg void
free_INSN_LIST_node(rtx ptr)2041debfc3dSmrg free_INSN_LIST_node (rtx ptr)
2051debfc3dSmrg {
2061debfc3dSmrg   gcc_assert (GET_CODE (ptr) == INSN_LIST);
2071debfc3dSmrg   XEXP (ptr, 1) = unused_insn_list;
2081debfc3dSmrg   unused_insn_list = ptr;
2091debfc3dSmrg }
2101debfc3dSmrg 
2111debfc3dSmrg /* Remove and free corresponding to ELEM node in the INSN_LIST pointed to
2121debfc3dSmrg    by LISTP.  */
2131debfc3dSmrg void
remove_free_INSN_LIST_elem(rtx_insn * elem,rtx_insn_list ** listp)2141debfc3dSmrg remove_free_INSN_LIST_elem (rtx_insn *elem, rtx_insn_list **listp)
2151debfc3dSmrg {
2161debfc3dSmrg   free_INSN_LIST_node (remove_list_elem (elem, (rtx *)listp));
2171debfc3dSmrg }
2181debfc3dSmrg 
2191debfc3dSmrg /* Remove and free the first node in the INSN_LIST pointed to by LISTP.  */
2201debfc3dSmrg rtx_insn *
remove_free_INSN_LIST_node(rtx_insn_list ** listp)2211debfc3dSmrg remove_free_INSN_LIST_node (rtx_insn_list **listp)
2221debfc3dSmrg {
2231debfc3dSmrg   rtx_insn_list *node = *listp;
2241debfc3dSmrg   rtx_insn *elem = node->insn ();
2251debfc3dSmrg 
2261debfc3dSmrg   remove_list_node ((rtx *)listp);
2271debfc3dSmrg   free_INSN_LIST_node (node);
2281debfc3dSmrg 
2291debfc3dSmrg   return elem;
2301debfc3dSmrg }
2311debfc3dSmrg 
2321debfc3dSmrg /* Remove and free the first node in the EXPR_LIST pointed to by LISTP.  */
2331debfc3dSmrg rtx
remove_free_EXPR_LIST_node(rtx_expr_list ** listp)2341debfc3dSmrg remove_free_EXPR_LIST_node (rtx_expr_list **listp)
2351debfc3dSmrg {
2361debfc3dSmrg   rtx_expr_list *node = *listp;
2371debfc3dSmrg   rtx elem = XEXP (node, 0);
2381debfc3dSmrg 
2391debfc3dSmrg   remove_list_node ((rtx *)listp);
2401debfc3dSmrg   free_EXPR_LIST_node (node);
2411debfc3dSmrg 
2421debfc3dSmrg   return elem;
2431debfc3dSmrg }
2441debfc3dSmrg 
2451debfc3dSmrg #include "gt-lists.h"
246