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