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