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