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 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 "toplev.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 /* This function will free up an individual EXPR_LIST node. */ 168 void 169 free_EXPR_LIST_node (rtx ptr) 170 { 171 XEXP (ptr, 1) = unused_expr_list; 172 unused_expr_list = ptr; 173 } 174 175 /* This function will free up an individual INSN_LIST node. */ 176 void 177 free_INSN_LIST_node (rtx ptr) 178 { 179 gcc_assert (GET_CODE (ptr) == INSN_LIST); 180 XEXP (ptr, 1) = unused_insn_list; 181 unused_insn_list = ptr; 182 } 183 184 /* Remove and free corresponding to ELEM node in the INSN_LIST pointed to 185 by LISTP. */ 186 void 187 remove_free_INSN_LIST_elem (rtx elem, rtx *listp) 188 { 189 free_INSN_LIST_node (remove_list_elem (elem, listp)); 190 } 191 192 /* Remove and free the first node in the INSN_LIST pointed to by LISTP. */ 193 rtx 194 remove_free_INSN_LIST_node (rtx *listp) 195 { 196 rtx node = *listp; 197 rtx elem = XEXP (node, 0); 198 199 remove_list_node (listp); 200 free_INSN_LIST_node (node); 201 202 return elem; 203 } 204 205 /* Remove and free the first node in the EXPR_LIST pointed to by LISTP. */ 206 rtx 207 remove_free_EXPR_LIST_node (rtx *listp) 208 { 209 rtx node = *listp; 210 rtx elem = XEXP (node, 0); 211 212 remove_list_node (listp); 213 free_EXPR_LIST_node (node); 214 215 return elem; 216 } 217 218 #include "gt-lists.h" 219