]>
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" |
51ce5652 | 45 | #include "ipa-utils.h" |
c16b9430 | 46 | #include "calls.h" |
51ce5652 | 47 | |
48 | static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; | |
cf951b1a | 49 | |
50 | const char * const ld_plugin_symbol_resolution_names[]= | |
51 | { | |
52 | "", | |
53 | "undef", | |
54 | "prevailing_def", | |
55 | "prevailing_def_ironly", | |
56 | "preempted_reg", | |
57 | "preempted_ir", | |
58 | "resolved_ir", | |
59 | "resolved_exec", | |
60 | "resolved_dyn", | |
61 | "prevailing_def_ironly_exp" | |
62 | }; | |
cfbe30aa | 63 | |
738a6bda | 64 | |
65 | /* Hash table used to hold sectoons. */ | |
66 | static GTY((param_is (section_hash_entry))) htab_t section_hash; | |
67 | ||
cfbe30aa | 68 | /* Hash table used to convert assembler names into nodes. */ |
452659af | 69 | static GTY((param_is (symtab_node))) htab_t assembler_name_hash; |
0704fb2e | 70 | |
9db80d42 | 71 | /* Map from a symbol to initialization/finalization priorities. */ |
72 | struct GTY(()) symbol_priority_map { | |
73 | symtab_node *symbol; | |
74 | priority_type init; | |
75 | priority_type fini; | |
76 | }; | |
77 | ||
78 | /* Hash table used to hold init priorities. */ | |
79 | static GTY ((param_is (struct symbol_priority_map))) | |
80 | htab_t init_priority_hash; | |
81 | ||
0704fb2e | 82 | /* Linked list of symbol table nodes. */ |
452659af | 83 | symtab_node *symtab_nodes; |
0704fb2e | 84 | |
85 | /* The order index of the next symtab node to be created. This is | |
86 | used so that we can sort the cgraph nodes in order by when we saw | |
87 | them, to support -fno-toplevel-reorder. */ | |
88 | int symtab_order; | |
89 | ||
0e80b01d | 90 | /* Hash asmnames ignoring the user specified marks. */ |
91 | ||
92 | static hashval_t | |
93 | decl_assembler_name_hash (const_tree asmname) | |
94 | { | |
95 | if (IDENTIFIER_POINTER (asmname)[0] == '*') | |
96 | { | |
97 | const char *decl_str = IDENTIFIER_POINTER (asmname) + 1; | |
98 | size_t ulp_len = strlen (user_label_prefix); | |
99 | ||
100 | if (ulp_len == 0) | |
101 | ; | |
102 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
103 | decl_str += ulp_len; | |
104 | ||
105 | return htab_hash_string (decl_str); | |
106 | } | |
107 | ||
108 | return htab_hash_string (IDENTIFIER_POINTER (asmname)); | |
109 | } | |
110 | ||
111 | ||
cfbe30aa | 112 | /* Returns a hash code for P. */ |
113 | ||
114 | static hashval_t | |
115 | hash_node_by_assembler_name (const void *p) | |
116 | { | |
452659af | 117 | const symtab_node *n = (const symtab_node *) p; |
02774f2d | 118 | return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl)); |
cfbe30aa | 119 | } |
120 | ||
0e80b01d | 121 | /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ |
122 | ||
123 | static bool | |
124 | decl_assembler_name_equal (tree decl, const_tree asmname) | |
125 | { | |
126 | tree decl_asmname = DECL_ASSEMBLER_NAME (decl); | |
127 | const char *decl_str; | |
128 | const char *asmname_str; | |
129 | bool test = false; | |
130 | ||
131 | if (decl_asmname == asmname) | |
132 | return true; | |
133 | ||
134 | decl_str = IDENTIFIER_POINTER (decl_asmname); | |
135 | asmname_str = IDENTIFIER_POINTER (asmname); | |
136 | ||
137 | ||
138 | /* If the target assembler name was set by the user, things are trickier. | |
139 | We have a leading '*' to begin with. After that, it's arguable what | |
140 | is the correct thing to do with -fleading-underscore. Arguably, we've | |
141 | historically been doing the wrong thing in assemble_alias by always | |
142 | printing the leading underscore. Since we're not changing that, make | |
143 | sure user_label_prefix follows the '*' before matching. */ | |
144 | if (decl_str[0] == '*') | |
145 | { | |
146 | size_t ulp_len = strlen (user_label_prefix); | |
147 | ||
148 | decl_str ++; | |
149 | ||
150 | if (ulp_len == 0) | |
151 | test = true; | |
152 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
153 | decl_str += ulp_len, test=true; | |
154 | else | |
155 | decl_str --; | |
156 | } | |
157 | if (asmname_str[0] == '*') | |
158 | { | |
159 | size_t ulp_len = strlen (user_label_prefix); | |
160 | ||
161 | asmname_str ++; | |
162 | ||
163 | if (ulp_len == 0) | |
164 | test = true; | |
165 | else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0) | |
166 | asmname_str += ulp_len, test=true; | |
167 | else | |
168 | asmname_str --; | |
169 | } | |
170 | ||
171 | if (!test) | |
172 | return false; | |
173 | return strcmp (decl_str, asmname_str) == 0; | |
174 | } | |
175 | ||
176 | ||
cfbe30aa | 177 | /* Returns nonzero if P1 and P2 are equal. */ |
178 | ||
179 | static int | |
180 | eq_assembler_name (const void *p1, const void *p2) | |
181 | { | |
452659af | 182 | const symtab_node *n1 = (const symtab_node *) p1; |
cfbe30aa | 183 | const_tree name = (const_tree)p2; |
02774f2d | 184 | return (decl_assembler_name_equal (n1->decl, name)); |
cfbe30aa | 185 | } |
186 | ||
187 | /* Insert NODE to assembler name hash. */ | |
188 | ||
189 | static void | |
452659af | 190 | insert_to_assembler_name_hash (symtab_node *node, bool with_clones) |
cfbe30aa | 191 | { |
13cbeaac | 192 | if (is_a <varpool_node *> (node) && DECL_HARD_REGISTER (node->decl)) |
c9aa6453 | 193 | return; |
02774f2d | 194 | gcc_checking_assert (!node->previous_sharing_asm_name |
195 | && !node->next_sharing_asm_name); | |
cfbe30aa | 196 | if (assembler_name_hash) |
197 | { | |
198 | void **aslot; | |
6f4cfc6d | 199 | struct cgraph_node *cnode; |
02774f2d | 200 | tree decl = node->decl; |
6f4cfc6d | 201 | |
02774f2d | 202 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
cfbe30aa | 203 | |
204 | aslot = htab_find_slot_with_hash (assembler_name_hash, name, | |
205 | decl_assembler_name_hash (name), | |
206 | INSERT); | |
207 | gcc_assert (*aslot != node); | |
452659af | 208 | node->next_sharing_asm_name = (symtab_node *)*aslot; |
cfbe30aa | 209 | if (*aslot != NULL) |
452659af | 210 | ((symtab_node *)*aslot)->previous_sharing_asm_name = node; |
cfbe30aa | 211 | *aslot = node; |
6f4cfc6d | 212 | |
213 | /* Update also possible inline clones sharing a decl. */ | |
13cbeaac | 214 | cnode = dyn_cast <cgraph_node *> (node); |
6f4cfc6d | 215 | if (cnode && cnode->clones && with_clones) |
216 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
02774f2d | 217 | if (cnode->decl == decl) |
218 | insert_to_assembler_name_hash (cnode, true); | |
cfbe30aa | 219 | } |
220 | ||
221 | } | |
222 | ||
223 | /* Remove NODE from assembler name hash. */ | |
224 | ||
225 | static void | |
452659af | 226 | unlink_from_assembler_name_hash (symtab_node *node, bool with_clones) |
cfbe30aa | 227 | { |
228 | if (assembler_name_hash) | |
229 | { | |
6f4cfc6d | 230 | struct cgraph_node *cnode; |
02774f2d | 231 | tree decl = node->decl; |
6f4cfc6d | 232 | |
02774f2d | 233 | if (node->next_sharing_asm_name) |
234 | node->next_sharing_asm_name->previous_sharing_asm_name | |
235 | = node->previous_sharing_asm_name; | |
236 | if (node->previous_sharing_asm_name) | |
cfbe30aa | 237 | { |
02774f2d | 238 | node->previous_sharing_asm_name->next_sharing_asm_name |
239 | = node->next_sharing_asm_name; | |
cfbe30aa | 240 | } |
241 | else | |
242 | { | |
02774f2d | 243 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
cfbe30aa | 244 | void **slot; |
245 | slot = htab_find_slot_with_hash (assembler_name_hash, name, | |
246 | decl_assembler_name_hash (name), | |
247 | NO_INSERT); | |
248 | gcc_assert (*slot == node); | |
02774f2d | 249 | if (!node->next_sharing_asm_name) |
cfbe30aa | 250 | htab_clear_slot (assembler_name_hash, slot); |
251 | else | |
02774f2d | 252 | *slot = node->next_sharing_asm_name; |
cfbe30aa | 253 | } |
02774f2d | 254 | node->next_sharing_asm_name = NULL; |
255 | node->previous_sharing_asm_name = NULL; | |
6f4cfc6d | 256 | |
257 | /* Update also possible inline clones sharing a decl. */ | |
13cbeaac | 258 | cnode = dyn_cast <cgraph_node *> (node); |
6f4cfc6d | 259 | if (cnode && cnode->clones && with_clones) |
260 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
02774f2d | 261 | if (cnode->decl == decl) |
262 | unlink_from_assembler_name_hash (cnode, true); | |
cfbe30aa | 263 | } |
264 | } | |
265 | ||
c9aa6453 | 266 | /* Arrange node to be first in its entry of assembler_name_hash. */ |
267 | ||
268 | void | |
452659af | 269 | symtab_prevail_in_asm_name_hash (symtab_node *node) |
c9aa6453 | 270 | { |
6f4cfc6d | 271 | unlink_from_assembler_name_hash (node, false); |
272 | insert_to_assembler_name_hash (node, false); | |
c9aa6453 | 273 | } |
274 | ||
cfbe30aa | 275 | |
0704fb2e | 276 | /* Add node into symbol table. This function is not used directly, but via |
277 | cgraph/varpool node creation routines. */ | |
278 | ||
279 | void | |
452659af | 280 | symtab_register_node (symtab_node *node) |
0704fb2e | 281 | { |
02774f2d | 282 | node->next = symtab_nodes; |
283 | node->previous = NULL; | |
0704fb2e | 284 | if (symtab_nodes) |
02774f2d | 285 | symtab_nodes->previous = node; |
0704fb2e | 286 | symtab_nodes = node; |
287 | ||
8c016392 | 288 | if (!node->decl->decl_with_vis.symtab_node) |
289 | node->decl->decl_with_vis.symtab_node = node; | |
cfbe30aa | 290 | |
51ce5652 | 291 | node->ref_list.clear (); |
cfbe30aa | 292 | |
02774f2d | 293 | node->order = symtab_order++; |
0704fb2e | 294 | |
ad0fe105 | 295 | /* Be sure to do this last; C++ FE might create new nodes via |
296 | DECL_ASSEMBLER_NAME langhook! */ | |
6f4cfc6d | 297 | insert_to_assembler_name_hash (node, false); |
0704fb2e | 298 | } |
299 | ||
04f65f92 | 300 | /* Remove NODE from same comdat group. */ |
0704fb2e | 301 | |
302 | void | |
04f65f92 | 303 | symtab_remove_from_same_comdat_group (symtab_node *node) |
0704fb2e | 304 | { |
02774f2d | 305 | if (node->same_comdat_group) |
0704fb2e | 306 | { |
452659af | 307 | symtab_node *prev; |
02774f2d | 308 | for (prev = node->same_comdat_group; |
309 | prev->same_comdat_group != node; | |
310 | prev = prev->same_comdat_group) | |
0704fb2e | 311 | ; |
02774f2d | 312 | if (node->same_comdat_group == prev) |
313 | prev->same_comdat_group = NULL; | |
0704fb2e | 314 | else |
02774f2d | 315 | prev->same_comdat_group = node->same_comdat_group; |
316 | node->same_comdat_group = NULL; | |
0704fb2e | 317 | } |
04f65f92 | 318 | } |
319 | ||
320 | /* Remove node from symbol table. This function is not used directly, but via | |
321 | cgraph/varpool node removal routines. */ | |
322 | ||
323 | void | |
324 | symtab_unregister_node (symtab_node *node) | |
325 | { | |
51ce5652 | 326 | node->remove_all_references (); |
327 | node->remove_all_referring (); | |
04f65f92 | 328 | |
738a6bda | 329 | /* Remove reference to section. */ |
330 | node->set_section_for_node (NULL); | |
331 | ||
04f65f92 | 332 | symtab_remove_from_same_comdat_group (node); |
0704fb2e | 333 | |
02774f2d | 334 | if (node->previous) |
335 | node->previous->next = node->next; | |
0704fb2e | 336 | else |
02774f2d | 337 | symtab_nodes = node->next; |
338 | if (node->next) | |
339 | node->next->previous = node->previous; | |
340 | node->next = NULL; | |
341 | node->previous = NULL; | |
cfbe30aa | 342 | |
9e9c3e92 | 343 | /* During LTO symtab merging we temporarily corrupt decl to symtab node |
344 | hash. */ | |
8c016392 | 345 | gcc_assert (node->decl->decl_with_vis.symtab_node || in_lto_p); |
346 | if (node->decl->decl_with_vis.symtab_node == node) | |
cfbe30aa | 347 | { |
452659af | 348 | symtab_node *replacement_node = NULL; |
13cbeaac | 349 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
02774f2d | 350 | replacement_node = cgraph_find_replacement_node (cnode); |
8c016392 | 351 | node->decl->decl_with_vis.symtab_node = replacement_node; |
cfbe30aa | 352 | } |
13cbeaac | 353 | if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl)) |
46000538 | 354 | unlink_from_assembler_name_hash (node, false); |
9db80d42 | 355 | if (node->in_init_priority_hash) |
356 | { | |
357 | struct symbol_priority_map in; | |
358 | void **slot; | |
359 | in.symbol = node; | |
360 | ||
361 | slot = htab_find_slot (init_priority_hash, &in, NO_INSERT); | |
362 | if (slot) | |
363 | htab_clear_slot (init_priority_hash, slot); | |
364 | } | |
cfbe30aa | 365 | } |
366 | ||
0704fb2e | 367 | |
368 | /* Remove symtab NODE from the symbol table. */ | |
369 | ||
370 | void | |
452659af | 371 | symtab_remove_node (symtab_node *node) |
0704fb2e | 372 | { |
13cbeaac | 373 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
2dc9831f | 374 | cgraph_remove_node (cnode); |
13cbeaac | 375 | else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
2dc9831f | 376 | varpool_remove_node (vnode); |
0704fb2e | 377 | } |
cfbe30aa | 378 | |
c9aa6453 | 379 | /* Initalize asm name hash unless. */ |
cfbe30aa | 380 | |
c9aa6453 | 381 | void |
382 | symtab_initialize_asm_name_hash (void) | |
cfbe30aa | 383 | { |
452659af | 384 | symtab_node *node; |
cfbe30aa | 385 | if (!assembler_name_hash) |
386 | { | |
387 | assembler_name_hash = | |
388 | htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name, | |
389 | NULL); | |
390 | FOR_EACH_SYMBOL (node) | |
6f4cfc6d | 391 | insert_to_assembler_name_hash (node, false); |
cfbe30aa | 392 | } |
c9aa6453 | 393 | } |
cfbe30aa | 394 | |
c9aa6453 | 395 | /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. |
396 | Return NULL if there's no such node. */ | |
397 | ||
452659af | 398 | symtab_node * |
c9aa6453 | 399 | symtab_node_for_asm (const_tree asmname) |
400 | { | |
452659af | 401 | symtab_node *node; |
c9aa6453 | 402 | void **slot; |
403 | ||
404 | symtab_initialize_asm_name_hash (); | |
cfbe30aa | 405 | slot = htab_find_slot_with_hash (assembler_name_hash, asmname, |
406 | decl_assembler_name_hash (asmname), | |
407 | NO_INSERT); | |
408 | ||
409 | if (slot) | |
410 | { | |
452659af | 411 | node = (symtab_node *) *slot; |
cfbe30aa | 412 | return node; |
413 | } | |
414 | return NULL; | |
415 | } | |
416 | ||
417 | /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */ | |
418 | ||
419 | void | |
420 | change_decl_assembler_name (tree decl, tree name) | |
421 | { | |
452659af | 422 | symtab_node *node = NULL; |
cfbe30aa | 423 | |
424 | /* We can have user ASM names on things, like global register variables, that | |
425 | are not in the symbol table. */ | |
426 | if ((TREE_CODE (decl) == VAR_DECL | |
427 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) | |
428 | || TREE_CODE (decl) == FUNCTION_DECL) | |
429 | node = symtab_get_node (decl); | |
430 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) | |
431 | { | |
432 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
433 | if (node) | |
6f4cfc6d | 434 | insert_to_assembler_name_hash (node, true); |
cfbe30aa | 435 | } |
436 | else | |
437 | { | |
438 | if (name == DECL_ASSEMBLER_NAME (decl)) | |
439 | return; | |
440 | ||
2fe870c5 | 441 | tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) |
442 | ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) | |
443 | : NULL); | |
cfbe30aa | 444 | if (node) |
6f4cfc6d | 445 | unlink_from_assembler_name_hash (node, true); |
cfbe30aa | 446 | if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) |
447 | && DECL_RTL_SET_P (decl)) | |
448 | warning (0, "%D renamed after being referenced in assembly", decl); | |
449 | ||
450 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
2fe870c5 | 451 | if (alias) |
452 | { | |
453 | IDENTIFIER_TRANSPARENT_ALIAS (name) = 1; | |
7b324376 | 454 | TREE_CHAIN (name) = alias; |
2fe870c5 | 455 | } |
cfbe30aa | 456 | if (node) |
6f4cfc6d | 457 | insert_to_assembler_name_hash (node, true); |
cfbe30aa | 458 | } |
459 | } | |
460 | ||
cf951b1a | 461 | /* Add NEW_ to the same comdat group that OLD is in. */ |
462 | ||
463 | void | |
452659af | 464 | symtab_add_to_same_comdat_group (symtab_node *new_node, |
465 | symtab_node *old_node) | |
cf951b1a | 466 | { |
8c016392 | 467 | gcc_assert (old_node->get_comdat_group ()); |
02774f2d | 468 | gcc_assert (!new_node->same_comdat_group); |
cf951b1a | 469 | gcc_assert (new_node != old_node); |
470 | ||
8c016392 | 471 | new_node->set_comdat_group (old_node->get_comdat_group ()); |
02774f2d | 472 | new_node->same_comdat_group = old_node; |
473 | if (!old_node->same_comdat_group) | |
474 | old_node->same_comdat_group = new_node; | |
cf951b1a | 475 | else |
476 | { | |
452659af | 477 | symtab_node *n; |
02774f2d | 478 | for (n = old_node->same_comdat_group; |
479 | n->same_comdat_group != old_node; | |
480 | n = n->same_comdat_group) | |
cf951b1a | 481 | ; |
02774f2d | 482 | n->same_comdat_group = new_node; |
cf951b1a | 483 | } |
484 | } | |
485 | ||
486 | /* Dissolve the same_comdat_group list in which NODE resides. */ | |
487 | ||
488 | void | |
452659af | 489 | symtab_dissolve_same_comdat_group_list (symtab_node *node) |
cf951b1a | 490 | { |
452659af | 491 | symtab_node *n = node; |
492 | symtab_node *next; | |
cf951b1a | 493 | |
02774f2d | 494 | if (!node->same_comdat_group) |
cf951b1a | 495 | return; |
496 | do | |
497 | { | |
02774f2d | 498 | next = n->same_comdat_group; |
499 | n->same_comdat_group = NULL; | |
8c016392 | 500 | /* Clear comdat_group for comdat locals, since |
468088ac | 501 | make_decl_local doesn't. */ |
502 | if (!TREE_PUBLIC (n->decl)) | |
8c016392 | 503 | n->set_comdat_group (NULL); |
cf951b1a | 504 | n = next; |
505 | } | |
506 | while (n != node); | |
507 | } | |
508 | ||
18841b0c | 509 | /* Return printable assembler name of NODE. |
510 | This function is used only for debugging. When assembler name | |
511 | is unknown go with identifier name. */ | |
512 | ||
513 | const char * | |
f1c8b4d7 | 514 | symtab_node::asm_name () const |
18841b0c | 515 | { |
f1c8b4d7 | 516 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) |
517 | return lang_hooks.decl_printable_name (decl, 2); | |
518 | return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
18841b0c | 519 | } |
520 | ||
521 | /* Return printable identifier name. */ | |
522 | ||
523 | const char * | |
f1c8b4d7 | 524 | symtab_node::name () const |
18841b0c | 525 | { |
f1c8b4d7 | 526 | return lang_hooks.decl_printable_name (decl, 2); |
18841b0c | 527 | } |
528 | ||
51ce5652 | 529 | /* Return ipa reference from this symtab_node to |
530 | REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type | |
531 | of the use. */ | |
532 | ||
533 | struct ipa_ref * | |
534 | symtab_node::add_reference (symtab_node *referred_node, | |
535 | enum ipa_ref_use use_type) | |
536 | { | |
537 | return add_reference (referred_node, use_type, NULL); | |
538 | } | |
539 | ||
540 | ||
541 | /* Return ipa reference from this symtab_node to | |
542 | REFERED_NODE or REFERED_VARPOOL_NODE. USE_TYPE specify type | |
543 | of the use and STMT the statement (if it exists). */ | |
544 | ||
545 | struct ipa_ref * | |
546 | symtab_node::add_reference (symtab_node *referred_node, | |
547 | enum ipa_ref_use use_type, gimple stmt) | |
548 | { | |
549 | struct ipa_ref *ref = NULL, *ref2 = NULL; | |
550 | struct ipa_ref_list *list, *list2; | |
551 | ipa_ref_t *old_references; | |
552 | ||
553 | gcc_checking_assert (!stmt || is_a <cgraph_node *> (this)); | |
554 | gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); | |
555 | ||
556 | list = &ref_list; | |
557 | old_references = vec_safe_address (list->references); | |
558 | vec_safe_grow (list->references, vec_safe_length (list->references) + 1); | |
559 | ref = &list->references->last (); | |
560 | ||
561 | list2 = &referred_node->ref_list; | |
e4a2b488 | 562 | |
563 | /* IPA_REF_ALIAS is always inserted at the beginning of the list. */ | |
564 | if(use_type == IPA_REF_ALIAS) | |
565 | { | |
566 | list2->referring.safe_insert (0, ref); | |
567 | ref->referred_index = 0; | |
568 | ||
569 | for (unsigned int i = 1; i < list2->referring.length (); i++) | |
570 | list2->referring[i]->referred_index = i; | |
571 | } | |
572 | else | |
573 | { | |
574 | list2->referring.safe_push (ref); | |
575 | ref->referred_index = list2->referring.length () - 1; | |
576 | } | |
577 | ||
51ce5652 | 578 | ref->referring = this; |
579 | ref->referred = referred_node; | |
580 | ref->stmt = stmt; | |
581 | ref->lto_stmt_uid = 0; | |
582 | ref->use = use_type; | |
583 | ref->speculative = 0; | |
584 | ||
585 | /* If vector was moved in memory, update pointers. */ | |
586 | if (old_references != list->references->address ()) | |
587 | { | |
588 | int i; | |
589 | for (i = 0; iterate_reference(i, ref2); i++) | |
590 | ref2->referred_ref_list ()->referring[ref2->referred_index] = ref2; | |
591 | } | |
592 | return ref; | |
593 | } | |
594 | ||
595 | /* If VAL is a reference to a function or a variable, add a reference from | |
596 | this symtab_node to the corresponding symbol table node. USE_TYPE specify | |
597 | type of the use and STMT the statement (if it exists). Return the new | |
598 | reference or NULL if none was created. */ | |
599 | ||
600 | struct ipa_ref * | |
601 | symtab_node::maybe_add_reference (tree val, enum ipa_ref_use use_type, | |
602 | gimple stmt) | |
603 | { | |
604 | STRIP_NOPS (val); | |
605 | if (TREE_CODE (val) != ADDR_EXPR) | |
606 | return NULL; | |
607 | val = get_base_var (val); | |
608 | if (val && (TREE_CODE (val) == FUNCTION_DECL | |
609 | || TREE_CODE (val) == VAR_DECL)) | |
610 | { | |
611 | symtab_node *referred = symtab_get_node (val); | |
612 | gcc_checking_assert (referred); | |
613 | return add_reference (referred, use_type, stmt); | |
614 | } | |
615 | return NULL; | |
616 | } | |
617 | ||
618 | /* Clone all references from symtab NODE to this symtab_node. */ | |
619 | ||
620 | void | |
621 | symtab_node::clone_references (struct symtab_node *node) | |
622 | { | |
623 | struct ipa_ref *ref = NULL, *ref2 = NULL; | |
624 | int i; | |
625 | for (i = 0; node->iterate_reference (i, ref); i++) | |
626 | { | |
627 | bool speculative = ref->speculative; | |
628 | unsigned int stmt_uid = ref->lto_stmt_uid; | |
629 | ||
630 | ref2 = add_reference (ref->referred, ref->use, ref->stmt); | |
631 | ref2->speculative = speculative; | |
632 | ref2->lto_stmt_uid = stmt_uid; | |
633 | } | |
634 | } | |
635 | ||
636 | /* Clone all referring from symtab NODE to this symtab_node. */ | |
637 | ||
638 | void | |
639 | symtab_node::clone_referring (struct symtab_node *node) | |
640 | { | |
641 | struct ipa_ref *ref = NULL, *ref2 = NULL; | |
642 | int i; | |
643 | for (i = 0; node->iterate_referring(i, ref); i++) | |
644 | { | |
645 | bool speculative = ref->speculative; | |
646 | unsigned int stmt_uid = ref->lto_stmt_uid; | |
647 | ||
648 | ref2 = ref->referring->add_reference (this, ref->use, ref->stmt); | |
649 | ref2->speculative = speculative; | |
650 | ref2->lto_stmt_uid = stmt_uid; | |
651 | } | |
652 | } | |
653 | ||
654 | /* Clone reference REF to this symtab_node and set its stmt to STMT. */ | |
655 | ||
656 | struct ipa_ref * | |
657 | symtab_node::clone_reference (struct ipa_ref *ref, gimple stmt) | |
658 | { | |
659 | bool speculative = ref->speculative; | |
660 | unsigned int stmt_uid = ref->lto_stmt_uid; | |
661 | struct ipa_ref *ref2; | |
662 | ||
663 | ref2 = add_reference (ref->referred, ref->use, stmt); | |
664 | ref2->speculative = speculative; | |
665 | ref2->lto_stmt_uid = stmt_uid; | |
666 | return ref2; | |
667 | } | |
668 | ||
669 | /* Find the structure describing a reference to REFERRED_NODE | |
670 | and associated with statement STMT. */ | |
671 | ||
672 | struct ipa_ref * | |
673 | symtab_node::find_reference (symtab_node *referred_node, | |
674 | gimple stmt, unsigned int lto_stmt_uid) | |
675 | { | |
676 | struct ipa_ref *r = NULL; | |
677 | int i; | |
678 | ||
679 | for (i = 0; iterate_reference (i, r); i++) | |
680 | if (r->referred == referred_node | |
681 | && !r->speculative | |
682 | && ((stmt && r->stmt == stmt) | |
683 | || (lto_stmt_uid && r->lto_stmt_uid == lto_stmt_uid) | |
684 | || (!stmt && !lto_stmt_uid && !r->stmt && !r->lto_stmt_uid))) | |
685 | return r; | |
686 | return NULL; | |
687 | } | |
688 | ||
689 | /* Remove all references that are associated with statement STMT. */ | |
690 | ||
691 | void | |
692 | symtab_node::remove_stmt_references (gimple stmt) | |
693 | { | |
694 | struct ipa_ref *r = NULL; | |
695 | int i = 0; | |
696 | ||
697 | while (iterate_reference (i, r)) | |
698 | if (r->stmt == stmt) | |
699 | r->remove_reference (); | |
700 | else | |
701 | i++; | |
702 | } | |
703 | ||
704 | /* Remove all stmt references in non-speculative references. | |
705 | Those are not maintained during inlining & clonning. | |
706 | The exception are speculative references that are updated along | |
707 | with callgraph edges associated with them. */ | |
708 | ||
709 | void | |
710 | symtab_node::clear_stmts_in_references (void) | |
711 | { | |
712 | struct ipa_ref *r = NULL; | |
713 | int i; | |
714 | ||
715 | for (i = 0; iterate_reference (i, r); i++) | |
716 | if (!r->speculative) | |
717 | { | |
718 | r->stmt = NULL; | |
719 | r->lto_stmt_uid = 0; | |
720 | } | |
721 | } | |
722 | ||
723 | /* Remove all references in ref list. */ | |
724 | ||
725 | void | |
726 | symtab_node::remove_all_references (void) | |
727 | { | |
728 | while (vec_safe_length (ref_list.references)) | |
729 | ref_list.references->last ().remove_reference (); | |
730 | vec_free (ref_list.references); | |
731 | } | |
732 | ||
733 | /* Remove all referring items in ref list. */ | |
734 | ||
735 | void | |
736 | symtab_node::remove_all_referring (void) | |
737 | { | |
738 | while (ref_list.referring.length ()) | |
739 | ref_list.referring.last ()->remove_reference (); | |
740 | ref_list.referring.release (); | |
741 | } | |
742 | ||
743 | /* Dump references in ref list to FILE. */ | |
744 | ||
745 | void | |
746 | symtab_node::dump_references (FILE *file) | |
747 | { | |
748 | struct ipa_ref *ref = NULL; | |
749 | int i; | |
750 | for (i = 0; iterate_reference (i, ref); i++) | |
751 | { | |
752 | fprintf (file, "%s/%i (%s)", | |
753 | ref->referred->asm_name (), | |
754 | ref->referred->order, | |
755 | ipa_ref_use_name [ref->use]); | |
756 | if (ref->speculative) | |
757 | fprintf (file, " (speculative)"); | |
758 | } | |
759 | fprintf (file, "\n"); | |
760 | } | |
761 | ||
762 | /* Dump referring in list to FILE. */ | |
763 | ||
764 | void | |
765 | symtab_node::dump_referring (FILE *file) | |
766 | { | |
767 | struct ipa_ref *ref = NULL; | |
768 | int i; | |
769 | for (i = 0; iterate_referring(i, ref); i++) | |
770 | { | |
771 | fprintf (file, "%s/%i (%s)", | |
772 | ref->referring->asm_name (), | |
773 | ref->referring->order, | |
774 | ipa_ref_use_name [ref->use]); | |
775 | if (ref->speculative) | |
776 | fprintf (file, " (speculative)"); | |
777 | } | |
778 | fprintf (file, "\n"); | |
779 | } | |
780 | ||
781 | /* Return true if list contains an alias. */ | |
782 | bool | |
783 | symtab_node::has_aliases_p (void) | |
784 | { | |
785 | struct ipa_ref *ref = NULL; | |
786 | int i; | |
787 | ||
788 | for (i = 0; iterate_referring (i, ref); i++) | |
789 | if (ref->use == IPA_REF_ALIAS) | |
790 | return true; | |
791 | return false; | |
792 | } | |
793 | ||
794 | /* Iterates I-th reference in the list, REF is also set. */ | |
795 | ||
796 | struct ipa_ref * | |
797 | symtab_node::iterate_reference (unsigned i, struct ipa_ref *&ref) | |
798 | { | |
799 | vec_safe_iterate (ref_list.references, i, &ref); | |
800 | ||
801 | return ref; | |
802 | } | |
803 | ||
804 | /* Iterates I-th referring item in the list, REF is also set. */ | |
805 | ||
806 | struct ipa_ref * | |
807 | symtab_node::iterate_referring (unsigned i, struct ipa_ref *&ref) | |
808 | { | |
809 | ref_list.referring.iterate (i, &ref); | |
810 | ||
811 | return ref; | |
812 | } | |
813 | ||
e4a2b488 | 814 | /* Iterates I-th referring alias item in the list, REF is also set. */ |
815 | ||
816 | struct ipa_ref * | |
817 | symtab_node::iterate_direct_aliases (unsigned i, struct ipa_ref *&ref) | |
818 | { | |
819 | ref_list.referring.iterate (i, &ref); | |
820 | ||
821 | if (ref && ref->use != IPA_REF_ALIAS) | |
822 | return NULL; | |
823 | ||
824 | return ref; | |
825 | } | |
826 | ||
827 | ||
18841b0c | 828 | static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; |
829 | ||
830 | /* Dump base fields of symtab nodes. Not to be used directly. */ | |
831 | ||
832 | void | |
452659af | 833 | dump_symtab_base (FILE *f, symtab_node *node) |
18841b0c | 834 | { |
835 | static const char * const visibility_types[] = { | |
836 | "default", "protected", "hidden", "internal" | |
837 | }; | |
838 | ||
839 | fprintf (f, "%s/%i (%s)", | |
f1c8b4d7 | 840 | node->asm_name (), |
02774f2d | 841 | node->order, |
f1c8b4d7 | 842 | node->name ()); |
18841b0c | 843 | dump_addr (f, " @", (void *)node); |
02774f2d | 844 | fprintf (f, "\n Type: %s", symtab_type_names[node->type]); |
15ca8f90 | 845 | |
02774f2d | 846 | if (node->definition) |
15ca8f90 | 847 | fprintf (f, " definition"); |
02774f2d | 848 | if (node->analyzed) |
15ca8f90 | 849 | fprintf (f, " analyzed"); |
02774f2d | 850 | if (node->alias) |
15ca8f90 | 851 | fprintf (f, " alias"); |
02774f2d | 852 | if (node->weakref) |
f2526cce | 853 | fprintf (f, " weakref"); |
02774f2d | 854 | if (node->cpp_implicit_alias) |
48669653 | 855 | fprintf (f, " cpp_implicit_alias"); |
02774f2d | 856 | if (node->alias_target) |
48669653 | 857 | fprintf (f, " target:%s", |
02774f2d | 858 | DECL_P (node->alias_target) |
48669653 | 859 | ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME |
02774f2d | 860 | (node->alias_target)) |
861 | : IDENTIFIER_POINTER (node->alias_target)); | |
fa4052b3 | 862 | if (node->body_removed) |
863 | fprintf (f, "\n Body removed by symtab_remove_unreachable_nodes"); | |
15ca8f90 | 864 | fprintf (f, "\n Visibility:"); |
02774f2d | 865 | if (node->in_other_partition) |
18841b0c | 866 | fprintf (f, " in_other_partition"); |
02774f2d | 867 | if (node->used_from_other_partition) |
18841b0c | 868 | fprintf (f, " used_from_other_partition"); |
02774f2d | 869 | if (node->force_output) |
8efa224a | 870 | fprintf (f, " force_output"); |
02774f2d | 871 | if (node->forced_by_abi) |
6a1c0403 | 872 | fprintf (f, " forced_by_abi"); |
02774f2d | 873 | if (node->externally_visible) |
a1d135c3 | 874 | fprintf (f, " externally_visible"); |
02774f2d | 875 | if (node->resolution != LDPR_UNKNOWN) |
18841b0c | 876 | fprintf (f, " %s", |
02774f2d | 877 | ld_plugin_symbol_resolution_names[(int)node->resolution]); |
878 | if (TREE_ASM_WRITTEN (node->decl)) | |
18841b0c | 879 | fprintf (f, " asm_written"); |
02774f2d | 880 | if (DECL_EXTERNAL (node->decl)) |
18841b0c | 881 | fprintf (f, " external"); |
02774f2d | 882 | if (TREE_PUBLIC (node->decl)) |
18841b0c | 883 | fprintf (f, " public"); |
02774f2d | 884 | if (DECL_COMMON (node->decl)) |
18841b0c | 885 | fprintf (f, " common"); |
02774f2d | 886 | if (DECL_WEAK (node->decl)) |
18841b0c | 887 | fprintf (f, " weak"); |
02774f2d | 888 | if (DECL_DLLIMPORT_P (node->decl)) |
18841b0c | 889 | fprintf (f, " dll_import"); |
02774f2d | 890 | if (DECL_COMDAT (node->decl)) |
18841b0c | 891 | fprintf (f, " comdat"); |
8c016392 | 892 | if (node->get_comdat_group ()) |
18841b0c | 893 | fprintf (f, " comdat_group:%s", |
1d9ca4f0 | 894 | IDENTIFIER_POINTER (node->get_comdat_group_id ())); |
02774f2d | 895 | if (DECL_ONE_ONLY (node->decl)) |
18841b0c | 896 | fprintf (f, " one_only"); |
71e19e54 | 897 | if (node->get_section ()) |
898 | fprintf (f, " section:%s", | |
e4c07a06 | 899 | node->get_section ()); |
900 | if (node->implicit_section) | |
901 | fprintf (f," (implicit_section)"); | |
02774f2d | 902 | if (DECL_VISIBILITY_SPECIFIED (node->decl)) |
18841b0c | 903 | fprintf (f, " visibility_specified"); |
02774f2d | 904 | if (DECL_VISIBILITY (node->decl)) |
18841b0c | 905 | fprintf (f, " visibility:%s", |
02774f2d | 906 | visibility_types [DECL_VISIBILITY (node->decl)]); |
907 | if (DECL_VIRTUAL_P (node->decl)) | |
18841b0c | 908 | fprintf (f, " virtual"); |
02774f2d | 909 | if (DECL_ARTIFICIAL (node->decl)) |
18841b0c | 910 | fprintf (f, " artificial"); |
02774f2d | 911 | if (TREE_CODE (node->decl) == FUNCTION_DECL) |
9a2639fc | 912 | { |
02774f2d | 913 | if (DECL_STATIC_CONSTRUCTOR (node->decl)) |
9a2639fc | 914 | fprintf (f, " constructor"); |
02774f2d | 915 | if (DECL_STATIC_DESTRUCTOR (node->decl)) |
9a2639fc | 916 | fprintf (f, " destructor"); |
917 | } | |
18841b0c | 918 | fprintf (f, "\n"); |
919 | ||
02774f2d | 920 | if (node->same_comdat_group) |
18841b0c | 921 | fprintf (f, " Same comdat group as: %s/%i\n", |
f1c8b4d7 | 922 | node->same_comdat_group->asm_name (), |
02774f2d | 923 | node->same_comdat_group->order); |
924 | if (node->next_sharing_asm_name) | |
18841b0c | 925 | fprintf (f, " next sharing asm name: %i\n", |
02774f2d | 926 | node->next_sharing_asm_name->order); |
927 | if (node->previous_sharing_asm_name) | |
18841b0c | 928 | fprintf (f, " previous sharing asm name: %i\n", |
02774f2d | 929 | node->previous_sharing_asm_name->order); |
18841b0c | 930 | |
02774f2d | 931 | if (node->address_taken) |
cfacc26f | 932 | fprintf (f, " Address is taken.\n"); |
02774f2d | 933 | if (node->aux) |
ff2a5ada | 934 | { |
935 | fprintf (f, " Aux:"); | |
02774f2d | 936 | dump_addr (f, " @", (void *)node->aux); |
ff2a5ada | 937 | } |
18841b0c | 938 | |
939 | fprintf (f, " References: "); | |
51ce5652 | 940 | node->dump_references (f); |
04ec15fa | 941 | fprintf (f, " Referring: "); |
51ce5652 | 942 | node->dump_referring (f); |
02774f2d | 943 | if (node->lto_file_data) |
c9aa6453 | 944 | fprintf (f, " Read from file: %s\n", |
02774f2d | 945 | node->lto_file_data->file_name); |
18841b0c | 946 | } |
947 | ||
948 | /* Dump symtab node. */ | |
949 | ||
950 | void | |
452659af | 951 | dump_symtab_node (FILE *f, symtab_node *node) |
18841b0c | 952 | { |
13cbeaac | 953 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
2dc9831f | 954 | dump_cgraph_node (f, cnode); |
13cbeaac | 955 | else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
2dc9831f | 956 | dump_varpool_node (f, vnode); |
18841b0c | 957 | } |
958 | ||
959 | /* Dump symbol table. */ | |
960 | ||
961 | void | |
962 | dump_symtab (FILE *f) | |
963 | { | |
452659af | 964 | symtab_node *node; |
18841b0c | 965 | fprintf (f, "Symbol table:\n\n"); |
966 | FOR_EACH_SYMBOL (node) | |
967 | dump_symtab_node (f, node); | |
968 | } | |
969 | ||
970 | /* Dump symtab node NODE to stderr. */ | |
971 | ||
972 | DEBUG_FUNCTION void | |
452659af | 973 | debug_symtab_node (symtab_node *node) |
18841b0c | 974 | { |
975 | dump_symtab_node (stderr, node); | |
976 | } | |
977 | ||
978 | /* Dump symbol table to stderr. */ | |
979 | ||
980 | DEBUG_FUNCTION void | |
981 | debug_symtab (void) | |
982 | { | |
983 | dump_symtab (stderr); | |
984 | } | |
985 | ||
3e7775f6 | 986 | /* Verify common part of symtab nodes. */ |
987 | ||
988 | DEBUG_FUNCTION bool | |
452659af | 989 | verify_symtab_base (symtab_node *node) |
3e7775f6 | 990 | { |
991 | bool error_found = false; | |
452659af | 992 | symtab_node *hashed_node; |
3e7775f6 | 993 | |
13cbeaac | 994 | if (is_a <cgraph_node *> (node)) |
3e7775f6 | 995 | { |
02774f2d | 996 | if (TREE_CODE (node->decl) != FUNCTION_DECL) |
3e7775f6 | 997 | { |
998 | error ("function symbol is not function"); | |
999 | error_found = true; | |
1000 | } | |
1001 | } | |
13cbeaac | 1002 | else if (is_a <varpool_node *> (node)) |
3e7775f6 | 1003 | { |
02774f2d | 1004 | if (TREE_CODE (node->decl) != VAR_DECL) |
3e7775f6 | 1005 | { |
1006 | error ("variable symbol is not variable"); | |
1007 | error_found = true; | |
1008 | } | |
1009 | } | |
1010 | else | |
1011 | { | |
1012 | error ("node has unknown type"); | |
1013 | error_found = true; | |
1014 | } | |
1015 | ||
da4b8721 | 1016 | if (cgraph_state != CGRAPH_LTO_STREAMING) |
3e7775f6 | 1017 | { |
02774f2d | 1018 | hashed_node = symtab_get_node (node->decl); |
da4b8721 | 1019 | if (!hashed_node) |
1020 | { | |
8c016392 | 1021 | error ("node not found node->decl->decl_with_vis.symtab_node"); |
da4b8721 | 1022 | error_found = true; |
1023 | } | |
a1d135c3 | 1024 | if (hashed_node != node |
13cbeaac | 1025 | && (!is_a <cgraph_node *> (node) |
1026 | || !dyn_cast <cgraph_node *> (node)->clone_of | |
1027 | || dyn_cast <cgraph_node *> (node)->clone_of->decl | |
02774f2d | 1028 | != node->decl)) |
a1d135c3 | 1029 | { |
8c016392 | 1030 | error ("node differs from node->decl->decl_with_vis.symtab_node"); |
a1d135c3 | 1031 | error_found = true; |
1032 | } | |
3e7775f6 | 1033 | } |
1034 | if (assembler_name_hash) | |
1035 | { | |
02774f2d | 1036 | hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl)); |
1037 | if (hashed_node && hashed_node->previous_sharing_asm_name) | |
3e7775f6 | 1038 | { |
1039 | error ("assembler name hash list corrupted"); | |
1040 | error_found = true; | |
1041 | } | |
1042 | while (hashed_node) | |
1043 | { | |
1044 | if (hashed_node == node) | |
1045 | break; | |
02774f2d | 1046 | hashed_node = hashed_node->next_sharing_asm_name; |
3e7775f6 | 1047 | } |
c9aa6453 | 1048 | if (!hashed_node |
13cbeaac | 1049 | && !(is_a <varpool_node *> (node) |
02774f2d | 1050 | || DECL_HARD_REGISTER (node->decl))) |
3e7775f6 | 1051 | { |
1052 | error ("node not found in symtab assembler name hash"); | |
1053 | error_found = true; | |
1054 | } | |
1055 | } | |
02774f2d | 1056 | if (node->previous_sharing_asm_name |
1057 | && node->previous_sharing_asm_name->next_sharing_asm_name != node) | |
3e7775f6 | 1058 | { |
1059 | error ("double linked list of assembler names corrupted"); | |
15ca8f90 | 1060 | error_found = true; |
1061 | } | |
02774f2d | 1062 | if (node->analyzed && !node->definition) |
15ca8f90 | 1063 | { |
1064 | error ("node is analyzed byt it is not a definition"); | |
1065 | error_found = true; | |
3e7775f6 | 1066 | } |
02774f2d | 1067 | if (node->cpp_implicit_alias && !node->alias) |
48669653 | 1068 | { |
1069 | error ("node is alias but not implicit alias"); | |
1070 | error_found = true; | |
1071 | } | |
02774f2d | 1072 | if (node->alias && !node->definition |
1073 | && !node->weakref) | |
48669653 | 1074 | { |
1075 | error ("node is alias but not definition"); | |
1076 | error_found = true; | |
1077 | } | |
02774f2d | 1078 | if (node->weakref && !node->alias) |
f2526cce | 1079 | { |
1080 | error ("node is weakref but not an alias"); | |
1081 | error_found = true; | |
1082 | } | |
02774f2d | 1083 | if (node->same_comdat_group) |
3e7775f6 | 1084 | { |
452659af | 1085 | symtab_node *n = node->same_comdat_group; |
3e7775f6 | 1086 | |
8c016392 | 1087 | if (!n->get_comdat_group ()) |
3e7775f6 | 1088 | { |
8c016392 | 1089 | error ("node is in same_comdat_group list but has no comdat_group"); |
3e7775f6 | 1090 | error_found = true; |
1091 | } | |
8c016392 | 1092 | if (n->get_comdat_group () != node->get_comdat_group ()) |
04f65f92 | 1093 | { |
1094 | error ("same_comdat_group list across different groups"); | |
1095 | error_found = true; | |
1096 | } | |
1097 | if (!n->definition) | |
1098 | { | |
1099 | error ("Node has same_comdat_group but it is not a definition"); | |
1100 | error_found = true; | |
1101 | } | |
02774f2d | 1102 | if (n->type != node->type) |
3e7775f6 | 1103 | { |
1104 | error ("mixing different types of symbol in same comdat groups is not supported"); | |
1105 | error_found = true; | |
1106 | } | |
1107 | if (n == node) | |
1108 | { | |
1109 | error ("node is alone in a comdat group"); | |
1110 | error_found = true; | |
1111 | } | |
1112 | do | |
1113 | { | |
02774f2d | 1114 | if (!n->same_comdat_group) |
3e7775f6 | 1115 | { |
1116 | error ("same_comdat_group is not a circular list"); | |
1117 | error_found = true; | |
1118 | break; | |
1119 | } | |
02774f2d | 1120 | n = n->same_comdat_group; |
3e7775f6 | 1121 | } |
1122 | while (n != node); | |
468088ac | 1123 | if (symtab_comdat_local_p (node)) |
1124 | { | |
51ce5652 | 1125 | struct ipa_ref *ref = NULL; |
e4c07a06 | 1126 | |
51ce5652 | 1127 | for (int i = 0; node->iterate_referring (i, ref); ++i) |
468088ac | 1128 | { |
1129 | if (!symtab_in_same_comdat_p (ref->referring, node)) | |
1130 | { | |
1131 | error ("comdat-local symbol referred to by %s outside its " | |
1132 | "comdat", | |
1133 | identifier_to_locale (ref->referring->name())); | |
1134 | error_found = true; | |
1135 | } | |
1136 | } | |
1137 | } | |
3e7775f6 | 1138 | } |
e4c07a06 | 1139 | if (node->implicit_section && !node->get_section ()) |
1140 | { | |
1141 | error ("implicit_section flag is set but section isn't"); | |
1142 | error_found = true; | |
1143 | } | |
1144 | if (node->get_section () && node->get_comdat_group () | |
1145 | && !node->implicit_section) | |
1146 | { | |
1147 | error ("Both section and comdat group is set"); | |
1148 | error_found = true; | |
1149 | } | |
1150 | /* TODO: Add string table for sections, so we do not keep holding duplicated | |
1151 | strings. */ | |
1152 | if (node->alias && node->definition | |
1153 | && node->get_section () != symtab_alias_target (node)->get_section () | |
1154 | && (!node->get_section() | |
1155 | || !symtab_alias_target (node)->get_section () | |
1156 | || strcmp (node->get_section(), | |
1157 | symtab_alias_target (node)->get_section ()))) | |
1158 | { | |
1159 | error ("Alias and target's section differs"); | |
1160 | dump_symtab_node (stderr, symtab_alias_target (node)); | |
1161 | error_found = true; | |
1162 | } | |
1163 | if (node->alias && node->definition | |
1164 | && node->get_comdat_group () != symtab_alias_target (node)->get_comdat_group ()) | |
1165 | { | |
1166 | error ("Alias and target's comdat groups differs"); | |
1167 | dump_symtab_node (stderr, symtab_alias_target (node)); | |
1168 | error_found = true; | |
1169 | } | |
1170 | ||
3e7775f6 | 1171 | return error_found; |
1172 | } | |
1173 | ||
1174 | /* Verify consistency of NODE. */ | |
1175 | ||
1176 | DEBUG_FUNCTION void | |
452659af | 1177 | verify_symtab_node (symtab_node *node) |
3e7775f6 | 1178 | { |
1179 | if (seen_error ()) | |
1180 | return; | |
1181 | ||
1182 | timevar_push (TV_CGRAPH_VERIFY); | |
13cbeaac | 1183 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
2dc9831f | 1184 | verify_cgraph_node (cnode); |
3e7775f6 | 1185 | else |
1186 | if (verify_symtab_base (node)) | |
1187 | { | |
1188 | dump_symtab_node (stderr, node); | |
1189 | internal_error ("verify_symtab_node failed"); | |
1190 | } | |
1191 | timevar_pop (TV_CGRAPH_VERIFY); | |
1192 | } | |
1193 | ||
1194 | /* Verify symbol table for internal consistency. */ | |
1195 | ||
1196 | DEBUG_FUNCTION void | |
1197 | verify_symtab (void) | |
1198 | { | |
452659af | 1199 | symtab_node *node; |
d62dd039 | 1200 | hash_map<tree, symtab_node *> comdat_head_map (251); |
e4c07a06 | 1201 | |
3e7775f6 | 1202 | FOR_EACH_SYMBOL (node) |
e4c07a06 | 1203 | { |
1204 | verify_symtab_node (node); | |
1205 | if (node->get_comdat_group ()) | |
1206 | { | |
1207 | symtab_node **entry, *s; | |
1208 | bool existed; | |
1209 | ||
d62dd039 | 1210 | entry = &comdat_head_map.get_or_insert (node->get_comdat_group (), |
1211 | &existed); | |
e4c07a06 | 1212 | if (!existed) |
1213 | *entry = node; | |
1214 | else | |
1215 | for (s = (*entry)->same_comdat_group; s != NULL && s != node; s = s->same_comdat_group) | |
1216 | if (!s || s == *entry) | |
1217 | { | |
1218 | error ("Two symbols with same comdat_group are not linked by the same_comdat_group list."); | |
1219 | dump_symtab_node (stderr, *entry); | |
1220 | dump_symtab_node (stderr, s); | |
1221 | internal_error ("verify_symtab failed"); | |
1222 | } | |
1223 | } | |
1224 | } | |
3e7775f6 | 1225 | } |
1226 | ||
cf951b1a | 1227 | /* Return true when RESOLUTION indicate that linker will use |
1228 | the symbol from non-LTO object files. */ | |
1229 | ||
1230 | bool | |
1231 | resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) | |
1232 | { | |
1233 | return (resolution == LDPR_PREVAILING_DEF | |
1234 | || resolution == LDPR_PREEMPTED_REG | |
1235 | || resolution == LDPR_RESOLVED_EXEC | |
1236 | || resolution == LDPR_RESOLVED_DYN); | |
1237 | } | |
1238 | ||
1239 | /* Return true when NODE is known to be used from other (non-LTO) object file. | |
1240 | Known only when doing LTO via linker plugin. */ | |
1241 | ||
1242 | bool | |
452659af | 1243 | symtab_used_from_object_file_p (symtab_node *node) |
cf951b1a | 1244 | { |
02774f2d | 1245 | if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) |
cf951b1a | 1246 | return false; |
02774f2d | 1247 | if (resolution_used_from_other_file_p (node->resolution)) |
cf951b1a | 1248 | return true; |
1249 | return false; | |
1250 | } | |
1251 | ||
1252 | /* Make DECL local. FIXME: We shouldn't need to mess with rtl this early, | |
1253 | but other code such as notice_global_symbol generates rtl. */ | |
48669653 | 1254 | |
cf951b1a | 1255 | void |
1256 | symtab_make_decl_local (tree decl) | |
1257 | { | |
1258 | rtx rtl, symbol; | |
1259 | ||
8c016392 | 1260 | /* Avoid clearing comdat_groups on comdat-local decls. */ |
468088ac | 1261 | if (TREE_PUBLIC (decl) == 0) |
1262 | return; | |
1263 | ||
cf951b1a | 1264 | if (TREE_CODE (decl) == VAR_DECL) |
1265 | DECL_COMMON (decl) = 0; | |
1266 | else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | |
1267 | ||
71e19e54 | 1268 | DECL_COMDAT (decl) = 0; |
cf951b1a | 1269 | DECL_WEAK (decl) = 0; |
1270 | DECL_EXTERNAL (decl) = 0; | |
c9aa6453 | 1271 | DECL_VISIBILITY_SPECIFIED (decl) = 0; |
1272 | DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; | |
cf951b1a | 1273 | TREE_PUBLIC (decl) = 0; |
1274 | if (!DECL_RTL_SET_P (decl)) | |
1275 | return; | |
1276 | ||
1277 | /* Update rtl flags. */ | |
1278 | make_decl_rtl (decl); | |
1279 | ||
1280 | rtl = DECL_RTL (decl); | |
1281 | if (!MEM_P (rtl)) | |
1282 | return; | |
1283 | ||
1284 | symbol = XEXP (rtl, 0); | |
1285 | if (GET_CODE (symbol) != SYMBOL_REF) | |
1286 | return; | |
1287 | ||
1288 | SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl); | |
1289 | } | |
15ca8f90 | 1290 | |
48669653 | 1291 | /* Return availability of NODE. */ |
1292 | ||
1293 | enum availability | |
452659af | 1294 | symtab_node_availability (symtab_node *node) |
48669653 | 1295 | { |
13cbeaac | 1296 | if (is_a <cgraph_node *> (node)) |
48669653 | 1297 | return cgraph_function_body_availability (cgraph (node)); |
1298 | else | |
1299 | return cgraph_variable_initializer_availability (varpool (node)); | |
1300 | } | |
1301 | ||
15ca8f90 | 1302 | /* Given NODE, walk the alias chain to return the symbol NODE is alias of. |
1303 | If NODE is not an alias, return NODE. | |
1304 | When AVAILABILITY is non-NULL, get minimal availability in the chain. */ | |
1305 | ||
452659af | 1306 | symtab_node * |
1307 | symtab_alias_ultimate_target (symtab_node *node, enum availability *availability) | |
15ca8f90 | 1308 | { |
9817f2cd | 1309 | bool weakref_p = false; |
1310 | ||
02774f2d | 1311 | if (!node->alias) |
9817f2cd | 1312 | { |
1313 | if (availability) | |
1314 | *availability = symtab_node_availability (node); | |
1315 | return node; | |
1316 | } | |
1317 | ||
1318 | /* To determine visibility of the target, we follow ELF semantic of aliases. | |
1319 | Here alias is an alternative assembler name of a given definition. Its | |
75de4aa2 | 1320 | availability prevails the availability of its target (i.e. static alias of |
9817f2cd | 1321 | weak definition is available. |
1322 | ||
1323 | Weakref is a different animal (and not part of ELF per se). It is just | |
1324 | alternative name of a given symbol used within one complation unit | |
1325 | and is translated prior hitting the object file. It inherits the | |
1326 | visibility of its target (i.e. weakref of non-overwritable definition | |
1327 | is non-overwritable, while weakref of weak definition is weak). | |
1328 | ||
1329 | If we ever get into supporting targets with different semantics, a target | |
1330 | hook will be needed here. */ | |
1331 | ||
15ca8f90 | 1332 | if (availability) |
9817f2cd | 1333 | { |
02774f2d | 1334 | weakref_p = node->weakref; |
9817f2cd | 1335 | if (!weakref_p) |
1336 | *availability = symtab_node_availability (node); | |
1337 | else | |
1338 | *availability = AVAIL_LOCAL; | |
1339 | } | |
15ca8f90 | 1340 | while (node) |
1341 | { | |
02774f2d | 1342 | if (node->alias && node->analyzed) |
15ca8f90 | 1343 | node = symtab_alias_target (node); |
1344 | else | |
9817f2cd | 1345 | { |
1346 | if (!availability) | |
1347 | ; | |
02774f2d | 1348 | else if (node->analyzed) |
9817f2cd | 1349 | { |
1350 | if (weakref_p) | |
1351 | { | |
1352 | enum availability a = symtab_node_availability (node); | |
1353 | if (a < *availability) | |
1354 | *availability = a; | |
1355 | } | |
1356 | } | |
1357 | else | |
1358 | *availability = AVAIL_NOT_AVAILABLE; | |
1359 | return node; | |
1360 | } | |
1361 | if (node && availability && weakref_p) | |
15ca8f90 | 1362 | { |
48669653 | 1363 | enum availability a = symtab_node_availability (node); |
15ca8f90 | 1364 | if (a < *availability) |
1365 | *availability = a; | |
02774f2d | 1366 | weakref_p = node->weakref; |
15ca8f90 | 1367 | } |
1368 | } | |
1369 | if (availability) | |
1370 | *availability = AVAIL_NOT_AVAILABLE; | |
1371 | return NULL; | |
1372 | } | |
48669653 | 1373 | |
1374 | /* C++ FE sometimes change linkage flags after producing same body aliases. | |
1375 | ||
1376 | FIXME: C++ produce implicit aliases for virtual functions and vtables that | |
1377 | are obviously equivalent. The way it is doing so is however somewhat | |
1378 | kludgy and interferes with the visibility code. As a result we need to | |
1379 | copy the visibility from the target to get things right. */ | |
1380 | ||
1381 | void | |
452659af | 1382 | fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) |
48669653 | 1383 | { |
13cbeaac | 1384 | if (is_a <cgraph_node *> (node)) |
48669653 | 1385 | { |
02774f2d | 1386 | DECL_DECLARED_INLINE_P (node->decl) |
1387 | = DECL_DECLARED_INLINE_P (target->decl); | |
1388 | DECL_DISREGARD_INLINE_LIMITS (node->decl) | |
1389 | = DECL_DISREGARD_INLINE_LIMITS (target->decl); | |
48669653 | 1390 | } |
1391 | /* FIXME: It is not really clear why those flags should not be copied for | |
1392 | functions, too. */ | |
1393 | else | |
1394 | { | |
02774f2d | 1395 | DECL_WEAK (node->decl) = DECL_WEAK (target->decl); |
1396 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); | |
1397 | DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (target->decl); | |
48669653 | 1398 | } |
02774f2d | 1399 | DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl); |
1400 | if (TREE_PUBLIC (node->decl)) | |
48669653 | 1401 | { |
8c016392 | 1402 | tree group; |
1403 | ||
02774f2d | 1404 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); |
1405 | DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl); | |
8c016392 | 1406 | group = target->get_comdat_group (); |
1407 | node->set_comdat_group (group); | |
1408 | if (group | |
02774f2d | 1409 | && !node->same_comdat_group) |
1410 | symtab_add_to_same_comdat_group (node, target); | |
48669653 | 1411 | } |
02774f2d | 1412 | node->externally_visible = target->externally_visible; |
48669653 | 1413 | } |
1414 | ||
738a6bda | 1415 | /* Hash sections by their names. */ |
1416 | ||
1417 | static hashval_t | |
1418 | hash_section_hash_entry (const void *p) | |
1419 | { | |
1420 | const section_hash_entry *n = (const section_hash_entry *) p; | |
1421 | return htab_hash_string (n->name); | |
1422 | } | |
1423 | ||
1424 | /* Return true if section P1 name equals to P2. */ | |
1425 | ||
1426 | static int | |
1427 | eq_sections (const void *p1, const void *p2) | |
1428 | { | |
1429 | const section_hash_entry *n1 = (const section_hash_entry *) p1; | |
1430 | const char *name = (const char *)p2; | |
1431 | return n1->name == name || !strcmp (n1->name, name); | |
1432 | } | |
1433 | ||
1434 | /* Set section, do not recurse into aliases. | |
1435 | When one wants to change section of symbol and its aliases, | |
1436 | use set_section */ | |
1437 | ||
1438 | void | |
1439 | symtab_node::set_section_for_node (const char *section) | |
1440 | { | |
1441 | const char *current = get_section (); | |
1442 | void **slot; | |
1443 | ||
1444 | if (current == section | |
1445 | || (current && section | |
1446 | && !strcmp (current, section))) | |
1447 | return; | |
1448 | ||
1449 | if (current) | |
1450 | { | |
1451 | x_section->ref_count--; | |
1452 | if (!x_section->ref_count) | |
1453 | { | |
1454 | slot = htab_find_slot_with_hash (section_hash, x_section->name, | |
1455 | htab_hash_string (x_section->name), | |
1456 | INSERT); | |
1457 | ggc_free (x_section); | |
1458 | htab_clear_slot (section_hash, slot); | |
1459 | } | |
1460 | x_section = NULL; | |
1461 | } | |
1462 | if (!section) | |
1463 | { | |
1464 | implicit_section = false; | |
1465 | return; | |
1466 | } | |
1467 | if (!section_hash) | |
1468 | section_hash = htab_create_ggc (10, hash_section_hash_entry, | |
1469 | eq_sections, NULL); | |
1470 | slot = htab_find_slot_with_hash (section_hash, section, | |
1471 | htab_hash_string (section), | |
1472 | INSERT); | |
1473 | if (*slot) | |
1474 | x_section = (section_hash_entry *)*slot; | |
1475 | else | |
1476 | { | |
1477 | int len = strlen (section); | |
1478 | *slot = x_section = ggc_cleared_alloc<section_hash_entry> (); | |
1479 | x_section->name = ggc_vec_alloc<char> (len + 1); | |
1480 | memcpy (x_section->name, section, len + 1); | |
1481 | } | |
1482 | x_section->ref_count++; | |
1483 | } | |
1484 | ||
e4c07a06 | 1485 | /* Worker for set_section. */ |
1486 | ||
1487 | static bool | |
1488 | set_section_1 (struct symtab_node *n, void *s) | |
1489 | { | |
738a6bda | 1490 | n->set_section_for_node ((char *)s); |
e4c07a06 | 1491 | return false; |
1492 | } | |
1493 | ||
1494 | /* Set section of symbol and its aliases. */ | |
1495 | ||
1496 | void | |
738a6bda | 1497 | symtab_node::set_section (const char *section) |
e4c07a06 | 1498 | { |
1499 | gcc_assert (!this->alias); | |
738a6bda | 1500 | symtab_for_node_and_aliases (this, set_section_1, const_cast<char *>(section), true); |
e4c07a06 | 1501 | } |
1502 | ||
9db80d42 | 1503 | /* Return the initialization priority. */ |
1504 | ||
1505 | priority_type | |
1506 | symtab_node::get_init_priority () | |
1507 | { | |
1508 | struct symbol_priority_map *h; | |
1509 | struct symbol_priority_map in; | |
1510 | ||
1511 | if (!this->in_init_priority_hash) | |
1512 | return DEFAULT_INIT_PRIORITY; | |
1513 | in.symbol = this; | |
1514 | h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); | |
1515 | return h ? h->init : DEFAULT_INIT_PRIORITY; | |
1516 | } | |
1517 | ||
1518 | /* Return the finalization priority. */ | |
1519 | ||
1520 | priority_type | |
1521 | cgraph_node::get_fini_priority () | |
1522 | { | |
1523 | struct symbol_priority_map *h; | |
1524 | struct symbol_priority_map in; | |
1525 | ||
1526 | if (!this->in_init_priority_hash) | |
1527 | return DEFAULT_INIT_PRIORITY; | |
1528 | in.symbol = this; | |
1529 | h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); | |
1530 | return h ? h->fini : DEFAULT_INIT_PRIORITY; | |
1531 | } | |
1532 | ||
1533 | /* Return true if the from tree in both priority maps are equal. */ | |
1534 | ||
1535 | int | |
1536 | symbol_priority_map_eq (const void *va, const void *vb) | |
1537 | { | |
1538 | const struct symbol_priority_map *const a = (const struct symbol_priority_map *) va, | |
1539 | *const b = (const struct symbol_priority_map *) vb; | |
1540 | return (a->symbol == b->symbol); | |
1541 | } | |
1542 | ||
1543 | /* Hash a from symbol in a symbol_priority_map. */ | |
1544 | ||
1545 | unsigned int | |
1546 | symbol_priority_map_hash (const void *item) | |
1547 | { | |
1548 | return htab_hash_pointer (((const struct symbol_priority_map *)item)->symbol); | |
1549 | } | |
1550 | ||
1551 | /* Return the initialization and finalization priority information for | |
1552 | DECL. If there is no previous priority information, a freshly | |
1553 | allocated structure is returned. */ | |
1554 | ||
1555 | static struct symbol_priority_map * | |
1556 | symbol_priority_info (struct symtab_node *symbol) | |
1557 | { | |
1558 | struct symbol_priority_map in; | |
1559 | struct symbol_priority_map *h; | |
1560 | void **loc; | |
1561 | ||
1562 | in.symbol = symbol; | |
1563 | if (!init_priority_hash) | |
1564 | init_priority_hash = htab_create_ggc (512, symbol_priority_map_hash, | |
1565 | symbol_priority_map_eq, 0); | |
1566 | ||
1567 | loc = htab_find_slot (init_priority_hash, &in, INSERT); | |
1568 | h = (struct symbol_priority_map *) *loc; | |
1569 | if (!h) | |
1570 | { | |
1571 | h = ggc_cleared_alloc<symbol_priority_map> (); | |
1572 | *loc = h; | |
1573 | h->symbol = symbol; | |
1574 | h->init = DEFAULT_INIT_PRIORITY; | |
1575 | h->fini = DEFAULT_INIT_PRIORITY; | |
1576 | symbol->in_init_priority_hash = true; | |
1577 | } | |
1578 | ||
1579 | return h; | |
1580 | } | |
1581 | ||
1582 | /* Set initialization priority to PRIORITY. */ | |
1583 | ||
1584 | void | |
1585 | symtab_node::set_init_priority (priority_type priority) | |
1586 | { | |
1587 | struct symbol_priority_map *h; | |
1588 | ||
1589 | if (is_a <cgraph_node *> (this)) | |
1590 | gcc_assert (DECL_STATIC_CONSTRUCTOR (this->decl)); | |
1591 | ||
1592 | if (priority == DEFAULT_INIT_PRIORITY) | |
1593 | { | |
1594 | gcc_assert (get_init_priority() == priority); | |
1595 | return; | |
1596 | } | |
1597 | h = symbol_priority_info (this); | |
1598 | h->init = priority; | |
1599 | } | |
1600 | ||
1601 | /* Set fialization priority to PRIORITY. */ | |
1602 | ||
1603 | void | |
1604 | cgraph_node::set_fini_priority (priority_type priority) | |
1605 | { | |
1606 | struct symbol_priority_map *h; | |
1607 | ||
1608 | gcc_assert (DECL_STATIC_DESTRUCTOR (this->decl)); | |
1609 | ||
1610 | if (priority == DEFAULT_INIT_PRIORITY) | |
1611 | { | |
1612 | gcc_assert (get_fini_priority() == priority); | |
1613 | return; | |
1614 | } | |
1615 | h = symbol_priority_info (this); | |
1616 | h->fini = priority; | |
1617 | } | |
1618 | ||
e4c07a06 | 1619 | /* Worker for symtab_resolve_alias. */ |
1620 | ||
1621 | static bool | |
1622 | set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED) | |
1623 | { | |
1624 | n->implicit_section = true; | |
1625 | return false; | |
1626 | } | |
1627 | ||
48669653 | 1628 | /* Add reference recording that NODE is alias of TARGET. |
1629 | The function can fail in the case of aliasing cycles; in this case | |
1630 | it returns false. */ | |
1631 | ||
1632 | bool | |
452659af | 1633 | symtab_resolve_alias (symtab_node *node, symtab_node *target) |
48669653 | 1634 | { |
452659af | 1635 | symtab_node *n; |
48669653 | 1636 | |
02774f2d | 1637 | gcc_assert (!node->analyzed |
1638 | && !vec_safe_length (node->ref_list.references)); | |
48669653 | 1639 | |
1640 | /* Never let cycles to creep into the symbol table alias references; | |
1641 | those will make alias walkers to be infinite. */ | |
02774f2d | 1642 | for (n = target; n && n->alias; |
1643 | n = n->analyzed ? symtab_alias_target (n) : NULL) | |
48669653 | 1644 | if (n == node) |
1645 | { | |
13cbeaac | 1646 | if (is_a <cgraph_node *> (node)) |
02774f2d | 1647 | error ("function %q+D part of alias cycle", node->decl); |
13cbeaac | 1648 | else if (is_a <varpool_node *> (node)) |
02774f2d | 1649 | error ("variable %q+D part of alias cycle", node->decl); |
48669653 | 1650 | else |
1651 | gcc_unreachable (); | |
02774f2d | 1652 | node->alias = false; |
48669653 | 1653 | return false; |
1654 | } | |
1655 | ||
1656 | /* "analyze" the node - i.e. mark the reference. */ | |
02774f2d | 1657 | node->definition = true; |
1658 | node->alias = true; | |
1659 | node->analyzed = true; | |
51ce5652 | 1660 | node->add_reference (target, IPA_REF_ALIAS, NULL); |
48669653 | 1661 | |
e4c07a06 | 1662 | /* Add alias into the comdat group of its target unless it is already there. */ |
1663 | if (node->same_comdat_group) | |
1664 | symtab_remove_from_same_comdat_group (node); | |
1665 | node->set_comdat_group (NULL); | |
1666 | if (target->get_comdat_group ()) | |
1667 | symtab_add_to_same_comdat_group (node, target); | |
1668 | ||
1669 | if ((node->get_section () != target->get_section () | |
1670 | || target->get_comdat_group ()) | |
1671 | && node->get_section () && !node->implicit_section) | |
1672 | { | |
1673 | error ("section of alias %q+D must match section of its target", | |
1674 | node->decl); | |
1675 | } | |
738a6bda | 1676 | symtab_for_node_and_aliases (node, set_section_1, |
1677 | const_cast<char *>(target->get_section ()), true); | |
e4c07a06 | 1678 | if (target->implicit_section) |
1679 | symtab_for_node_and_aliases (node, | |
1680 | set_implicit_section, NULL, true); | |
1681 | ||
1d9ca4f0 | 1682 | /* Alias targets become redundant after alias is resolved into an reference. |
48669653 | 1683 | We do not want to keep it around or we would have to mind updating them |
1684 | when renaming symbols. */ | |
02774f2d | 1685 | node->alias_target = NULL; |
48669653 | 1686 | |
02774f2d | 1687 | if (node->cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) |
48669653 | 1688 | fixup_same_cpp_alias_visibility (node, target); |
1689 | ||
1690 | /* If alias has address taken, so does the target. */ | |
02774f2d | 1691 | if (node->address_taken) |
1692 | symtab_alias_ultimate_target (target, NULL)->address_taken = true; | |
48669653 | 1693 | return true; |
1694 | } | |
44e82502 | 1695 | |
1696 | /* Call calback on NODE and aliases associated to NODE. | |
1697 | When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are | |
1698 | skipped. */ | |
1699 | ||
1700 | bool | |
452659af | 1701 | symtab_for_node_and_aliases (symtab_node *node, |
1702 | bool (*callback) (symtab_node *, void *), | |
44e82502 | 1703 | void *data, |
1704 | bool include_overwritable) | |
1705 | { | |
1706 | int i; | |
1707 | struct ipa_ref *ref; | |
1708 | ||
1709 | if (callback (node, data)) | |
1710 | return true; | |
51ce5652 | 1711 | for (i = 0; node->iterate_referring (i, ref); i++) |
44e82502 | 1712 | if (ref->use == IPA_REF_ALIAS) |
1713 | { | |
452659af | 1714 | symtab_node *alias = ref->referring; |
44e82502 | 1715 | if (include_overwritable |
1716 | || symtab_node_availability (alias) > AVAIL_OVERWRITABLE) | |
1717 | if (symtab_for_node_and_aliases (alias, callback, data, | |
1718 | include_overwritable)) | |
1719 | return true; | |
1720 | } | |
1721 | return false; | |
1722 | } | |
1723 | ||
1724 | /* Worker searching nonoverwritable alias. */ | |
1725 | ||
1726 | static bool | |
452659af | 1727 | symtab_nonoverwritable_alias_1 (symtab_node *node, void *data) |
44e82502 | 1728 | { |
02774f2d | 1729 | if (decl_binds_to_current_def_p (node->decl)) |
44e82502 | 1730 | { |
c16b9430 | 1731 | symtab_node *fn = symtab_alias_ultimate_target (node); |
1732 | ||
1733 | /* Ensure that the alias is well formed this may not be the case | |
1734 | of user defined aliases and currently it is not always the case | |
1735 | of C++ same body aliases (that is a bug). */ | |
1736 | if (TREE_TYPE (node->decl) != TREE_TYPE (fn->decl) | |
1737 | || DECL_CONTEXT (node->decl) != DECL_CONTEXT (fn->decl) | |
1738 | || (TREE_CODE (node->decl) == FUNCTION_DECL | |
1739 | && flags_from_decl_or_type (node->decl) | |
1740 | != flags_from_decl_or_type (fn->decl)) | |
1741 | || DECL_ATTRIBUTES (node->decl) != DECL_ATTRIBUTES (fn->decl)) | |
1742 | return false; | |
1743 | ||
452659af | 1744 | *(symtab_node **)data = node; |
44e82502 | 1745 | return true; |
1746 | } | |
1747 | return false; | |
1748 | } | |
1749 | ||
1750 | /* If NODE can not be overwriten by static or dynamic linker to point to different | |
1751 | definition, return NODE. Otherwise look for alias with such property and if | |
1752 | none exists, introduce new one. */ | |
1753 | ||
452659af | 1754 | symtab_node * |
1755 | symtab_nonoverwritable_alias (symtab_node *node) | |
44e82502 | 1756 | { |
1757 | tree new_decl; | |
452659af | 1758 | symtab_node *new_node = NULL; |
2fe870c5 | 1759 | |
1760 | /* First try to look up existing alias or base object | |
1761 | (if that is already non-overwritable). */ | |
1762 | node = symtab_alias_ultimate_target (node, NULL); | |
02774f2d | 1763 | gcc_assert (!node->alias && !node->weakref); |
44e82502 | 1764 | symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, |
1765 | (void *)&new_node, true); | |
1766 | if (new_node) | |
1767 | return new_node; | |
cb064935 | 1768 | #ifndef ASM_OUTPUT_DEF |
1769 | /* If aliases aren't supported by the assembler, fail. */ | |
1770 | return NULL; | |
1771 | #endif | |
44e82502 | 1772 | |
2fe870c5 | 1773 | /* Otherwise create a new one. */ |
02774f2d | 1774 | new_decl = copy_node (node->decl); |
1775 | DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias"); | |
44e82502 | 1776 | if (TREE_CODE (new_decl) == FUNCTION_DECL) |
1777 | DECL_STRUCT_FUNCTION (new_decl) = NULL; | |
1778 | DECL_INITIAL (new_decl) = NULL; | |
1779 | SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | |
1780 | SET_DECL_RTL (new_decl, NULL); | |
1781 | ||
1782 | /* Update the properties. */ | |
1783 | DECL_EXTERNAL (new_decl) = 0; | |
44e82502 | 1784 | TREE_PUBLIC (new_decl) = 0; |
1785 | DECL_COMDAT (new_decl) = 0; | |
1786 | DECL_WEAK (new_decl) = 0; | |
338af93e | 1787 | |
1788 | /* Since the aliases can be added to vtables, keep DECL_VIRTUAL flag. */ | |
1789 | DECL_VIRTUAL_P (new_decl) = DECL_VIRTUAL_P (node->decl); | |
44e82502 | 1790 | if (TREE_CODE (new_decl) == FUNCTION_DECL) |
1791 | { | |
1792 | DECL_STATIC_CONSTRUCTOR (new_decl) = 0; | |
1793 | DECL_STATIC_DESTRUCTOR (new_decl) = 0; | |
02774f2d | 1794 | new_node = cgraph_create_function_alias |
1795 | (new_decl, node->decl); | |
44e82502 | 1796 | } |
1797 | else | |
19b03318 | 1798 | { |
1799 | TREE_READONLY (new_decl) = TREE_READONLY (node->decl); | |
338af93e | 1800 | DECL_INITIAL (new_decl) = error_mark_node; |
19b03318 | 1801 | new_node = varpool_create_variable_alias (new_decl, node->decl); |
1802 | } | |
44e82502 | 1803 | symtab_resolve_alias (new_node, node); |
19b03318 | 1804 | gcc_assert (decl_binds_to_current_def_p (new_decl) |
1805 | && targetm.binds_local_p (new_decl)); | |
44e82502 | 1806 | return new_node; |
1807 | } | |
e9de52cc | 1808 | |
1809 | /* Return true if A and B represents semantically equivalent symbols. */ | |
1810 | ||
1811 | bool | |
452659af | 1812 | symtab_semantically_equivalent_p (symtab_node *a, |
1813 | symtab_node *b) | |
e9de52cc | 1814 | { |
1815 | enum availability avail; | |
452659af | 1816 | symtab_node *ba; |
1817 | symtab_node *bb; | |
e9de52cc | 1818 | |
1819 | /* Equivalent functions are equivalent. */ | |
02774f2d | 1820 | if (a->decl == b->decl) |
e9de52cc | 1821 | return true; |
1822 | ||
1823 | /* If symbol is not overwritable by different implementation, | |
1824 | walk to the base object it defines. */ | |
1825 | ba = symtab_alias_ultimate_target (a, &avail); | |
1826 | if (avail >= AVAIL_AVAILABLE) | |
1827 | { | |
1828 | if (ba == b) | |
1829 | return true; | |
1830 | } | |
1831 | else | |
1832 | ba = a; | |
1833 | bb = symtab_alias_ultimate_target (b, &avail); | |
1834 | if (avail >= AVAIL_AVAILABLE) | |
1835 | { | |
1836 | if (a == bb) | |
1837 | return true; | |
1838 | } | |
1839 | else | |
1840 | bb = b; | |
1841 | return bb == ba; | |
1842 | } | |
2b7cb172 | 1843 | |
1844 | /* Classify symbol NODE for partitioning. */ | |
1845 | ||
1846 | enum symbol_partitioning_class | |
1847 | symtab_get_symbol_partitioning_class (symtab_node *node) | |
1848 | { | |
1849 | /* Inline clones are always duplicated. | |
1850 | This include external delcarations. */ | |
13cbeaac | 1851 | cgraph_node *cnode = dyn_cast <cgraph_node *> (node); |
2b7cb172 | 1852 | |
1853 | if (DECL_ABSTRACT (node->decl)) | |
1854 | return SYMBOL_EXTERNAL; | |
1855 | ||
1856 | if (cnode && cnode->global.inlined_to) | |
1857 | return SYMBOL_DUPLICATE; | |
1858 | ||
1859 | /* Weakref aliases are always duplicated. */ | |
1860 | if (node->weakref) | |
1861 | return SYMBOL_DUPLICATE; | |
1862 | ||
1863 | /* External declarations are external. */ | |
1864 | if (DECL_EXTERNAL (node->decl)) | |
1865 | return SYMBOL_EXTERNAL; | |
1866 | ||
13cbeaac | 1867 | if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
2b7cb172 | 1868 | { |
1869 | /* Constant pool references use local symbol names that can not | |
1870 | be promoted global. We should never put into a constant pool | |
1871 | objects that can not be duplicated across partitions. */ | |
1872 | if (DECL_IN_CONSTANT_POOL (node->decl)) | |
1873 | return SYMBOL_DUPLICATE; | |
1874 | gcc_checking_assert (vnode->definition); | |
1875 | } | |
1876 | /* Functions that are cloned may stay in callgraph even if they are unused. | |
1877 | Handle them as external; compute_ltrans_boundary take care to make | |
1878 | proper things to happen (i.e. to make them appear in the boundary but | |
1879 | with body streamed, so clone can me materialized). */ | |
1880 | else if (!cgraph (node)->definition) | |
1881 | return SYMBOL_EXTERNAL; | |
1882 | ||
1883 | /* Linker discardable symbols are duplicated to every use unless they are | |
b395f451 | 1884 | keyed. */ |
2b7cb172 | 1885 | if (DECL_ONE_ONLY (node->decl) |
1886 | && !node->force_output | |
1887 | && !node->forced_by_abi | |
1888 | && !symtab_used_from_object_file_p (node)) | |
1889 | return SYMBOL_DUPLICATE; | |
1890 | ||
1891 | return SYMBOL_PARTITION; | |
1892 | } | |
cfbe30aa | 1893 | #include "gt-symtab.h" |