]>
Commit | Line | Data |
---|---|---|
2aae7680 | 1 | /* Symbol table. |
d1e082c2 | 2 | Copyright (C) 2012-2013 Free Software Foundation, Inc. |
2aae7680 JH |
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 "tm.h" | |
d8a2d370 | 25 | #include "rtl.h" |
2aae7680 | 26 | #include "tree.h" |
d8a2d370 DN |
27 | #include "print-tree.h" |
28 | #include "varasm.h" | |
29 | #include "function.h" | |
30 | #include "emit-rtl.h" | |
2fb9a547 AM |
31 | #include "basic-block.h" |
32 | #include "tree-ssa-alias.h" | |
33 | #include "internal-fn.h" | |
34 | #include "gimple-expr.h" | |
35 | #include "is-a.h" | |
8e9055ae | 36 | #include "gimple.h" |
2aae7680 | 37 | #include "tree-inline.h" |
8f940ee6 | 38 | #include "langhooks.h" |
2aae7680 JH |
39 | #include "hashtab.h" |
40 | #include "cgraph.h" | |
1ab24192 | 41 | #include "diagnostic.h" |
474ffc72 | 42 | #include "timevar.h" |
65d630d4 | 43 | #include "lto-streamer.h" |
862d0b35 | 44 | #include "output.h" |
65d630d4 JH |
45 | |
46 | const char * const ld_plugin_symbol_resolution_names[]= | |
47 | { | |
48 | "", | |
49 | "undef", | |
50 | "prevailing_def", | |
51 | "prevailing_def_ironly", | |
52 | "preempted_reg", | |
53 | "preempted_ir", | |
54 | "resolved_ir", | |
55 | "resolved_exec", | |
56 | "resolved_dyn", | |
57 | "prevailing_def_ironly_exp" | |
58 | }; | |
1ab24192 JH |
59 | |
60 | /* Hash table used to convert declarations into nodes. */ | |
5e20cdc9 | 61 | static GTY((param_is (symtab_node))) htab_t symtab_hash; |
1ab24192 | 62 | /* Hash table used to convert assembler names into nodes. */ |
5e20cdc9 | 63 | static GTY((param_is (symtab_node))) htab_t assembler_name_hash; |
2aae7680 JH |
64 | |
65 | /* Linked list of symbol table nodes. */ | |
5e20cdc9 | 66 | symtab_node *symtab_nodes; |
2aae7680 JH |
67 | |
68 | /* The order index of the next symtab node to be created. This is | |
69 | used so that we can sort the cgraph nodes in order by when we saw | |
70 | them, to support -fno-toplevel-reorder. */ | |
71 | int symtab_order; | |
72 | ||
1ab24192 JH |
73 | /* Returns a hash code for P. */ |
74 | ||
75 | static hashval_t | |
76 | hash_node (const void *p) | |
77 | { | |
5e20cdc9 | 78 | const symtab_node *n = (const symtab_node *) p; |
67348ccc | 79 | return (hashval_t) DECL_UID (n->decl); |
1ab24192 JH |
80 | } |
81 | ||
82 | ||
83 | /* Returns nonzero if P1 and P2 are equal. */ | |
84 | ||
85 | static int | |
86 | eq_node (const void *p1, const void *p2) | |
87 | { | |
5e20cdc9 DM |
88 | const symtab_node *n1 = (const symtab_node *) p1; |
89 | const symtab_node *n2 = (const symtab_node *) p2; | |
67348ccc | 90 | return DECL_UID (n1->decl) == DECL_UID (n2->decl); |
1ab24192 JH |
91 | } |
92 | ||
862d0b35 DN |
93 | /* Hash asmnames ignoring the user specified marks. */ |
94 | ||
95 | static hashval_t | |
96 | decl_assembler_name_hash (const_tree asmname) | |
97 | { | |
98 | if (IDENTIFIER_POINTER (asmname)[0] == '*') | |
99 | { | |
100 | const char *decl_str = IDENTIFIER_POINTER (asmname) + 1; | |
101 | size_t ulp_len = strlen (user_label_prefix); | |
102 | ||
103 | if (ulp_len == 0) | |
104 | ; | |
105 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
106 | decl_str += ulp_len; | |
107 | ||
108 | return htab_hash_string (decl_str); | |
109 | } | |
110 | ||
111 | return htab_hash_string (IDENTIFIER_POINTER (asmname)); | |
112 | } | |
113 | ||
114 | ||
1ab24192 JH |
115 | /* Returns a hash code for P. */ |
116 | ||
117 | static hashval_t | |
118 | hash_node_by_assembler_name (const void *p) | |
119 | { | |
5e20cdc9 | 120 | const symtab_node *n = (const symtab_node *) p; |
67348ccc | 121 | return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl)); |
1ab24192 JH |
122 | } |
123 | ||
862d0b35 DN |
124 | /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ |
125 | ||
126 | static bool | |
127 | decl_assembler_name_equal (tree decl, const_tree asmname) | |
128 | { | |
129 | tree decl_asmname = DECL_ASSEMBLER_NAME (decl); | |
130 | const char *decl_str; | |
131 | const char *asmname_str; | |
132 | bool test = false; | |
133 | ||
134 | if (decl_asmname == asmname) | |
135 | return true; | |
136 | ||
137 | decl_str = IDENTIFIER_POINTER (decl_asmname); | |
138 | asmname_str = IDENTIFIER_POINTER (asmname); | |
139 | ||
140 | ||
141 | /* If the target assembler name was set by the user, things are trickier. | |
142 | We have a leading '*' to begin with. After that, it's arguable what | |
143 | is the correct thing to do with -fleading-underscore. Arguably, we've | |
144 | historically been doing the wrong thing in assemble_alias by always | |
145 | printing the leading underscore. Since we're not changing that, make | |
146 | sure user_label_prefix follows the '*' before matching. */ | |
147 | if (decl_str[0] == '*') | |
148 | { | |
149 | size_t ulp_len = strlen (user_label_prefix); | |
150 | ||
151 | decl_str ++; | |
152 | ||
153 | if (ulp_len == 0) | |
154 | test = true; | |
155 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
156 | decl_str += ulp_len, test=true; | |
157 | else | |
158 | decl_str --; | |
159 | } | |
160 | if (asmname_str[0] == '*') | |
161 | { | |
162 | size_t ulp_len = strlen (user_label_prefix); | |
163 | ||
164 | asmname_str ++; | |
165 | ||
166 | if (ulp_len == 0) | |
167 | test = true; | |
168 | else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0) | |
169 | asmname_str += ulp_len, test=true; | |
170 | else | |
171 | asmname_str --; | |
172 | } | |
173 | ||
174 | if (!test) | |
175 | return false; | |
176 | return strcmp (decl_str, asmname_str) == 0; | |
177 | } | |
178 | ||
179 | ||
1ab24192 JH |
180 | /* Returns nonzero if P1 and P2 are equal. */ |
181 | ||
182 | static int | |
183 | eq_assembler_name (const void *p1, const void *p2) | |
184 | { | |
5e20cdc9 | 185 | const symtab_node *n1 = (const symtab_node *) p1; |
1ab24192 | 186 | const_tree name = (const_tree)p2; |
67348ccc | 187 | return (decl_assembler_name_equal (n1->decl, name)); |
1ab24192 JH |
188 | } |
189 | ||
190 | /* Insert NODE to assembler name hash. */ | |
191 | ||
192 | static void | |
5e20cdc9 | 193 | insert_to_assembler_name_hash (symtab_node *node, bool with_clones) |
1ab24192 | 194 | { |
67348ccc | 195 | if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->decl)) |
b5493fb2 | 196 | return; |
67348ccc DM |
197 | gcc_checking_assert (!node->previous_sharing_asm_name |
198 | && !node->next_sharing_asm_name); | |
1ab24192 JH |
199 | if (assembler_name_hash) |
200 | { | |
201 | void **aslot; | |
c3167b00 | 202 | struct cgraph_node *cnode; |
67348ccc | 203 | tree decl = node->decl; |
c3167b00 | 204 | |
67348ccc | 205 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
1ab24192 JH |
206 | |
207 | aslot = htab_find_slot_with_hash (assembler_name_hash, name, | |
208 | decl_assembler_name_hash (name), | |
209 | INSERT); | |
210 | gcc_assert (*aslot != node); | |
5e20cdc9 | 211 | node->next_sharing_asm_name = (symtab_node *)*aslot; |
1ab24192 | 212 | if (*aslot != NULL) |
5e20cdc9 | 213 | ((symtab_node *)*aslot)->previous_sharing_asm_name = node; |
1ab24192 | 214 | *aslot = node; |
c3167b00 JH |
215 | |
216 | /* Update also possible inline clones sharing a decl. */ | |
217 | cnode = dyn_cast <cgraph_node> (node); | |
218 | if (cnode && cnode->clones && with_clones) | |
219 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
67348ccc DM |
220 | if (cnode->decl == decl) |
221 | insert_to_assembler_name_hash (cnode, true); | |
1ab24192 JH |
222 | } |
223 | ||
224 | } | |
225 | ||
226 | /* Remove NODE from assembler name hash. */ | |
227 | ||
228 | static void | |
5e20cdc9 | 229 | unlink_from_assembler_name_hash (symtab_node *node, bool with_clones) |
1ab24192 JH |
230 | { |
231 | if (assembler_name_hash) | |
232 | { | |
c3167b00 | 233 | struct cgraph_node *cnode; |
67348ccc | 234 | tree decl = node->decl; |
c3167b00 | 235 | |
67348ccc DM |
236 | if (node->next_sharing_asm_name) |
237 | node->next_sharing_asm_name->previous_sharing_asm_name | |
238 | = node->previous_sharing_asm_name; | |
239 | if (node->previous_sharing_asm_name) | |
1ab24192 | 240 | { |
67348ccc DM |
241 | node->previous_sharing_asm_name->next_sharing_asm_name |
242 | = node->next_sharing_asm_name; | |
1ab24192 JH |
243 | } |
244 | else | |
245 | { | |
67348ccc | 246 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
1ab24192 JH |
247 | void **slot; |
248 | slot = htab_find_slot_with_hash (assembler_name_hash, name, | |
249 | decl_assembler_name_hash (name), | |
250 | NO_INSERT); | |
251 | gcc_assert (*slot == node); | |
67348ccc | 252 | if (!node->next_sharing_asm_name) |
1ab24192 JH |
253 | htab_clear_slot (assembler_name_hash, slot); |
254 | else | |
67348ccc | 255 | *slot = node->next_sharing_asm_name; |
1ab24192 | 256 | } |
67348ccc DM |
257 | node->next_sharing_asm_name = NULL; |
258 | node->previous_sharing_asm_name = NULL; | |
c3167b00 JH |
259 | |
260 | /* Update also possible inline clones sharing a decl. */ | |
261 | cnode = dyn_cast <cgraph_node> (node); | |
262 | if (cnode && cnode->clones && with_clones) | |
263 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
67348ccc DM |
264 | if (cnode->decl == decl) |
265 | unlink_from_assembler_name_hash (cnode, true); | |
1ab24192 JH |
266 | } |
267 | } | |
268 | ||
b5493fb2 JH |
269 | /* Arrange node to be first in its entry of assembler_name_hash. */ |
270 | ||
271 | void | |
5e20cdc9 | 272 | symtab_prevail_in_asm_name_hash (symtab_node *node) |
b5493fb2 | 273 | { |
c3167b00 JH |
274 | unlink_from_assembler_name_hash (node, false); |
275 | insert_to_assembler_name_hash (node, false); | |
b5493fb2 JH |
276 | } |
277 | ||
1ab24192 | 278 | |
2aae7680 JH |
279 | /* Add node into symbol table. This function is not used directly, but via |
280 | cgraph/varpool node creation routines. */ | |
281 | ||
282 | void | |
5e20cdc9 | 283 | symtab_register_node (symtab_node *node) |
2aae7680 | 284 | { |
5e20cdc9 DM |
285 | struct symtab_node key; |
286 | symtab_node **slot; | |
1ab24192 | 287 | |
67348ccc DM |
288 | node->next = symtab_nodes; |
289 | node->previous = NULL; | |
2aae7680 | 290 | if (symtab_nodes) |
67348ccc | 291 | symtab_nodes->previous = node; |
2aae7680 JH |
292 | symtab_nodes = node; |
293 | ||
1ab24192 JH |
294 | if (!symtab_hash) |
295 | symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); | |
67348ccc | 296 | key.decl = node->decl; |
5e20cdc9 | 297 | slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT); |
1ab24192 JH |
298 | if (*slot == NULL) |
299 | *slot = node; | |
300 | ||
67348ccc | 301 | ipa_empty_ref_list (&node->ref_list); |
1ab24192 | 302 | |
67348ccc | 303 | node->order = symtab_order++; |
2aae7680 | 304 | |
66379195 JH |
305 | /* Be sure to do this last; C++ FE might create new nodes via |
306 | DECL_ASSEMBLER_NAME langhook! */ | |
c3167b00 | 307 | insert_to_assembler_name_hash (node, false); |
2aae7680 JH |
308 | } |
309 | ||
1ab24192 JH |
310 | /* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree |
311 | of inline clones. */ | |
312 | ||
313 | void | |
5e20cdc9 | 314 | symtab_insert_node_to_hashtable (symtab_node *node) |
1ab24192 | 315 | { |
5e20cdc9 DM |
316 | struct symtab_node key; |
317 | symtab_node **slot; | |
1ab24192 JH |
318 | |
319 | if (!symtab_hash) | |
320 | symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); | |
67348ccc | 321 | key.decl = node->decl; |
5e20cdc9 | 322 | slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT); |
1ab24192 JH |
323 | *slot = node; |
324 | } | |
325 | ||
2aae7680 JH |
326 | /* Remove node from symbol table. This function is not used directly, but via |
327 | cgraph/varpool node removal routines. */ | |
328 | ||
329 | void | |
5e20cdc9 | 330 | symtab_unregister_node (symtab_node *node) |
2aae7680 | 331 | { |
1ab24192 | 332 | void **slot; |
67348ccc DM |
333 | ipa_remove_all_references (&node->ref_list); |
334 | ipa_remove_all_referring (&node->ref_list); | |
2aae7680 | 335 | |
67348ccc | 336 | if (node->same_comdat_group) |
2aae7680 | 337 | { |
5e20cdc9 | 338 | symtab_node *prev; |
67348ccc DM |
339 | for (prev = node->same_comdat_group; |
340 | prev->same_comdat_group != node; | |
341 | prev = prev->same_comdat_group) | |
2aae7680 | 342 | ; |
67348ccc DM |
343 | if (node->same_comdat_group == prev) |
344 | prev->same_comdat_group = NULL; | |
2aae7680 | 345 | else |
67348ccc DM |
346 | prev->same_comdat_group = node->same_comdat_group; |
347 | node->same_comdat_group = NULL; | |
2aae7680 JH |
348 | } |
349 | ||
67348ccc DM |
350 | if (node->previous) |
351 | node->previous->next = node->next; | |
2aae7680 | 352 | else |
67348ccc DM |
353 | symtab_nodes = node->next; |
354 | if (node->next) | |
355 | node->next->previous = node->previous; | |
356 | node->next = NULL; | |
357 | node->previous = NULL; | |
1ab24192 JH |
358 | |
359 | slot = htab_find_slot (symtab_hash, node, NO_INSERT); | |
bbf9ad07 JH |
360 | |
361 | /* During LTO symtab merging we temporarily corrupt decl to symtab node | |
362 | hash. */ | |
363 | gcc_assert ((slot && *slot) || in_lto_p); | |
364 | if (slot && *slot && *slot == node) | |
1ab24192 | 365 | { |
5e20cdc9 | 366 | symtab_node *replacement_node = NULL; |
5d59b5e1 | 367 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
67348ccc | 368 | replacement_node = cgraph_find_replacement_node (cnode); |
1ab24192 JH |
369 | if (!replacement_node) |
370 | htab_clear_slot (symtab_hash, slot); | |
371 | else | |
372 | *slot = replacement_node; | |
373 | } | |
67348ccc | 374 | if (!is_a <varpool_node> (node) || !DECL_HARD_REGISTER (node->decl)) |
8e4c9a10 | 375 | unlink_from_assembler_name_hash (node, false); |
1ab24192 JH |
376 | } |
377 | ||
378 | /* Return symbol table node associated with DECL, if any, | |
379 | and NULL otherwise. */ | |
380 | ||
5e20cdc9 | 381 | symtab_node * |
1ab24192 JH |
382 | symtab_get_node (const_tree decl) |
383 | { | |
5e20cdc9 DM |
384 | symtab_node **slot; |
385 | struct symtab_node key; | |
1ab24192 | 386 | |
bbf9ad07 JH |
387 | #ifdef ENABLE_CHECKING |
388 | /* Check that we are called for sane type of object - functions | |
389 | and static or external variables. */ | |
1ab24192 JH |
390 | gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL |
391 | || (TREE_CODE (decl) == VAR_DECL | |
392 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) | |
393 | || in_lto_p))); | |
bbf9ad07 | 394 | #endif |
1ab24192 JH |
395 | |
396 | if (!symtab_hash) | |
397 | return NULL; | |
398 | ||
399 | key.decl = CONST_CAST2 (tree, const_tree, decl); | |
400 | ||
5e20cdc9 | 401 | slot = (symtab_node **) htab_find_slot (symtab_hash, &key, |
1ab24192 JH |
402 | NO_INSERT); |
403 | ||
404 | if (slot) | |
405 | return *slot; | |
406 | return NULL; | |
2aae7680 JH |
407 | } |
408 | ||
409 | /* Remove symtab NODE from the symbol table. */ | |
410 | ||
411 | void | |
5e20cdc9 | 412 | symtab_remove_node (symtab_node *node) |
2aae7680 | 413 | { |
5d59b5e1 LC |
414 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
415 | cgraph_remove_node (cnode); | |
416 | else if (varpool_node *vnode = dyn_cast <varpool_node> (node)) | |
417 | varpool_remove_node (vnode); | |
2aae7680 | 418 | } |
1ab24192 | 419 | |
b5493fb2 | 420 | /* Initalize asm name hash unless. */ |
1ab24192 | 421 | |
b5493fb2 JH |
422 | void |
423 | symtab_initialize_asm_name_hash (void) | |
1ab24192 | 424 | { |
5e20cdc9 | 425 | symtab_node *node; |
1ab24192 JH |
426 | if (!assembler_name_hash) |
427 | { | |
428 | assembler_name_hash = | |
429 | htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name, | |
430 | NULL); | |
431 | FOR_EACH_SYMBOL (node) | |
c3167b00 | 432 | insert_to_assembler_name_hash (node, false); |
1ab24192 | 433 | } |
b5493fb2 | 434 | } |
1ab24192 | 435 | |
b5493fb2 JH |
436 | /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. |
437 | Return NULL if there's no such node. */ | |
438 | ||
5e20cdc9 | 439 | symtab_node * |
b5493fb2 JH |
440 | symtab_node_for_asm (const_tree asmname) |
441 | { | |
5e20cdc9 | 442 | symtab_node *node; |
b5493fb2 JH |
443 | void **slot; |
444 | ||
445 | symtab_initialize_asm_name_hash (); | |
1ab24192 JH |
446 | slot = htab_find_slot_with_hash (assembler_name_hash, asmname, |
447 | decl_assembler_name_hash (asmname), | |
448 | NO_INSERT); | |
449 | ||
450 | if (slot) | |
451 | { | |
5e20cdc9 | 452 | node = (symtab_node *) *slot; |
1ab24192 JH |
453 | return node; |
454 | } | |
455 | return NULL; | |
456 | } | |
457 | ||
458 | /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */ | |
459 | ||
460 | void | |
461 | change_decl_assembler_name (tree decl, tree name) | |
462 | { | |
5e20cdc9 | 463 | symtab_node *node = NULL; |
1ab24192 JH |
464 | |
465 | /* We can have user ASM names on things, like global register variables, that | |
466 | are not in the symbol table. */ | |
467 | if ((TREE_CODE (decl) == VAR_DECL | |
468 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) | |
469 | || TREE_CODE (decl) == FUNCTION_DECL) | |
470 | node = symtab_get_node (decl); | |
471 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) | |
472 | { | |
473 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
474 | if (node) | |
c3167b00 | 475 | insert_to_assembler_name_hash (node, true); |
1ab24192 JH |
476 | } |
477 | else | |
478 | { | |
479 | if (name == DECL_ASSEMBLER_NAME (decl)) | |
480 | return; | |
481 | ||
8a41354f JH |
482 | tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) |
483 | ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) | |
484 | : NULL); | |
1ab24192 | 485 | if (node) |
c3167b00 | 486 | unlink_from_assembler_name_hash (node, true); |
1ab24192 JH |
487 | if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) |
488 | && DECL_RTL_SET_P (decl)) | |
489 | warning (0, "%D renamed after being referenced in assembly", decl); | |
490 | ||
491 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
8a41354f JH |
492 | if (alias) |
493 | { | |
494 | IDENTIFIER_TRANSPARENT_ALIAS (name) = 1; | |
495 | TREE_CHAIN (DECL_ASSEMBLER_NAME (name)) = alias; | |
496 | } | |
1ab24192 | 497 | if (node) |
c3167b00 | 498 | insert_to_assembler_name_hash (node, true); |
1ab24192 JH |
499 | } |
500 | } | |
501 | ||
65d630d4 JH |
502 | /* Add NEW_ to the same comdat group that OLD is in. */ |
503 | ||
504 | void | |
5e20cdc9 DM |
505 | symtab_add_to_same_comdat_group (symtab_node *new_node, |
506 | symtab_node *old_node) | |
65d630d4 | 507 | { |
67348ccc DM |
508 | gcc_assert (DECL_ONE_ONLY (old_node->decl)); |
509 | gcc_assert (!new_node->same_comdat_group); | |
65d630d4 JH |
510 | gcc_assert (new_node != old_node); |
511 | ||
67348ccc DM |
512 | DECL_COMDAT_GROUP (new_node->decl) = DECL_COMDAT_GROUP (old_node->decl); |
513 | new_node->same_comdat_group = old_node; | |
514 | if (!old_node->same_comdat_group) | |
515 | old_node->same_comdat_group = new_node; | |
65d630d4 JH |
516 | else |
517 | { | |
5e20cdc9 | 518 | symtab_node *n; |
67348ccc DM |
519 | for (n = old_node->same_comdat_group; |
520 | n->same_comdat_group != old_node; | |
521 | n = n->same_comdat_group) | |
65d630d4 | 522 | ; |
67348ccc | 523 | n->same_comdat_group = new_node; |
65d630d4 JH |
524 | } |
525 | } | |
526 | ||
527 | /* Dissolve the same_comdat_group list in which NODE resides. */ | |
528 | ||
529 | void | |
5e20cdc9 | 530 | symtab_dissolve_same_comdat_group_list (symtab_node *node) |
65d630d4 | 531 | { |
5e20cdc9 DM |
532 | symtab_node *n = node; |
533 | symtab_node *next; | |
65d630d4 | 534 | |
67348ccc | 535 | if (!node->same_comdat_group) |
65d630d4 JH |
536 | return; |
537 | do | |
538 | { | |
67348ccc DM |
539 | next = n->same_comdat_group; |
540 | n->same_comdat_group = NULL; | |
1f26ac87 JM |
541 | /* Clear DECL_COMDAT_GROUP for comdat locals, since |
542 | make_decl_local doesn't. */ | |
543 | if (!TREE_PUBLIC (n->decl)) | |
544 | DECL_COMDAT_GROUP (n->decl) = NULL_TREE; | |
65d630d4 JH |
545 | n = next; |
546 | } | |
547 | while (n != node); | |
548 | } | |
549 | ||
8f940ee6 JH |
550 | /* Return printable assembler name of NODE. |
551 | This function is used only for debugging. When assembler name | |
552 | is unknown go with identifier name. */ | |
553 | ||
554 | const char * | |
fec39fa6 | 555 | symtab_node::asm_name () const |
8f940ee6 | 556 | { |
fec39fa6 TS |
557 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) |
558 | return lang_hooks.decl_printable_name (decl, 2); | |
559 | return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
8f940ee6 JH |
560 | } |
561 | ||
562 | /* Return printable identifier name. */ | |
563 | ||
564 | const char * | |
fec39fa6 | 565 | symtab_node::name () const |
8f940ee6 | 566 | { |
fec39fa6 | 567 | return lang_hooks.decl_printable_name (decl, 2); |
8f940ee6 JH |
568 | } |
569 | ||
570 | static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; | |
571 | ||
572 | /* Dump base fields of symtab nodes. Not to be used directly. */ | |
573 | ||
574 | void | |
5e20cdc9 | 575 | dump_symtab_base (FILE *f, symtab_node *node) |
8f940ee6 JH |
576 | { |
577 | static const char * const visibility_types[] = { | |
578 | "default", "protected", "hidden", "internal" | |
579 | }; | |
580 | ||
581 | fprintf (f, "%s/%i (%s)", | |
fec39fa6 | 582 | node->asm_name (), |
67348ccc | 583 | node->order, |
fec39fa6 | 584 | node->name ()); |
8f940ee6 | 585 | dump_addr (f, " @", (void *)node); |
67348ccc | 586 | fprintf (f, "\n Type: %s", symtab_type_names[node->type]); |
e70670cf | 587 | |
67348ccc | 588 | if (node->definition) |
e70670cf | 589 | fprintf (f, " definition"); |
67348ccc | 590 | if (node->analyzed) |
e70670cf | 591 | fprintf (f, " analyzed"); |
67348ccc | 592 | if (node->alias) |
e70670cf | 593 | fprintf (f, " alias"); |
67348ccc | 594 | if (node->weakref) |
08346abd | 595 | fprintf (f, " weakref"); |
67348ccc | 596 | if (node->cpp_implicit_alias) |
40a7fe1e | 597 | fprintf (f, " cpp_implicit_alias"); |
67348ccc | 598 | if (node->alias_target) |
40a7fe1e | 599 | fprintf (f, " target:%s", |
67348ccc | 600 | DECL_P (node->alias_target) |
40a7fe1e | 601 | ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME |
67348ccc DM |
602 | (node->alias_target)) |
603 | : IDENTIFIER_POINTER (node->alias_target)); | |
e70670cf | 604 | fprintf (f, "\n Visibility:"); |
67348ccc | 605 | if (node->in_other_partition) |
8f940ee6 | 606 | fprintf (f, " in_other_partition"); |
67348ccc | 607 | if (node->used_from_other_partition) |
8f940ee6 | 608 | fprintf (f, " used_from_other_partition"); |
67348ccc | 609 | if (node->force_output) |
ead84f73 | 610 | fprintf (f, " force_output"); |
67348ccc | 611 | if (node->forced_by_abi) |
edb983b2 | 612 | fprintf (f, " forced_by_abi"); |
67348ccc | 613 | if (node->externally_visible) |
e5b962d0 | 614 | fprintf (f, " externally_visible"); |
67348ccc | 615 | if (node->resolution != LDPR_UNKNOWN) |
8f940ee6 | 616 | fprintf (f, " %s", |
67348ccc DM |
617 | ld_plugin_symbol_resolution_names[(int)node->resolution]); |
618 | if (TREE_ASM_WRITTEN (node->decl)) | |
8f940ee6 | 619 | fprintf (f, " asm_written"); |
67348ccc | 620 | if (DECL_EXTERNAL (node->decl)) |
8f940ee6 | 621 | fprintf (f, " external"); |
67348ccc | 622 | if (TREE_PUBLIC (node->decl)) |
8f940ee6 | 623 | fprintf (f, " public"); |
67348ccc | 624 | if (DECL_COMMON (node->decl)) |
8f940ee6 | 625 | fprintf (f, " common"); |
67348ccc | 626 | if (DECL_WEAK (node->decl)) |
8f940ee6 | 627 | fprintf (f, " weak"); |
67348ccc | 628 | if (DECL_DLLIMPORT_P (node->decl)) |
8f940ee6 | 629 | fprintf (f, " dll_import"); |
67348ccc | 630 | if (DECL_COMDAT (node->decl)) |
8f940ee6 | 631 | fprintf (f, " comdat"); |
67348ccc | 632 | if (DECL_COMDAT_GROUP (node->decl)) |
8f940ee6 | 633 | fprintf (f, " comdat_group:%s", |
67348ccc DM |
634 | IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->decl))); |
635 | if (DECL_ONE_ONLY (node->decl)) | |
8f940ee6 | 636 | fprintf (f, " one_only"); |
67348ccc | 637 | if (DECL_SECTION_NAME (node->decl)) |
8f940ee6 | 638 | fprintf (f, " section_name:%s", |
67348ccc DM |
639 | TREE_STRING_POINTER (DECL_SECTION_NAME (node->decl))); |
640 | if (DECL_VISIBILITY_SPECIFIED (node->decl)) | |
8f940ee6 | 641 | fprintf (f, " visibility_specified"); |
67348ccc | 642 | if (DECL_VISIBILITY (node->decl)) |
8f940ee6 | 643 | fprintf (f, " visibility:%s", |
67348ccc DM |
644 | visibility_types [DECL_VISIBILITY (node->decl)]); |
645 | if (DECL_VIRTUAL_P (node->decl)) | |
8f940ee6 | 646 | fprintf (f, " virtual"); |
67348ccc | 647 | if (DECL_ARTIFICIAL (node->decl)) |
8f940ee6 | 648 | fprintf (f, " artificial"); |
67348ccc | 649 | if (TREE_CODE (node->decl) == FUNCTION_DECL) |
838ff415 | 650 | { |
67348ccc | 651 | if (DECL_STATIC_CONSTRUCTOR (node->decl)) |
838ff415 | 652 | fprintf (f, " constructor"); |
67348ccc | 653 | if (DECL_STATIC_DESTRUCTOR (node->decl)) |
838ff415 JH |
654 | fprintf (f, " destructor"); |
655 | } | |
8f940ee6 JH |
656 | fprintf (f, "\n"); |
657 | ||
67348ccc | 658 | if (node->same_comdat_group) |
8f940ee6 | 659 | fprintf (f, " Same comdat group as: %s/%i\n", |
fec39fa6 | 660 | node->same_comdat_group->asm_name (), |
67348ccc DM |
661 | node->same_comdat_group->order); |
662 | if (node->next_sharing_asm_name) | |
8f940ee6 | 663 | fprintf (f, " next sharing asm name: %i\n", |
67348ccc DM |
664 | node->next_sharing_asm_name->order); |
665 | if (node->previous_sharing_asm_name) | |
8f940ee6 | 666 | fprintf (f, " previous sharing asm name: %i\n", |
67348ccc | 667 | node->previous_sharing_asm_name->order); |
8f940ee6 | 668 | |
67348ccc | 669 | if (node->address_taken) |
fe0bd630 | 670 | fprintf (f, " Address is taken.\n"); |
67348ccc | 671 | if (node->aux) |
66058468 JH |
672 | { |
673 | fprintf (f, " Aux:"); | |
67348ccc | 674 | dump_addr (f, " @", (void *)node->aux); |
66058468 | 675 | } |
8f940ee6 JH |
676 | |
677 | fprintf (f, " References: "); | |
67348ccc | 678 | ipa_dump_references (f, &node->ref_list); |
5932a4d4 | 679 | fprintf (f, " Referring: "); |
67348ccc DM |
680 | ipa_dump_referring (f, &node->ref_list); |
681 | if (node->lto_file_data) | |
b5493fb2 | 682 | fprintf (f, " Read from file: %s\n", |
67348ccc | 683 | node->lto_file_data->file_name); |
8f940ee6 JH |
684 | } |
685 | ||
686 | /* Dump symtab node. */ | |
687 | ||
688 | void | |
5e20cdc9 | 689 | dump_symtab_node (FILE *f, symtab_node *node) |
8f940ee6 | 690 | { |
5d59b5e1 LC |
691 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
692 | dump_cgraph_node (f, cnode); | |
693 | else if (varpool_node *vnode = dyn_cast <varpool_node> (node)) | |
694 | dump_varpool_node (f, vnode); | |
8f940ee6 JH |
695 | } |
696 | ||
697 | /* Dump symbol table. */ | |
698 | ||
699 | void | |
700 | dump_symtab (FILE *f) | |
701 | { | |
5e20cdc9 | 702 | symtab_node *node; |
8f940ee6 JH |
703 | fprintf (f, "Symbol table:\n\n"); |
704 | FOR_EACH_SYMBOL (node) | |
705 | dump_symtab_node (f, node); | |
706 | } | |
707 | ||
708 | /* Dump symtab node NODE to stderr. */ | |
709 | ||
710 | DEBUG_FUNCTION void | |
5e20cdc9 | 711 | debug_symtab_node (symtab_node *node) |
8f940ee6 JH |
712 | { |
713 | dump_symtab_node (stderr, node); | |
714 | } | |
715 | ||
716 | /* Dump symbol table to stderr. */ | |
717 | ||
718 | DEBUG_FUNCTION void | |
719 | debug_symtab (void) | |
720 | { | |
721 | dump_symtab (stderr); | |
722 | } | |
723 | ||
474ffc72 JH |
724 | /* Verify common part of symtab nodes. */ |
725 | ||
726 | DEBUG_FUNCTION bool | |
5e20cdc9 | 727 | verify_symtab_base (symtab_node *node) |
474ffc72 JH |
728 | { |
729 | bool error_found = false; | |
5e20cdc9 | 730 | symtab_node *hashed_node; |
474ffc72 | 731 | |
5d59b5e1 | 732 | if (is_a <cgraph_node> (node)) |
474ffc72 | 733 | { |
67348ccc | 734 | if (TREE_CODE (node->decl) != FUNCTION_DECL) |
474ffc72 JH |
735 | { |
736 | error ("function symbol is not function"); | |
737 | error_found = true; | |
738 | } | |
739 | } | |
5d59b5e1 | 740 | else if (is_a <varpool_node> (node)) |
474ffc72 | 741 | { |
67348ccc | 742 | if (TREE_CODE (node->decl) != VAR_DECL) |
474ffc72 JH |
743 | { |
744 | error ("variable symbol is not variable"); | |
745 | error_found = true; | |
746 | } | |
747 | } | |
748 | else | |
749 | { | |
750 | error ("node has unknown type"); | |
751 | error_found = true; | |
752 | } | |
753 | ||
ca0f62a8 | 754 | if (cgraph_state != CGRAPH_LTO_STREAMING) |
474ffc72 | 755 | { |
67348ccc | 756 | hashed_node = symtab_get_node (node->decl); |
ca0f62a8 JH |
757 | if (!hashed_node) |
758 | { | |
759 | error ("node not found in symtab decl hashtable"); | |
760 | error_found = true; | |
761 | } | |
e5b962d0 JH |
762 | if (hashed_node != node |
763 | && (!is_a <cgraph_node> (node) | |
764 | || !dyn_cast <cgraph_node> (node)->clone_of | |
67348ccc DM |
765 | || dyn_cast <cgraph_node> (node)->clone_of->decl |
766 | != node->decl)) | |
e5b962d0 JH |
767 | { |
768 | error ("node differs from symtab decl hashtable"); | |
769 | error_found = true; | |
770 | } | |
474ffc72 JH |
771 | } |
772 | if (assembler_name_hash) | |
773 | { | |
67348ccc DM |
774 | hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl)); |
775 | if (hashed_node && hashed_node->previous_sharing_asm_name) | |
474ffc72 JH |
776 | { |
777 | error ("assembler name hash list corrupted"); | |
778 | error_found = true; | |
779 | } | |
780 | while (hashed_node) | |
781 | { | |
782 | if (hashed_node == node) | |
783 | break; | |
67348ccc | 784 | hashed_node = hashed_node->next_sharing_asm_name; |
474ffc72 | 785 | } |
b5493fb2 | 786 | if (!hashed_node |
5d59b5e1 | 787 | && !(is_a <varpool_node> (node) |
67348ccc | 788 | || DECL_HARD_REGISTER (node->decl))) |
474ffc72 JH |
789 | { |
790 | error ("node not found in symtab assembler name hash"); | |
791 | error_found = true; | |
792 | } | |
793 | } | |
67348ccc DM |
794 | if (node->previous_sharing_asm_name |
795 | && node->previous_sharing_asm_name->next_sharing_asm_name != node) | |
474ffc72 JH |
796 | { |
797 | error ("double linked list of assembler names corrupted"); | |
e70670cf JH |
798 | error_found = true; |
799 | } | |
67348ccc | 800 | if (node->analyzed && !node->definition) |
e70670cf JH |
801 | { |
802 | error ("node is analyzed byt it is not a definition"); | |
803 | error_found = true; | |
474ffc72 | 804 | } |
67348ccc | 805 | if (node->cpp_implicit_alias && !node->alias) |
40a7fe1e JH |
806 | { |
807 | error ("node is alias but not implicit alias"); | |
808 | error_found = true; | |
809 | } | |
67348ccc DM |
810 | if (node->alias && !node->definition |
811 | && !node->weakref) | |
40a7fe1e JH |
812 | { |
813 | error ("node is alias but not definition"); | |
814 | error_found = true; | |
815 | } | |
67348ccc | 816 | if (node->weakref && !node->alias) |
08346abd JH |
817 | { |
818 | error ("node is weakref but not an alias"); | |
819 | error_found = true; | |
820 | } | |
67348ccc | 821 | if (node->same_comdat_group) |
474ffc72 | 822 | { |
5e20cdc9 | 823 | symtab_node *n = node->same_comdat_group; |
474ffc72 | 824 | |
67348ccc | 825 | if (!DECL_ONE_ONLY (n->decl)) |
474ffc72 JH |
826 | { |
827 | error ("non-DECL_ONE_ONLY node in a same_comdat_group list"); | |
828 | error_found = true; | |
829 | } | |
67348ccc | 830 | if (n->type != node->type) |
474ffc72 JH |
831 | { |
832 | error ("mixing different types of symbol in same comdat groups is not supported"); | |
833 | error_found = true; | |
834 | } | |
835 | if (n == node) | |
836 | { | |
837 | error ("node is alone in a comdat group"); | |
838 | error_found = true; | |
839 | } | |
840 | do | |
841 | { | |
67348ccc | 842 | if (!n->same_comdat_group) |
474ffc72 JH |
843 | { |
844 | error ("same_comdat_group is not a circular list"); | |
845 | error_found = true; | |
846 | break; | |
847 | } | |
67348ccc | 848 | n = n->same_comdat_group; |
474ffc72 JH |
849 | } |
850 | while (n != node); | |
1f26ac87 JM |
851 | if (symtab_comdat_local_p (node)) |
852 | { | |
853 | struct ipa_ref_list *refs = &node->ref_list; | |
854 | struct ipa_ref *ref; | |
855 | for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i) | |
856 | { | |
857 | if (!symtab_in_same_comdat_p (ref->referring, node)) | |
858 | { | |
859 | error ("comdat-local symbol referred to by %s outside its " | |
860 | "comdat", | |
861 | identifier_to_locale (ref->referring->name())); | |
862 | error_found = true; | |
863 | } | |
864 | } | |
865 | } | |
474ffc72 JH |
866 | } |
867 | return error_found; | |
868 | } | |
869 | ||
870 | /* Verify consistency of NODE. */ | |
871 | ||
872 | DEBUG_FUNCTION void | |
5e20cdc9 | 873 | verify_symtab_node (symtab_node *node) |
474ffc72 JH |
874 | { |
875 | if (seen_error ()) | |
876 | return; | |
877 | ||
878 | timevar_push (TV_CGRAPH_VERIFY); | |
5d59b5e1 LC |
879 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
880 | verify_cgraph_node (cnode); | |
474ffc72 JH |
881 | else |
882 | if (verify_symtab_base (node)) | |
883 | { | |
884 | dump_symtab_node (stderr, node); | |
885 | internal_error ("verify_symtab_node failed"); | |
886 | } | |
887 | timevar_pop (TV_CGRAPH_VERIFY); | |
888 | } | |
889 | ||
890 | /* Verify symbol table for internal consistency. */ | |
891 | ||
892 | DEBUG_FUNCTION void | |
893 | verify_symtab (void) | |
894 | { | |
5e20cdc9 | 895 | symtab_node *node; |
474ffc72 JH |
896 | FOR_EACH_SYMBOL (node) |
897 | verify_symtab_node (node); | |
898 | } | |
899 | ||
65d630d4 JH |
900 | /* Return true when RESOLUTION indicate that linker will use |
901 | the symbol from non-LTO object files. */ | |
902 | ||
903 | bool | |
904 | resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) | |
905 | { | |
906 | return (resolution == LDPR_PREVAILING_DEF | |
907 | || resolution == LDPR_PREEMPTED_REG | |
908 | || resolution == LDPR_RESOLVED_EXEC | |
909 | || resolution == LDPR_RESOLVED_DYN); | |
910 | } | |
911 | ||
912 | /* Return true when NODE is known to be used from other (non-LTO) object file. | |
913 | Known only when doing LTO via linker plugin. */ | |
914 | ||
915 | bool | |
5e20cdc9 | 916 | symtab_used_from_object_file_p (symtab_node *node) |
65d630d4 | 917 | { |
67348ccc | 918 | if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) |
65d630d4 | 919 | return false; |
67348ccc | 920 | if (resolution_used_from_other_file_p (node->resolution)) |
65d630d4 JH |
921 | return true; |
922 | return false; | |
923 | } | |
924 | ||
925 | /* Make DECL local. FIXME: We shouldn't need to mess with rtl this early, | |
926 | but other code such as notice_global_symbol generates rtl. */ | |
40a7fe1e | 927 | |
65d630d4 JH |
928 | void |
929 | symtab_make_decl_local (tree decl) | |
930 | { | |
931 | rtx rtl, symbol; | |
932 | ||
1f26ac87 JM |
933 | /* Avoid clearing DECL_COMDAT_GROUP on comdat-local decls. */ |
934 | if (TREE_PUBLIC (decl) == 0) | |
935 | return; | |
936 | ||
65d630d4 JH |
937 | if (TREE_CODE (decl) == VAR_DECL) |
938 | DECL_COMMON (decl) = 0; | |
939 | else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | |
940 | ||
941 | if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl)) | |
942 | { | |
65d630d4 JH |
943 | DECL_SECTION_NAME (decl) = 0; |
944 | DECL_COMDAT (decl) = 0; | |
945 | } | |
946 | DECL_COMDAT_GROUP (decl) = 0; | |
947 | DECL_WEAK (decl) = 0; | |
948 | DECL_EXTERNAL (decl) = 0; | |
b5493fb2 JH |
949 | DECL_VISIBILITY_SPECIFIED (decl) = 0; |
950 | DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; | |
65d630d4 JH |
951 | TREE_PUBLIC (decl) = 0; |
952 | if (!DECL_RTL_SET_P (decl)) | |
953 | return; | |
954 | ||
955 | /* Update rtl flags. */ | |
956 | make_decl_rtl (decl); | |
957 | ||
958 | rtl = DECL_RTL (decl); | |
959 | if (!MEM_P (rtl)) | |
960 | return; | |
961 | ||
962 | symbol = XEXP (rtl, 0); | |
963 | if (GET_CODE (symbol) != SYMBOL_REF) | |
964 | return; | |
965 | ||
966 | SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl); | |
967 | } | |
e70670cf | 968 | |
40a7fe1e JH |
969 | /* Return availability of NODE. */ |
970 | ||
971 | enum availability | |
5e20cdc9 | 972 | symtab_node_availability (symtab_node *node) |
40a7fe1e JH |
973 | { |
974 | if (is_a <cgraph_node> (node)) | |
975 | return cgraph_function_body_availability (cgraph (node)); | |
976 | else | |
977 | return cgraph_variable_initializer_availability (varpool (node)); | |
978 | } | |
979 | ||
e70670cf JH |
980 | /* Given NODE, walk the alias chain to return the symbol NODE is alias of. |
981 | If NODE is not an alias, return NODE. | |
982 | When AVAILABILITY is non-NULL, get minimal availability in the chain. */ | |
983 | ||
5e20cdc9 DM |
984 | symtab_node * |
985 | symtab_alias_ultimate_target (symtab_node *node, enum availability *availability) | |
e70670cf | 986 | { |
aaae719d JH |
987 | bool weakref_p = false; |
988 | ||
67348ccc | 989 | if (!node->alias) |
aaae719d JH |
990 | { |
991 | if (availability) | |
992 | *availability = symtab_node_availability (node); | |
993 | return node; | |
994 | } | |
995 | ||
996 | /* To determine visibility of the target, we follow ELF semantic of aliases. | |
997 | Here alias is an alternative assembler name of a given definition. Its | |
1aa95df7 | 998 | availability prevails the availability of its target (i.e. static alias of |
aaae719d JH |
999 | weak definition is available. |
1000 | ||
1001 | Weakref is a different animal (and not part of ELF per se). It is just | |
1002 | alternative name of a given symbol used within one complation unit | |
1003 | and is translated prior hitting the object file. It inherits the | |
1004 | visibility of its target (i.e. weakref of non-overwritable definition | |
1005 | is non-overwritable, while weakref of weak definition is weak). | |
1006 | ||
1007 | If we ever get into supporting targets with different semantics, a target | |
1008 | hook will be needed here. */ | |
1009 | ||
e70670cf | 1010 | if (availability) |
aaae719d | 1011 | { |
67348ccc | 1012 | weakref_p = node->weakref; |
aaae719d JH |
1013 | if (!weakref_p) |
1014 | *availability = symtab_node_availability (node); | |
1015 | else | |
1016 | *availability = AVAIL_LOCAL; | |
1017 | } | |
e70670cf JH |
1018 | while (node) |
1019 | { | |
67348ccc | 1020 | if (node->alias && node->analyzed) |
e70670cf JH |
1021 | node = symtab_alias_target (node); |
1022 | else | |
aaae719d JH |
1023 | { |
1024 | if (!availability) | |
1025 | ; | |
67348ccc | 1026 | else if (node->analyzed) |
aaae719d JH |
1027 | { |
1028 | if (weakref_p) | |
1029 | { | |
1030 | enum availability a = symtab_node_availability (node); | |
1031 | if (a < *availability) | |
1032 | *availability = a; | |
1033 | } | |
1034 | } | |
1035 | else | |
1036 | *availability = AVAIL_NOT_AVAILABLE; | |
1037 | return node; | |
1038 | } | |
1039 | if (node && availability && weakref_p) | |
e70670cf | 1040 | { |
40a7fe1e | 1041 | enum availability a = symtab_node_availability (node); |
e70670cf JH |
1042 | if (a < *availability) |
1043 | *availability = a; | |
67348ccc | 1044 | weakref_p = node->weakref; |
e70670cf JH |
1045 | } |
1046 | } | |
1047 | if (availability) | |
1048 | *availability = AVAIL_NOT_AVAILABLE; | |
1049 | return NULL; | |
1050 | } | |
40a7fe1e JH |
1051 | |
1052 | /* C++ FE sometimes change linkage flags after producing same body aliases. | |
1053 | ||
1054 | FIXME: C++ produce implicit aliases for virtual functions and vtables that | |
1055 | are obviously equivalent. The way it is doing so is however somewhat | |
1056 | kludgy and interferes with the visibility code. As a result we need to | |
1057 | copy the visibility from the target to get things right. */ | |
1058 | ||
1059 | void | |
5e20cdc9 | 1060 | fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) |
40a7fe1e JH |
1061 | { |
1062 | if (is_a <cgraph_node> (node)) | |
1063 | { | |
67348ccc DM |
1064 | DECL_DECLARED_INLINE_P (node->decl) |
1065 | = DECL_DECLARED_INLINE_P (target->decl); | |
1066 | DECL_DISREGARD_INLINE_LIMITS (node->decl) | |
1067 | = DECL_DISREGARD_INLINE_LIMITS (target->decl); | |
40a7fe1e JH |
1068 | } |
1069 | /* FIXME: It is not really clear why those flags should not be copied for | |
1070 | functions, too. */ | |
1071 | else | |
1072 | { | |
67348ccc DM |
1073 | DECL_WEAK (node->decl) = DECL_WEAK (target->decl); |
1074 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); | |
1075 | DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (target->decl); | |
40a7fe1e | 1076 | } |
67348ccc DM |
1077 | DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl); |
1078 | if (TREE_PUBLIC (node->decl)) | |
40a7fe1e | 1079 | { |
67348ccc DM |
1080 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); |
1081 | DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl); | |
1082 | DECL_COMDAT_GROUP (node->decl) | |
1083 | = DECL_COMDAT_GROUP (target->decl); | |
1084 | if (DECL_ONE_ONLY (target->decl) | |
1085 | && !node->same_comdat_group) | |
1086 | symtab_add_to_same_comdat_group (node, target); | |
40a7fe1e | 1087 | } |
67348ccc | 1088 | node->externally_visible = target->externally_visible; |
40a7fe1e JH |
1089 | } |
1090 | ||
1091 | /* Add reference recording that NODE is alias of TARGET. | |
1092 | The function can fail in the case of aliasing cycles; in this case | |
1093 | it returns false. */ | |
1094 | ||
1095 | bool | |
5e20cdc9 | 1096 | symtab_resolve_alias (symtab_node *node, symtab_node *target) |
40a7fe1e | 1097 | { |
5e20cdc9 | 1098 | symtab_node *n; |
40a7fe1e | 1099 | |
67348ccc DM |
1100 | gcc_assert (!node->analyzed |
1101 | && !vec_safe_length (node->ref_list.references)); | |
40a7fe1e JH |
1102 | |
1103 | /* Never let cycles to creep into the symbol table alias references; | |
1104 | those will make alias walkers to be infinite. */ | |
67348ccc DM |
1105 | for (n = target; n && n->alias; |
1106 | n = n->analyzed ? symtab_alias_target (n) : NULL) | |
40a7fe1e JH |
1107 | if (n == node) |
1108 | { | |
1109 | if (is_a <cgraph_node> (node)) | |
67348ccc | 1110 | error ("function %q+D part of alias cycle", node->decl); |
40a7fe1e | 1111 | else if (is_a <varpool_node> (node)) |
67348ccc | 1112 | error ("variable %q+D part of alias cycle", node->decl); |
40a7fe1e JH |
1113 | else |
1114 | gcc_unreachable (); | |
67348ccc | 1115 | node->alias = false; |
40a7fe1e JH |
1116 | return false; |
1117 | } | |
1118 | ||
1119 | /* "analyze" the node - i.e. mark the reference. */ | |
67348ccc DM |
1120 | node->definition = true; |
1121 | node->alias = true; | |
1122 | node->analyzed = true; | |
40a7fe1e JH |
1123 | ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); |
1124 | ||
1125 | /* Alias targets become reudndant after alias is resolved into an reference. | |
1126 | We do not want to keep it around or we would have to mind updating them | |
1127 | when renaming symbols. */ | |
67348ccc | 1128 | node->alias_target = NULL; |
40a7fe1e | 1129 | |
67348ccc | 1130 | if (node->cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) |
40a7fe1e JH |
1131 | fixup_same_cpp_alias_visibility (node, target); |
1132 | ||
1133 | /* If alias has address taken, so does the target. */ | |
67348ccc DM |
1134 | if (node->address_taken) |
1135 | symtab_alias_ultimate_target (target, NULL)->address_taken = true; | |
40a7fe1e JH |
1136 | return true; |
1137 | } | |
af15184a JH |
1138 | |
1139 | /* Call calback on NODE and aliases associated to NODE. | |
1140 | When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are | |
1141 | skipped. */ | |
1142 | ||
1143 | bool | |
5e20cdc9 DM |
1144 | symtab_for_node_and_aliases (symtab_node *node, |
1145 | bool (*callback) (symtab_node *, void *), | |
af15184a JH |
1146 | void *data, |
1147 | bool include_overwritable) | |
1148 | { | |
1149 | int i; | |
1150 | struct ipa_ref *ref; | |
1151 | ||
1152 | if (callback (node, data)) | |
1153 | return true; | |
67348ccc | 1154 | for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) |
af15184a JH |
1155 | if (ref->use == IPA_REF_ALIAS) |
1156 | { | |
5e20cdc9 | 1157 | symtab_node *alias = ref->referring; |
af15184a JH |
1158 | if (include_overwritable |
1159 | || symtab_node_availability (alias) > AVAIL_OVERWRITABLE) | |
1160 | if (symtab_for_node_and_aliases (alias, callback, data, | |
1161 | include_overwritable)) | |
1162 | return true; | |
1163 | } | |
1164 | return false; | |
1165 | } | |
1166 | ||
1167 | /* Worker searching nonoverwritable alias. */ | |
1168 | ||
1169 | static bool | |
5e20cdc9 | 1170 | symtab_nonoverwritable_alias_1 (symtab_node *node, void *data) |
af15184a | 1171 | { |
67348ccc | 1172 | if (decl_binds_to_current_def_p (node->decl)) |
af15184a | 1173 | { |
5e20cdc9 | 1174 | *(symtab_node **)data = node; |
af15184a JH |
1175 | return true; |
1176 | } | |
1177 | return false; | |
1178 | } | |
1179 | ||
1180 | /* If NODE can not be overwriten by static or dynamic linker to point to different | |
1181 | definition, return NODE. Otherwise look for alias with such property and if | |
1182 | none exists, introduce new one. */ | |
1183 | ||
5e20cdc9 DM |
1184 | symtab_node * |
1185 | symtab_nonoverwritable_alias (symtab_node *node) | |
af15184a JH |
1186 | { |
1187 | tree new_decl; | |
5e20cdc9 | 1188 | symtab_node *new_node = NULL; |
8a41354f JH |
1189 | |
1190 | /* First try to look up existing alias or base object | |
1191 | (if that is already non-overwritable). */ | |
1192 | node = symtab_alias_ultimate_target (node, NULL); | |
67348ccc | 1193 | gcc_assert (!node->alias && !node->weakref); |
af15184a JH |
1194 | symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, |
1195 | (void *)&new_node, true); | |
1196 | if (new_node) | |
1197 | return new_node; | |
cdb87c08 JH |
1198 | #ifndef ASM_OUTPUT_DEF |
1199 | /* If aliases aren't supported by the assembler, fail. */ | |
1200 | return NULL; | |
1201 | #endif | |
af15184a | 1202 | |
8a41354f | 1203 | /* Otherwise create a new one. */ |
67348ccc DM |
1204 | new_decl = copy_node (node->decl); |
1205 | DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias"); | |
af15184a JH |
1206 | if (TREE_CODE (new_decl) == FUNCTION_DECL) |
1207 | DECL_STRUCT_FUNCTION (new_decl) = NULL; | |
1208 | DECL_INITIAL (new_decl) = NULL; | |
1209 | SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | |
1210 | SET_DECL_RTL (new_decl, NULL); | |
1211 | ||
1212 | /* Update the properties. */ | |
1213 | DECL_EXTERNAL (new_decl) = 0; | |
67348ccc | 1214 | if (DECL_ONE_ONLY (node->decl)) |
af15184a JH |
1215 | DECL_SECTION_NAME (new_decl) = NULL; |
1216 | DECL_COMDAT_GROUP (new_decl) = 0; | |
1217 | TREE_PUBLIC (new_decl) = 0; | |
1218 | DECL_COMDAT (new_decl) = 0; | |
1219 | DECL_WEAK (new_decl) = 0; | |
1220 | DECL_VIRTUAL_P (new_decl) = 0; | |
1221 | if (TREE_CODE (new_decl) == FUNCTION_DECL) | |
1222 | { | |
1223 | DECL_STATIC_CONSTRUCTOR (new_decl) = 0; | |
1224 | DECL_STATIC_DESTRUCTOR (new_decl) = 0; | |
67348ccc DM |
1225 | new_node = cgraph_create_function_alias |
1226 | (new_decl, node->decl); | |
af15184a JH |
1227 | } |
1228 | else | |
67348ccc DM |
1229 | new_node = varpool_create_variable_alias (new_decl, |
1230 | node->decl); | |
af15184a | 1231 | symtab_resolve_alias (new_node, node); |
fc11f321 | 1232 | gcc_assert (decl_binds_to_current_def_p (new_decl)); |
af15184a JH |
1233 | return new_node; |
1234 | } | |
fc11f321 JH |
1235 | |
1236 | /* Return true if A and B represents semantically equivalent symbols. */ | |
1237 | ||
1238 | bool | |
5e20cdc9 DM |
1239 | symtab_semantically_equivalent_p (symtab_node *a, |
1240 | symtab_node *b) | |
fc11f321 JH |
1241 | { |
1242 | enum availability avail; | |
5e20cdc9 DM |
1243 | symtab_node *ba; |
1244 | symtab_node *bb; | |
fc11f321 JH |
1245 | |
1246 | /* Equivalent functions are equivalent. */ | |
67348ccc | 1247 | if (a->decl == b->decl) |
fc11f321 JH |
1248 | return true; |
1249 | ||
1250 | /* If symbol is not overwritable by different implementation, | |
1251 | walk to the base object it defines. */ | |
1252 | ba = symtab_alias_ultimate_target (a, &avail); | |
1253 | if (avail >= AVAIL_AVAILABLE) | |
1254 | { | |
1255 | if (ba == b) | |
1256 | return true; | |
1257 | } | |
1258 | else | |
1259 | ba = a; | |
1260 | bb = symtab_alias_ultimate_target (b, &avail); | |
1261 | if (avail >= AVAIL_AVAILABLE) | |
1262 | { | |
1263 | if (a == bb) | |
1264 | return true; | |
1265 | } | |
1266 | else | |
1267 | bb = b; | |
1268 | return bb == ba; | |
1269 | } | |
1ab24192 | 1270 | #include "gt-symtab.h" |