1 /* Interprocedural reference lists. 2 Copyright (C) 2010-2013 Free Software Foundation, Inc. 3 Contributed by Jan Hubicka 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 "tree.h" 25 #include "ggc.h" 26 #include "target.h" 27 #include "cgraph.h" 28 29 static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; 30 31 /* Return ipa reference from REFERING_NODE or REFERING_VARPOOL_NODE 32 to REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type 33 of the use and STMT the statement (if it exists). */ 34 35 struct ipa_ref * 36 ipa_record_reference (symtab_node referring_node, 37 symtab_node referred_node, 38 enum ipa_ref_use use_type, gimple stmt) 39 { 40 struct ipa_ref *ref; 41 struct ipa_ref_list *list, *list2; 42 ipa_ref_t *old_references; 43 44 gcc_checking_assert (!stmt || is_a <cgraph_node> (referring_node)); 45 gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); 46 47 list = &referring_node->symbol.ref_list; 48 old_references = vec_safe_address (list->references); 49 vec_safe_grow (list->references, vec_safe_length (list->references) + 1); 50 ref = &list->references->last (); 51 52 list2 = &referred_node->symbol.ref_list; 53 list2->referring.safe_push (ref); 54 ref->referred_index = list2->referring.length () - 1; 55 ref->referring = referring_node; 56 ref->referred = referred_node; 57 ref->stmt = stmt; 58 ref->use = use_type; 59 60 /* If vector was moved in memory, update pointers. */ 61 if (old_references != list->references->address ()) 62 { 63 int i; 64 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) 65 ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref; 66 } 67 return ref; 68 } 69 70 /* Remove reference REF. */ 71 72 void 73 ipa_remove_reference (struct ipa_ref *ref) 74 { 75 struct ipa_ref_list *list = ipa_ref_referred_ref_list (ref); 76 struct ipa_ref_list *list2 = ipa_ref_referring_ref_list (ref); 77 vec<ipa_ref_t, va_gc> *old_references = list2->references; 78 struct ipa_ref *last; 79 80 gcc_assert (list->referring[ref->referred_index] == ref); 81 last = list->referring.last (); 82 if (ref != last) 83 { 84 list->referring[ref->referred_index] = list->referring.last (); 85 list->referring[ref->referred_index]->referred_index 86 = ref->referred_index; 87 } 88 list->referring.pop (); 89 90 last = &list2->references->last (); 91 if (ref != last) 92 { 93 *ref = *last; 94 ipa_ref_referred_ref_list (ref)->referring[ref->referred_index] = ref; 95 } 96 list2->references->pop (); 97 gcc_assert (list2->references == old_references); 98 } 99 100 /* Remove all references in ref list LIST. */ 101 102 void 103 ipa_remove_all_references (struct ipa_ref_list *list) 104 { 105 while (vec_safe_length (list->references)) 106 ipa_remove_reference (&list->references->last ()); 107 vec_free (list->references); 108 } 109 110 /* Remove all references in ref list LIST. */ 111 112 void 113 ipa_remove_all_referring (struct ipa_ref_list *list) 114 { 115 while (list->referring.length ()) 116 ipa_remove_reference (list->referring.last ()); 117 list->referring.release (); 118 } 119 120 /* Dump references in LIST to FILE. */ 121 122 void 123 ipa_dump_references (FILE * file, struct ipa_ref_list *list) 124 { 125 struct ipa_ref *ref; 126 int i; 127 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) 128 { 129 fprintf (file, "%s/%i (%s)", 130 symtab_node_asm_name (ref->referred), 131 ref->referred->symbol.order, 132 ipa_ref_use_name [ref->use]); 133 } 134 fprintf (file, "\n"); 135 } 136 137 /* Dump referring in LIST to FILE. */ 138 139 void 140 ipa_dump_referring (FILE * file, struct ipa_ref_list *list) 141 { 142 struct ipa_ref *ref; 143 int i; 144 for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) 145 { 146 fprintf (file, "%s/%i (%s)", 147 symtab_node_asm_name (ref->referring), 148 ref->referring->symbol.order, 149 ipa_ref_use_name [ref->use]); 150 } 151 fprintf (file, "\n"); 152 } 153 154 /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ 155 156 void 157 ipa_clone_references (symtab_node dest_node, 158 struct ipa_ref_list *src) 159 { 160 struct ipa_ref *ref; 161 int i; 162 for (i = 0; ipa_ref_list_reference_iterate (src, i, ref); i++) 163 ipa_record_reference (dest_node, 164 ref->referred, 165 ref->use, ref->stmt); 166 } 167 168 /* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ 169 170 void 171 ipa_clone_referring (symtab_node dest_node, 172 struct ipa_ref_list *src) 173 { 174 struct ipa_ref *ref; 175 int i; 176 for (i = 0; ipa_ref_list_referring_iterate (src, i, ref); i++) 177 ipa_record_reference (ref->referring, 178 dest_node, 179 ref->use, ref->stmt); 180 } 181 182 /* Return true when execution of REF can lead to return from 183 function. */ 184 bool 185 ipa_ref_cannot_lead_to_return (struct ipa_ref *ref) 186 { 187 return cgraph_node_cannot_return (ipa_ref_referring_node (ref)); 188 } 189 190 /* Return true if list contains an alias. */ 191 bool 192 ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list) 193 { 194 struct ipa_ref *ref; 195 int i; 196 for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++) 197 if (ref->use == IPA_REF_ALIAS) 198 return true; 199 return false; 200 } 201