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