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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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