1*e4b17023SJohn Marino /* List management for the GCC expander.
2*e4b17023SJohn Marino Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3*e4b17023SJohn Marino 1999, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4*e4b17023SJohn Marino Free Software Foundation, Inc.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "diagnostic-core.h"
27*e4b17023SJohn Marino #include "rtl.h"
28*e4b17023SJohn Marino #include "ggc.h"
29*e4b17023SJohn Marino
30*e4b17023SJohn Marino static void free_list (rtx *, rtx *);
31*e4b17023SJohn Marino
32*e4b17023SJohn Marino /* Functions for maintaining cache-able lists of EXPR_LIST and INSN_LISTs. */
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino /* An INSN_LIST containing all INSN_LISTs allocated but currently unused. */
35*e4b17023SJohn Marino static GTY ((deletable)) rtx unused_insn_list;
36*e4b17023SJohn Marino
37*e4b17023SJohn Marino /* An EXPR_LIST containing all EXPR_LISTs allocated but currently unused. */
38*e4b17023SJohn Marino static GTY ((deletable)) rtx unused_expr_list;
39*e4b17023SJohn Marino
40*e4b17023SJohn Marino /* This function will free an entire list of either EXPR_LIST, INSN_LIST
41*e4b17023SJohn Marino or DEPS_LIST nodes. This is to be used only on lists that consist
42*e4b17023SJohn Marino exclusively of nodes of one type only. This is only called by
43*e4b17023SJohn Marino free_EXPR_LIST_list, free_INSN_LIST_list and free_DEPS_LIST_list. */
44*e4b17023SJohn Marino static void
free_list(rtx * listp,rtx * unused_listp)45*e4b17023SJohn Marino free_list (rtx *listp, rtx *unused_listp)
46*e4b17023SJohn Marino {
47*e4b17023SJohn Marino rtx link, prev_link;
48*e4b17023SJohn Marino
49*e4b17023SJohn Marino prev_link = *listp;
50*e4b17023SJohn Marino link = XEXP (prev_link, 1);
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino gcc_assert (unused_listp != &unused_insn_list
53*e4b17023SJohn Marino || GET_CODE (prev_link) == INSN_LIST);
54*e4b17023SJohn Marino
55*e4b17023SJohn Marino while (link)
56*e4b17023SJohn Marino {
57*e4b17023SJohn Marino gcc_assert (unused_listp != &unused_insn_list
58*e4b17023SJohn Marino || GET_CODE (prev_link) == INSN_LIST);
59*e4b17023SJohn Marino
60*e4b17023SJohn Marino prev_link = link;
61*e4b17023SJohn Marino link = XEXP (link, 1);
62*e4b17023SJohn Marino }
63*e4b17023SJohn Marino
64*e4b17023SJohn Marino XEXP (prev_link, 1) = *unused_listp;
65*e4b17023SJohn Marino *unused_listp = *listp;
66*e4b17023SJohn Marino *listp = 0;
67*e4b17023SJohn Marino }
68*e4b17023SJohn Marino
69*e4b17023SJohn Marino /* Find corresponding to ELEM node in the list pointed to by LISTP.
70*e4b17023SJohn Marino This node must exist in the list. Returns pointer to that node. */
71*e4b17023SJohn Marino static rtx *
find_list_elem(rtx elem,rtx * listp)72*e4b17023SJohn Marino find_list_elem (rtx elem, rtx *listp)
73*e4b17023SJohn Marino {
74*e4b17023SJohn Marino while (XEXP (*listp, 0) != elem)
75*e4b17023SJohn Marino listp = &XEXP (*listp, 1);
76*e4b17023SJohn Marino return listp;
77*e4b17023SJohn Marino }
78*e4b17023SJohn Marino
79*e4b17023SJohn Marino /* Remove the node pointed to by LISTP from the list. */
80*e4b17023SJohn Marino static void
remove_list_node(rtx * listp)81*e4b17023SJohn Marino remove_list_node (rtx *listp)
82*e4b17023SJohn Marino {
83*e4b17023SJohn Marino rtx node;
84*e4b17023SJohn Marino
85*e4b17023SJohn Marino node = *listp;
86*e4b17023SJohn Marino *listp = XEXP (node, 1);
87*e4b17023SJohn Marino XEXP (node, 1) = 0;
88*e4b17023SJohn Marino }
89*e4b17023SJohn Marino
90*e4b17023SJohn Marino /* Removes corresponding to ELEM node from the list pointed to by LISTP.
91*e4b17023SJohn Marino Returns that node. */
92*e4b17023SJohn Marino rtx
remove_list_elem(rtx elem,rtx * listp)93*e4b17023SJohn Marino remove_list_elem (rtx elem, rtx *listp)
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino rtx node;
96*e4b17023SJohn Marino
97*e4b17023SJohn Marino listp = find_list_elem (elem, listp);
98*e4b17023SJohn Marino node = *listp;
99*e4b17023SJohn Marino remove_list_node (listp);
100*e4b17023SJohn Marino return node;
101*e4b17023SJohn Marino }
102*e4b17023SJohn Marino
103*e4b17023SJohn Marino /* This call is used in place of a gen_rtx_INSN_LIST. If there is a cached
104*e4b17023SJohn Marino node available, we'll use it, otherwise a call to gen_rtx_INSN_LIST
105*e4b17023SJohn Marino is made. */
106*e4b17023SJohn Marino rtx
alloc_INSN_LIST(rtx val,rtx next)107*e4b17023SJohn Marino alloc_INSN_LIST (rtx val, rtx next)
108*e4b17023SJohn Marino {
109*e4b17023SJohn Marino rtx r;
110*e4b17023SJohn Marino
111*e4b17023SJohn Marino if (unused_insn_list)
112*e4b17023SJohn Marino {
113*e4b17023SJohn Marino r = unused_insn_list;
114*e4b17023SJohn Marino unused_insn_list = XEXP (r, 1);
115*e4b17023SJohn Marino XEXP (r, 0) = val;
116*e4b17023SJohn Marino XEXP (r, 1) = next;
117*e4b17023SJohn Marino PUT_REG_NOTE_KIND (r, VOIDmode);
118*e4b17023SJohn Marino
119*e4b17023SJohn Marino gcc_assert (GET_CODE (r) == INSN_LIST);
120*e4b17023SJohn Marino }
121*e4b17023SJohn Marino else
122*e4b17023SJohn Marino r = gen_rtx_INSN_LIST (VOIDmode, val, next);
123*e4b17023SJohn Marino
124*e4b17023SJohn Marino return r;
125*e4b17023SJohn Marino }
126*e4b17023SJohn Marino
127*e4b17023SJohn Marino /* This call is used in place of a gen_rtx_EXPR_LIST. If there is a cached
128*e4b17023SJohn Marino node available, we'll use it, otherwise a call to gen_rtx_EXPR_LIST
129*e4b17023SJohn Marino is made. */
130*e4b17023SJohn Marino rtx
alloc_EXPR_LIST(int kind,rtx val,rtx next)131*e4b17023SJohn Marino alloc_EXPR_LIST (int kind, rtx val, rtx next)
132*e4b17023SJohn Marino {
133*e4b17023SJohn Marino rtx r;
134*e4b17023SJohn Marino
135*e4b17023SJohn Marino if (unused_expr_list)
136*e4b17023SJohn Marino {
137*e4b17023SJohn Marino r = unused_expr_list;
138*e4b17023SJohn Marino unused_expr_list = XEXP (r, 1);
139*e4b17023SJohn Marino XEXP (r, 0) = val;
140*e4b17023SJohn Marino XEXP (r, 1) = next;
141*e4b17023SJohn Marino PUT_REG_NOTE_KIND (r, kind);
142*e4b17023SJohn Marino }
143*e4b17023SJohn Marino else
144*e4b17023SJohn Marino r = gen_rtx_EXPR_LIST ((enum machine_mode) kind, val, next);
145*e4b17023SJohn Marino
146*e4b17023SJohn Marino return r;
147*e4b17023SJohn Marino }
148*e4b17023SJohn Marino
149*e4b17023SJohn Marino /* This function will free up an entire list of EXPR_LIST nodes. */
150*e4b17023SJohn Marino void
free_EXPR_LIST_list(rtx * listp)151*e4b17023SJohn Marino free_EXPR_LIST_list (rtx *listp)
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino if (*listp == 0)
154*e4b17023SJohn Marino return;
155*e4b17023SJohn Marino free_list (listp, &unused_expr_list);
156*e4b17023SJohn Marino }
157*e4b17023SJohn Marino
158*e4b17023SJohn Marino /* This function will free up an entire list of INSN_LIST nodes. */
159*e4b17023SJohn Marino void
free_INSN_LIST_list(rtx * listp)160*e4b17023SJohn Marino free_INSN_LIST_list (rtx *listp)
161*e4b17023SJohn Marino {
162*e4b17023SJohn Marino if (*listp == 0)
163*e4b17023SJohn Marino return;
164*e4b17023SJohn Marino free_list (listp, &unused_insn_list);
165*e4b17023SJohn Marino }
166*e4b17023SJohn Marino
167*e4b17023SJohn Marino /* Make a copy of the INSN_LIST list LINK and return it. */
168*e4b17023SJohn Marino rtx
copy_INSN_LIST(rtx link)169*e4b17023SJohn Marino copy_INSN_LIST (rtx link)
170*e4b17023SJohn Marino {
171*e4b17023SJohn Marino rtx new_queue;
172*e4b17023SJohn Marino rtx *pqueue = &new_queue;
173*e4b17023SJohn Marino
174*e4b17023SJohn Marino for (; link; link = XEXP (link, 1))
175*e4b17023SJohn Marino {
176*e4b17023SJohn Marino rtx x = XEXP (link, 0);
177*e4b17023SJohn Marino rtx newlink = alloc_INSN_LIST (x, NULL);
178*e4b17023SJohn Marino *pqueue = newlink;
179*e4b17023SJohn Marino pqueue = &XEXP (newlink, 1);
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino *pqueue = NULL_RTX;
182*e4b17023SJohn Marino return new_queue;
183*e4b17023SJohn Marino }
184*e4b17023SJohn Marino
185*e4b17023SJohn Marino /* Duplicate the INSN_LIST elements of COPY and prepend them to OLD. */
186*e4b17023SJohn Marino rtx
concat_INSN_LIST(rtx copy,rtx old)187*e4b17023SJohn Marino concat_INSN_LIST (rtx copy, rtx old)
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino rtx new_rtx = old;
190*e4b17023SJohn Marino for (; copy ; copy = XEXP (copy, 1))
191*e4b17023SJohn Marino {
192*e4b17023SJohn Marino new_rtx = alloc_INSN_LIST (XEXP (copy, 0), new_rtx);
193*e4b17023SJohn Marino PUT_REG_NOTE_KIND (new_rtx, REG_NOTE_KIND (copy));
194*e4b17023SJohn Marino }
195*e4b17023SJohn Marino return new_rtx;
196*e4b17023SJohn Marino }
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino /* This function will free up an individual EXPR_LIST node. */
199*e4b17023SJohn Marino void
free_EXPR_LIST_node(rtx ptr)200*e4b17023SJohn Marino free_EXPR_LIST_node (rtx ptr)
201*e4b17023SJohn Marino {
202*e4b17023SJohn Marino XEXP (ptr, 1) = unused_expr_list;
203*e4b17023SJohn Marino unused_expr_list = ptr;
204*e4b17023SJohn Marino }
205*e4b17023SJohn Marino
206*e4b17023SJohn Marino /* This function will free up an individual INSN_LIST node. */
207*e4b17023SJohn Marino void
free_INSN_LIST_node(rtx ptr)208*e4b17023SJohn Marino free_INSN_LIST_node (rtx ptr)
209*e4b17023SJohn Marino {
210*e4b17023SJohn Marino gcc_assert (GET_CODE (ptr) == INSN_LIST);
211*e4b17023SJohn Marino XEXP (ptr, 1) = unused_insn_list;
212*e4b17023SJohn Marino unused_insn_list = ptr;
213*e4b17023SJohn Marino }
214*e4b17023SJohn Marino
215*e4b17023SJohn Marino /* Remove and free corresponding to ELEM node in the INSN_LIST pointed to
216*e4b17023SJohn Marino by LISTP. */
217*e4b17023SJohn Marino void
remove_free_INSN_LIST_elem(rtx elem,rtx * listp)218*e4b17023SJohn Marino remove_free_INSN_LIST_elem (rtx elem, rtx *listp)
219*e4b17023SJohn Marino {
220*e4b17023SJohn Marino free_INSN_LIST_node (remove_list_elem (elem, listp));
221*e4b17023SJohn Marino }
222*e4b17023SJohn Marino
223*e4b17023SJohn Marino /* Remove and free the first node in the INSN_LIST pointed to by LISTP. */
224*e4b17023SJohn Marino rtx
remove_free_INSN_LIST_node(rtx * listp)225*e4b17023SJohn Marino remove_free_INSN_LIST_node (rtx *listp)
226*e4b17023SJohn Marino {
227*e4b17023SJohn Marino rtx node = *listp;
228*e4b17023SJohn Marino rtx elem = XEXP (node, 0);
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino remove_list_node (listp);
231*e4b17023SJohn Marino free_INSN_LIST_node (node);
232*e4b17023SJohn Marino
233*e4b17023SJohn Marino return elem;
234*e4b17023SJohn Marino }
235*e4b17023SJohn Marino
236*e4b17023SJohn Marino /* Remove and free the first node in the EXPR_LIST pointed to by LISTP. */
237*e4b17023SJohn Marino rtx
remove_free_EXPR_LIST_node(rtx * listp)238*e4b17023SJohn Marino remove_free_EXPR_LIST_node (rtx *listp)
239*e4b17023SJohn Marino {
240*e4b17023SJohn Marino rtx node = *listp;
241*e4b17023SJohn Marino rtx elem = XEXP (node, 0);
242*e4b17023SJohn Marino
243*e4b17023SJohn Marino remove_list_node (listp);
244*e4b17023SJohn Marino free_EXPR_LIST_node (node);
245*e4b17023SJohn Marino
246*e4b17023SJohn Marino return elem;
247*e4b17023SJohn Marino }
248*e4b17023SJohn Marino
249*e4b17023SJohn Marino #include "gt-lists.h"
250