]>
Commit | Line | Data |
---|---|---|
2aae7680 | 1 | /* Symbol table. |
23a5b65a | 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. |
2aae7680 JH |
3 | Contributed by Jan Hubicka |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
d8a2d370 | 25 | #include "rtl.h" |
2aae7680 | 26 | #include "tree.h" |
d8a2d370 DN |
27 | #include "print-tree.h" |
28 | #include "varasm.h" | |
29 | #include "function.h" | |
30 | #include "emit-rtl.h" | |
2fb9a547 AM |
31 | #include "basic-block.h" |
32 | #include "tree-ssa-alias.h" | |
33 | #include "internal-fn.h" | |
34 | #include "gimple-expr.h" | |
35 | #include "is-a.h" | |
8e9055ae | 36 | #include "gimple.h" |
2aae7680 | 37 | #include "tree-inline.h" |
8f940ee6 | 38 | #include "langhooks.h" |
2aae7680 JH |
39 | #include "hashtab.h" |
40 | #include "cgraph.h" | |
1ab24192 | 41 | #include "diagnostic.h" |
474ffc72 | 42 | #include "timevar.h" |
65d630d4 | 43 | #include "lto-streamer.h" |
862d0b35 | 44 | #include "output.h" |
65d630d4 JH |
45 | |
46 | const char * const ld_plugin_symbol_resolution_names[]= | |
47 | { | |
48 | "", | |
49 | "undef", | |
50 | "prevailing_def", | |
51 | "prevailing_def_ironly", | |
52 | "preempted_reg", | |
53 | "preempted_ir", | |
54 | "resolved_ir", | |
55 | "resolved_exec", | |
56 | "resolved_dyn", | |
57 | "prevailing_def_ironly_exp" | |
58 | }; | |
1ab24192 | 59 | |
f961457f JH |
60 | |
61 | /* Hash table used to hold sectoons. */ | |
62 | static GTY((param_is (section_hash_entry))) htab_t section_hash; | |
63 | ||
1ab24192 | 64 | /* Hash table used to convert assembler names into nodes. */ |
5e20cdc9 | 65 | static GTY((param_is (symtab_node))) htab_t assembler_name_hash; |
2aae7680 | 66 | |
569b1784 JH |
67 | /* Map from a symbol to initialization/finalization priorities. */ |
68 | struct GTY(()) symbol_priority_map { | |
69 | symtab_node *symbol; | |
70 | priority_type init; | |
71 | priority_type fini; | |
72 | }; | |
73 | ||
74 | /* Hash table used to hold init priorities. */ | |
75 | static GTY ((param_is (struct symbol_priority_map))) | |
76 | htab_t init_priority_hash; | |
77 | ||
2aae7680 | 78 | /* Linked list of symbol table nodes. */ |
5e20cdc9 | 79 | symtab_node *symtab_nodes; |
2aae7680 JH |
80 | |
81 | /* The order index of the next symtab node to be created. This is | |
82 | used so that we can sort the cgraph nodes in order by when we saw | |
83 | them, to support -fno-toplevel-reorder. */ | |
84 | int symtab_order; | |
85 | ||
862d0b35 DN |
86 | /* Hash asmnames ignoring the user specified marks. */ |
87 | ||
88 | static hashval_t | |
89 | decl_assembler_name_hash (const_tree asmname) | |
90 | { | |
91 | if (IDENTIFIER_POINTER (asmname)[0] == '*') | |
92 | { | |
93 | const char *decl_str = IDENTIFIER_POINTER (asmname) + 1; | |
94 | size_t ulp_len = strlen (user_label_prefix); | |
95 | ||
96 | if (ulp_len == 0) | |
97 | ; | |
98 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
99 | decl_str += ulp_len; | |
100 | ||
101 | return htab_hash_string (decl_str); | |
102 | } | |
103 | ||
104 | return htab_hash_string (IDENTIFIER_POINTER (asmname)); | |
105 | } | |
106 | ||
107 | ||
1ab24192 JH |
108 | /* Returns a hash code for P. */ |
109 | ||
110 | static hashval_t | |
111 | hash_node_by_assembler_name (const void *p) | |
112 | { | |
5e20cdc9 | 113 | const symtab_node *n = (const symtab_node *) p; |
67348ccc | 114 | return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl)); |
1ab24192 JH |
115 | } |
116 | ||
862d0b35 DN |
117 | /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */ |
118 | ||
119 | static bool | |
120 | decl_assembler_name_equal (tree decl, const_tree asmname) | |
121 | { | |
122 | tree decl_asmname = DECL_ASSEMBLER_NAME (decl); | |
123 | const char *decl_str; | |
124 | const char *asmname_str; | |
125 | bool test = false; | |
126 | ||
127 | if (decl_asmname == asmname) | |
128 | return true; | |
129 | ||
130 | decl_str = IDENTIFIER_POINTER (decl_asmname); | |
131 | asmname_str = IDENTIFIER_POINTER (asmname); | |
132 | ||
133 | ||
134 | /* If the target assembler name was set by the user, things are trickier. | |
135 | We have a leading '*' to begin with. After that, it's arguable what | |
136 | is the correct thing to do with -fleading-underscore. Arguably, we've | |
137 | historically been doing the wrong thing in assemble_alias by always | |
138 | printing the leading underscore. Since we're not changing that, make | |
139 | sure user_label_prefix follows the '*' before matching. */ | |
140 | if (decl_str[0] == '*') | |
141 | { | |
142 | size_t ulp_len = strlen (user_label_prefix); | |
143 | ||
144 | decl_str ++; | |
145 | ||
146 | if (ulp_len == 0) | |
147 | test = true; | |
148 | else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0) | |
149 | decl_str += ulp_len, test=true; | |
150 | else | |
151 | decl_str --; | |
152 | } | |
153 | if (asmname_str[0] == '*') | |
154 | { | |
155 | size_t ulp_len = strlen (user_label_prefix); | |
156 | ||
157 | asmname_str ++; | |
158 | ||
159 | if (ulp_len == 0) | |
160 | test = true; | |
161 | else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0) | |
162 | asmname_str += ulp_len, test=true; | |
163 | else | |
164 | asmname_str --; | |
165 | } | |
166 | ||
167 | if (!test) | |
168 | return false; | |
169 | return strcmp (decl_str, asmname_str) == 0; | |
170 | } | |
171 | ||
172 | ||
1ab24192 JH |
173 | /* Returns nonzero if P1 and P2 are equal. */ |
174 | ||
175 | static int | |
176 | eq_assembler_name (const void *p1, const void *p2) | |
177 | { | |
5e20cdc9 | 178 | const symtab_node *n1 = (const symtab_node *) p1; |
1ab24192 | 179 | const_tree name = (const_tree)p2; |
67348ccc | 180 | return (decl_assembler_name_equal (n1->decl, name)); |
1ab24192 JH |
181 | } |
182 | ||
183 | /* Insert NODE to assembler name hash. */ | |
184 | ||
185 | static void | |
5e20cdc9 | 186 | insert_to_assembler_name_hash (symtab_node *node, bool with_clones) |
1ab24192 | 187 | { |
7de90a6c | 188 | if (is_a <varpool_node *> (node) && DECL_HARD_REGISTER (node->decl)) |
b5493fb2 | 189 | return; |
67348ccc DM |
190 | gcc_checking_assert (!node->previous_sharing_asm_name |
191 | && !node->next_sharing_asm_name); | |
1ab24192 JH |
192 | if (assembler_name_hash) |
193 | { | |
194 | void **aslot; | |
c3167b00 | 195 | struct cgraph_node *cnode; |
67348ccc | 196 | tree decl = node->decl; |
c3167b00 | 197 | |
67348ccc | 198 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
1ab24192 JH |
199 | |
200 | aslot = htab_find_slot_with_hash (assembler_name_hash, name, | |
201 | decl_assembler_name_hash (name), | |
202 | INSERT); | |
203 | gcc_assert (*aslot != node); | |
5e20cdc9 | 204 | node->next_sharing_asm_name = (symtab_node *)*aslot; |
1ab24192 | 205 | if (*aslot != NULL) |
5e20cdc9 | 206 | ((symtab_node *)*aslot)->previous_sharing_asm_name = node; |
1ab24192 | 207 | *aslot = node; |
c3167b00 JH |
208 | |
209 | /* Update also possible inline clones sharing a decl. */ | |
7de90a6c | 210 | cnode = dyn_cast <cgraph_node *> (node); |
c3167b00 JH |
211 | if (cnode && cnode->clones && with_clones) |
212 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
67348ccc DM |
213 | if (cnode->decl == decl) |
214 | insert_to_assembler_name_hash (cnode, true); | |
1ab24192 JH |
215 | } |
216 | ||
217 | } | |
218 | ||
219 | /* Remove NODE from assembler name hash. */ | |
220 | ||
221 | static void | |
5e20cdc9 | 222 | unlink_from_assembler_name_hash (symtab_node *node, bool with_clones) |
1ab24192 JH |
223 | { |
224 | if (assembler_name_hash) | |
225 | { | |
c3167b00 | 226 | struct cgraph_node *cnode; |
67348ccc | 227 | tree decl = node->decl; |
c3167b00 | 228 | |
67348ccc DM |
229 | if (node->next_sharing_asm_name) |
230 | node->next_sharing_asm_name->previous_sharing_asm_name | |
231 | = node->previous_sharing_asm_name; | |
232 | if (node->previous_sharing_asm_name) | |
1ab24192 | 233 | { |
67348ccc DM |
234 | node->previous_sharing_asm_name->next_sharing_asm_name |
235 | = node->next_sharing_asm_name; | |
1ab24192 JH |
236 | } |
237 | else | |
238 | { | |
67348ccc | 239 | tree name = DECL_ASSEMBLER_NAME (node->decl); |
1ab24192 JH |
240 | void **slot; |
241 | slot = htab_find_slot_with_hash (assembler_name_hash, name, | |
242 | decl_assembler_name_hash (name), | |
243 | NO_INSERT); | |
244 | gcc_assert (*slot == node); | |
67348ccc | 245 | if (!node->next_sharing_asm_name) |
1ab24192 JH |
246 | htab_clear_slot (assembler_name_hash, slot); |
247 | else | |
67348ccc | 248 | *slot = node->next_sharing_asm_name; |
1ab24192 | 249 | } |
67348ccc DM |
250 | node->next_sharing_asm_name = NULL; |
251 | node->previous_sharing_asm_name = NULL; | |
c3167b00 JH |
252 | |
253 | /* Update also possible inline clones sharing a decl. */ | |
7de90a6c | 254 | cnode = dyn_cast <cgraph_node *> (node); |
c3167b00 JH |
255 | if (cnode && cnode->clones && with_clones) |
256 | for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) | |
67348ccc DM |
257 | if (cnode->decl == decl) |
258 | unlink_from_assembler_name_hash (cnode, true); | |
1ab24192 JH |
259 | } |
260 | } | |
261 | ||
b5493fb2 JH |
262 | /* Arrange node to be first in its entry of assembler_name_hash. */ |
263 | ||
264 | void | |
5e20cdc9 | 265 | symtab_prevail_in_asm_name_hash (symtab_node *node) |
b5493fb2 | 266 | { |
c3167b00 JH |
267 | unlink_from_assembler_name_hash (node, false); |
268 | insert_to_assembler_name_hash (node, false); | |
b5493fb2 JH |
269 | } |
270 | ||
1ab24192 | 271 | |
2aae7680 JH |
272 | /* Add node into symbol table. This function is not used directly, but via |
273 | cgraph/varpool node creation routines. */ | |
274 | ||
275 | void | |
5e20cdc9 | 276 | symtab_register_node (symtab_node *node) |
2aae7680 | 277 | { |
67348ccc DM |
278 | node->next = symtab_nodes; |
279 | node->previous = NULL; | |
2aae7680 | 280 | if (symtab_nodes) |
67348ccc | 281 | symtab_nodes->previous = node; |
2aae7680 JH |
282 | symtab_nodes = node; |
283 | ||
aede2c10 JH |
284 | if (!node->decl->decl_with_vis.symtab_node) |
285 | node->decl->decl_with_vis.symtab_node = node; | |
1ab24192 | 286 | |
67348ccc | 287 | ipa_empty_ref_list (&node->ref_list); |
1ab24192 | 288 | |
67348ccc | 289 | node->order = symtab_order++; |
2aae7680 | 290 | |
66379195 JH |
291 | /* Be sure to do this last; C++ FE might create new nodes via |
292 | DECL_ASSEMBLER_NAME langhook! */ | |
c3167b00 | 293 | insert_to_assembler_name_hash (node, false); |
2aae7680 JH |
294 | } |
295 | ||
7b3376a0 | 296 | /* Remove NODE from same comdat group. */ |
2aae7680 JH |
297 | |
298 | void | |
7b3376a0 | 299 | symtab_remove_from_same_comdat_group (symtab_node *node) |
2aae7680 | 300 | { |
67348ccc | 301 | if (node->same_comdat_group) |
2aae7680 | 302 | { |
5e20cdc9 | 303 | symtab_node *prev; |
67348ccc DM |
304 | for (prev = node->same_comdat_group; |
305 | prev->same_comdat_group != node; | |
306 | prev = prev->same_comdat_group) | |
2aae7680 | 307 | ; |
67348ccc DM |
308 | if (node->same_comdat_group == prev) |
309 | prev->same_comdat_group = NULL; | |
2aae7680 | 310 | else |
67348ccc DM |
311 | prev->same_comdat_group = node->same_comdat_group; |
312 | node->same_comdat_group = NULL; | |
2aae7680 | 313 | } |
7b3376a0 JH |
314 | } |
315 | ||
316 | /* Remove node from symbol table. This function is not used directly, but via | |
317 | cgraph/varpool node removal routines. */ | |
318 | ||
319 | void | |
320 | symtab_unregister_node (symtab_node *node) | |
321 | { | |
7b3376a0 JH |
322 | ipa_remove_all_references (&node->ref_list); |
323 | ipa_remove_all_referring (&node->ref_list); | |
324 | ||
f961457f JH |
325 | /* Remove reference to section. */ |
326 | node->set_section_for_node (NULL); | |
327 | ||
7b3376a0 | 328 | symtab_remove_from_same_comdat_group (node); |
2aae7680 | 329 | |
67348ccc DM |
330 | if (node->previous) |
331 | node->previous->next = node->next; | |
2aae7680 | 332 | else |
67348ccc DM |
333 | symtab_nodes = node->next; |
334 | if (node->next) | |
335 | node->next->previous = node->previous; | |
336 | node->next = NULL; | |
337 | node->previous = NULL; | |
1ab24192 | 338 | |
bbf9ad07 JH |
339 | /* During LTO symtab merging we temporarily corrupt decl to symtab node |
340 | hash. */ | |
aede2c10 JH |
341 | gcc_assert (node->decl->decl_with_vis.symtab_node || in_lto_p); |
342 | if (node->decl->decl_with_vis.symtab_node == node) | |
1ab24192 | 343 | { |
5e20cdc9 | 344 | symtab_node *replacement_node = NULL; |
7de90a6c | 345 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
67348ccc | 346 | replacement_node = cgraph_find_replacement_node (cnode); |
aede2c10 | 347 | node->decl->decl_with_vis.symtab_node = replacement_node; |
1ab24192 | 348 | } |
7de90a6c | 349 | if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl)) |
8e4c9a10 | 350 | unlink_from_assembler_name_hash (node, false); |
569b1784 JH |
351 | if (node->in_init_priority_hash) |
352 | { | |
353 | struct symbol_priority_map in; | |
354 | void **slot; | |
355 | in.symbol = node; | |
356 | ||
357 | slot = htab_find_slot (init_priority_hash, &in, NO_INSERT); | |
358 | if (slot) | |
359 | htab_clear_slot (init_priority_hash, slot); | |
360 | } | |
1ab24192 JH |
361 | } |
362 | ||
2aae7680 JH |
363 | |
364 | /* Remove symtab NODE from the symbol table. */ | |
365 | ||
366 | void | |
5e20cdc9 | 367 | symtab_remove_node (symtab_node *node) |
2aae7680 | 368 | { |
7de90a6c | 369 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
5d59b5e1 | 370 | cgraph_remove_node (cnode); |
7de90a6c | 371 | else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
5d59b5e1 | 372 | varpool_remove_node (vnode); |
2aae7680 | 373 | } |
1ab24192 | 374 | |
b5493fb2 | 375 | /* Initalize asm name hash unless. */ |
1ab24192 | 376 | |
b5493fb2 JH |
377 | void |
378 | symtab_initialize_asm_name_hash (void) | |
1ab24192 | 379 | { |
5e20cdc9 | 380 | symtab_node *node; |
1ab24192 JH |
381 | if (!assembler_name_hash) |
382 | { | |
383 | assembler_name_hash = | |
384 | htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name, | |
385 | NULL); | |
386 | FOR_EACH_SYMBOL (node) | |
c3167b00 | 387 | insert_to_assembler_name_hash (node, false); |
1ab24192 | 388 | } |
b5493fb2 | 389 | } |
1ab24192 | 390 | |
b5493fb2 JH |
391 | /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. |
392 | Return NULL if there's no such node. */ | |
393 | ||
5e20cdc9 | 394 | symtab_node * |
b5493fb2 JH |
395 | symtab_node_for_asm (const_tree asmname) |
396 | { | |
5e20cdc9 | 397 | symtab_node *node; |
b5493fb2 JH |
398 | void **slot; |
399 | ||
400 | symtab_initialize_asm_name_hash (); | |
1ab24192 JH |
401 | slot = htab_find_slot_with_hash (assembler_name_hash, asmname, |
402 | decl_assembler_name_hash (asmname), | |
403 | NO_INSERT); | |
404 | ||
405 | if (slot) | |
406 | { | |
5e20cdc9 | 407 | node = (symtab_node *) *slot; |
1ab24192 JH |
408 | return node; |
409 | } | |
410 | return NULL; | |
411 | } | |
412 | ||
413 | /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */ | |
414 | ||
415 | void | |
416 | change_decl_assembler_name (tree decl, tree name) | |
417 | { | |
5e20cdc9 | 418 | symtab_node *node = NULL; |
1ab24192 JH |
419 | |
420 | /* We can have user ASM names on things, like global register variables, that | |
421 | are not in the symbol table. */ | |
422 | if ((TREE_CODE (decl) == VAR_DECL | |
423 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) | |
424 | || TREE_CODE (decl) == FUNCTION_DECL) | |
425 | node = symtab_get_node (decl); | |
426 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) | |
427 | { | |
428 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
429 | if (node) | |
c3167b00 | 430 | insert_to_assembler_name_hash (node, true); |
1ab24192 JH |
431 | } |
432 | else | |
433 | { | |
434 | if (name == DECL_ASSEMBLER_NAME (decl)) | |
435 | return; | |
436 | ||
8a41354f JH |
437 | tree alias = (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) |
438 | ? TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) | |
439 | : NULL); | |
1ab24192 | 440 | if (node) |
c3167b00 | 441 | unlink_from_assembler_name_hash (node, true); |
1ab24192 JH |
442 | if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) |
443 | && DECL_RTL_SET_P (decl)) | |
444 | warning (0, "%D renamed after being referenced in assembly", decl); | |
445 | ||
446 | SET_DECL_ASSEMBLER_NAME (decl, name); | |
8a41354f JH |
447 | if (alias) |
448 | { | |
449 | IDENTIFIER_TRANSPARENT_ALIAS (name) = 1; | |
1fed15fc | 450 | TREE_CHAIN (name) = alias; |
8a41354f | 451 | } |
1ab24192 | 452 | if (node) |
c3167b00 | 453 | insert_to_assembler_name_hash (node, true); |
1ab24192 JH |
454 | } |
455 | } | |
456 | ||
65d630d4 JH |
457 | /* Add NEW_ to the same comdat group that OLD is in. */ |
458 | ||
459 | void | |
5e20cdc9 DM |
460 | symtab_add_to_same_comdat_group (symtab_node *new_node, |
461 | symtab_node *old_node) | |
65d630d4 | 462 | { |
aede2c10 | 463 | gcc_assert (old_node->get_comdat_group ()); |
67348ccc | 464 | gcc_assert (!new_node->same_comdat_group); |
65d630d4 JH |
465 | gcc_assert (new_node != old_node); |
466 | ||
aede2c10 | 467 | new_node->set_comdat_group (old_node->get_comdat_group ()); |
67348ccc DM |
468 | new_node->same_comdat_group = old_node; |
469 | if (!old_node->same_comdat_group) | |
470 | old_node->same_comdat_group = new_node; | |
65d630d4 JH |
471 | else |
472 | { | |
5e20cdc9 | 473 | symtab_node *n; |
67348ccc DM |
474 | for (n = old_node->same_comdat_group; |
475 | n->same_comdat_group != old_node; | |
476 | n = n->same_comdat_group) | |
65d630d4 | 477 | ; |
67348ccc | 478 | n->same_comdat_group = new_node; |
65d630d4 JH |
479 | } |
480 | } | |
481 | ||
482 | /* Dissolve the same_comdat_group list in which NODE resides. */ | |
483 | ||
484 | void | |
5e20cdc9 | 485 | symtab_dissolve_same_comdat_group_list (symtab_node *node) |
65d630d4 | 486 | { |
5e20cdc9 DM |
487 | symtab_node *n = node; |
488 | symtab_node *next; | |
65d630d4 | 489 | |
67348ccc | 490 | if (!node->same_comdat_group) |
65d630d4 JH |
491 | return; |
492 | do | |
493 | { | |
67348ccc DM |
494 | next = n->same_comdat_group; |
495 | n->same_comdat_group = NULL; | |
aede2c10 | 496 | /* Clear comdat_group for comdat locals, since |
1f26ac87 JM |
497 | make_decl_local doesn't. */ |
498 | if (!TREE_PUBLIC (n->decl)) | |
aede2c10 | 499 | n->set_comdat_group (NULL); |
65d630d4 JH |
500 | n = next; |
501 | } | |
502 | while (n != node); | |
503 | } | |
504 | ||
8f940ee6 JH |
505 | /* Return printable assembler name of NODE. |
506 | This function is used only for debugging. When assembler name | |
507 | is unknown go with identifier name. */ | |
508 | ||
509 | const char * | |
fec39fa6 | 510 | symtab_node::asm_name () const |
8f940ee6 | 511 | { |
fec39fa6 TS |
512 | if (!DECL_ASSEMBLER_NAME_SET_P (decl)) |
513 | return lang_hooks.decl_printable_name (decl, 2); | |
514 | return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
8f940ee6 JH |
515 | } |
516 | ||
517 | /* Return printable identifier name. */ | |
518 | ||
519 | const char * | |
fec39fa6 | 520 | symtab_node::name () const |
8f940ee6 | 521 | { |
fec39fa6 | 522 | return lang_hooks.decl_printable_name (decl, 2); |
8f940ee6 JH |
523 | } |
524 | ||
525 | static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; | |
526 | ||
527 | /* Dump base fields of symtab nodes. Not to be used directly. */ | |
528 | ||
529 | void | |
5e20cdc9 | 530 | dump_symtab_base (FILE *f, symtab_node *node) |
8f940ee6 JH |
531 | { |
532 | static const char * const visibility_types[] = { | |
533 | "default", "protected", "hidden", "internal" | |
534 | }; | |
535 | ||
536 | fprintf (f, "%s/%i (%s)", | |
fec39fa6 | 537 | node->asm_name (), |
67348ccc | 538 | node->order, |
fec39fa6 | 539 | node->name ()); |
8f940ee6 | 540 | dump_addr (f, " @", (void *)node); |
67348ccc | 541 | fprintf (f, "\n Type: %s", symtab_type_names[node->type]); |
e70670cf | 542 | |
67348ccc | 543 | if (node->definition) |
e70670cf | 544 | fprintf (f, " definition"); |
67348ccc | 545 | if (node->analyzed) |
e70670cf | 546 | fprintf (f, " analyzed"); |
67348ccc | 547 | if (node->alias) |
e70670cf | 548 | fprintf (f, " alias"); |
67348ccc | 549 | if (node->weakref) |
08346abd | 550 | fprintf (f, " weakref"); |
67348ccc | 551 | if (node->cpp_implicit_alias) |
40a7fe1e | 552 | fprintf (f, " cpp_implicit_alias"); |
67348ccc | 553 | if (node->alias_target) |
40a7fe1e | 554 | fprintf (f, " target:%s", |
67348ccc | 555 | DECL_P (node->alias_target) |
40a7fe1e | 556 | ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME |
67348ccc DM |
557 | (node->alias_target)) |
558 | : IDENTIFIER_POINTER (node->alias_target)); | |
3d8d0043 MJ |
559 | if (node->body_removed) |
560 | fprintf (f, "\n Body removed by symtab_remove_unreachable_nodes"); | |
e70670cf | 561 | fprintf (f, "\n Visibility:"); |
67348ccc | 562 | if (node->in_other_partition) |
8f940ee6 | 563 | fprintf (f, " in_other_partition"); |
67348ccc | 564 | if (node->used_from_other_partition) |
8f940ee6 | 565 | fprintf (f, " used_from_other_partition"); |
67348ccc | 566 | if (node->force_output) |
ead84f73 | 567 | fprintf (f, " force_output"); |
67348ccc | 568 | if (node->forced_by_abi) |
edb983b2 | 569 | fprintf (f, " forced_by_abi"); |
67348ccc | 570 | if (node->externally_visible) |
e5b962d0 | 571 | fprintf (f, " externally_visible"); |
67348ccc | 572 | if (node->resolution != LDPR_UNKNOWN) |
8f940ee6 | 573 | fprintf (f, " %s", |
67348ccc DM |
574 | ld_plugin_symbol_resolution_names[(int)node->resolution]); |
575 | if (TREE_ASM_WRITTEN (node->decl)) | |
8f940ee6 | 576 | fprintf (f, " asm_written"); |
67348ccc | 577 | if (DECL_EXTERNAL (node->decl)) |
8f940ee6 | 578 | fprintf (f, " external"); |
67348ccc | 579 | if (TREE_PUBLIC (node->decl)) |
8f940ee6 | 580 | fprintf (f, " public"); |
67348ccc | 581 | if (DECL_COMMON (node->decl)) |
8f940ee6 | 582 | fprintf (f, " common"); |
67348ccc | 583 | if (DECL_WEAK (node->decl)) |
8f940ee6 | 584 | fprintf (f, " weak"); |
67348ccc | 585 | if (DECL_DLLIMPORT_P (node->decl)) |
8f940ee6 | 586 | fprintf (f, " dll_import"); |
67348ccc | 587 | if (DECL_COMDAT (node->decl)) |
8f940ee6 | 588 | fprintf (f, " comdat"); |
aede2c10 | 589 | if (node->get_comdat_group ()) |
8f940ee6 | 590 | fprintf (f, " comdat_group:%s", |
d67ff7b7 | 591 | IDENTIFIER_POINTER (node->get_comdat_group_id ())); |
67348ccc | 592 | if (DECL_ONE_ONLY (node->decl)) |
8f940ee6 | 593 | fprintf (f, " one_only"); |
24d047a3 JH |
594 | if (node->get_section ()) |
595 | fprintf (f, " section:%s", | |
e257a17c JH |
596 | node->get_section ()); |
597 | if (node->implicit_section) | |
598 | fprintf (f," (implicit_section)"); | |
67348ccc | 599 | if (DECL_VISIBILITY_SPECIFIED (node->decl)) |
8f940ee6 | 600 | fprintf (f, " visibility_specified"); |
67348ccc | 601 | if (DECL_VISIBILITY (node->decl)) |
8f940ee6 | 602 | fprintf (f, " visibility:%s", |
67348ccc DM |
603 | visibility_types [DECL_VISIBILITY (node->decl)]); |
604 | if (DECL_VIRTUAL_P (node->decl)) | |
8f940ee6 | 605 | fprintf (f, " virtual"); |
67348ccc | 606 | if (DECL_ARTIFICIAL (node->decl)) |
8f940ee6 | 607 | fprintf (f, " artificial"); |
67348ccc | 608 | if (TREE_CODE (node->decl) == FUNCTION_DECL) |
838ff415 | 609 | { |
67348ccc | 610 | if (DECL_STATIC_CONSTRUCTOR (node->decl)) |
838ff415 | 611 | fprintf (f, " constructor"); |
67348ccc | 612 | if (DECL_STATIC_DESTRUCTOR (node->decl)) |
838ff415 JH |
613 | fprintf (f, " destructor"); |
614 | } | |
8f940ee6 JH |
615 | fprintf (f, "\n"); |
616 | ||
67348ccc | 617 | if (node->same_comdat_group) |
8f940ee6 | 618 | fprintf (f, " Same comdat group as: %s/%i\n", |
fec39fa6 | 619 | node->same_comdat_group->asm_name (), |
67348ccc DM |
620 | node->same_comdat_group->order); |
621 | if (node->next_sharing_asm_name) | |
8f940ee6 | 622 | fprintf (f, " next sharing asm name: %i\n", |
67348ccc DM |
623 | node->next_sharing_asm_name->order); |
624 | if (node->previous_sharing_asm_name) | |
8f940ee6 | 625 | fprintf (f, " previous sharing asm name: %i\n", |
67348ccc | 626 | node->previous_sharing_asm_name->order); |
8f940ee6 | 627 | |
67348ccc | 628 | if (node->address_taken) |
fe0bd630 | 629 | fprintf (f, " Address is taken.\n"); |
67348ccc | 630 | if (node->aux) |
66058468 JH |
631 | { |
632 | fprintf (f, " Aux:"); | |
67348ccc | 633 | dump_addr (f, " @", (void *)node->aux); |
66058468 | 634 | } |
8f940ee6 JH |
635 | |
636 | fprintf (f, " References: "); | |
67348ccc | 637 | ipa_dump_references (f, &node->ref_list); |
5932a4d4 | 638 | fprintf (f, " Referring: "); |
67348ccc DM |
639 | ipa_dump_referring (f, &node->ref_list); |
640 | if (node->lto_file_data) | |
b5493fb2 | 641 | fprintf (f, " Read from file: %s\n", |
67348ccc | 642 | node->lto_file_data->file_name); |
8f940ee6 JH |
643 | } |
644 | ||
645 | /* Dump symtab node. */ | |
646 | ||
647 | void | |
5e20cdc9 | 648 | dump_symtab_node (FILE *f, symtab_node *node) |
8f940ee6 | 649 | { |
7de90a6c | 650 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
5d59b5e1 | 651 | dump_cgraph_node (f, cnode); |
7de90a6c | 652 | else if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
5d59b5e1 | 653 | dump_varpool_node (f, vnode); |
8f940ee6 JH |
654 | } |
655 | ||
656 | /* Dump symbol table. */ | |
657 | ||
658 | void | |
659 | dump_symtab (FILE *f) | |
660 | { | |
5e20cdc9 | 661 | symtab_node *node; |
8f940ee6 JH |
662 | fprintf (f, "Symbol table:\n\n"); |
663 | FOR_EACH_SYMBOL (node) | |
664 | dump_symtab_node (f, node); | |
665 | } | |
666 | ||
667 | /* Dump symtab node NODE to stderr. */ | |
668 | ||
669 | DEBUG_FUNCTION void | |
5e20cdc9 | 670 | debug_symtab_node (symtab_node *node) |
8f940ee6 JH |
671 | { |
672 | dump_symtab_node (stderr, node); | |
673 | } | |
674 | ||
675 | /* Dump symbol table to stderr. */ | |
676 | ||
677 | DEBUG_FUNCTION void | |
678 | debug_symtab (void) | |
679 | { | |
680 | dump_symtab (stderr); | |
681 | } | |
682 | ||
474ffc72 JH |
683 | /* Verify common part of symtab nodes. */ |
684 | ||
685 | DEBUG_FUNCTION bool | |
5e20cdc9 | 686 | verify_symtab_base (symtab_node *node) |
474ffc72 JH |
687 | { |
688 | bool error_found = false; | |
5e20cdc9 | 689 | symtab_node *hashed_node; |
474ffc72 | 690 | |
7de90a6c | 691 | if (is_a <cgraph_node *> (node)) |
474ffc72 | 692 | { |
67348ccc | 693 | if (TREE_CODE (node->decl) != FUNCTION_DECL) |
474ffc72 JH |
694 | { |
695 | error ("function symbol is not function"); | |
696 | error_found = true; | |
697 | } | |
698 | } | |
7de90a6c | 699 | else if (is_a <varpool_node *> (node)) |
474ffc72 | 700 | { |
67348ccc | 701 | if (TREE_CODE (node->decl) != VAR_DECL) |
474ffc72 JH |
702 | { |
703 | error ("variable symbol is not variable"); | |
704 | error_found = true; | |
705 | } | |
706 | } | |
707 | else | |
708 | { | |
709 | error ("node has unknown type"); | |
710 | error_found = true; | |
711 | } | |
712 | ||
ca0f62a8 | 713 | if (cgraph_state != CGRAPH_LTO_STREAMING) |
474ffc72 | 714 | { |
67348ccc | 715 | hashed_node = symtab_get_node (node->decl); |
ca0f62a8 JH |
716 | if (!hashed_node) |
717 | { | |
aede2c10 | 718 | error ("node not found node->decl->decl_with_vis.symtab_node"); |
ca0f62a8 JH |
719 | error_found = true; |
720 | } | |
e5b962d0 | 721 | if (hashed_node != node |
7de90a6c DM |
722 | && (!is_a <cgraph_node *> (node) |
723 | || !dyn_cast <cgraph_node *> (node)->clone_of | |
724 | || dyn_cast <cgraph_node *> (node)->clone_of->decl | |
67348ccc | 725 | != node->decl)) |
e5b962d0 | 726 | { |
aede2c10 | 727 | error ("node differs from node->decl->decl_with_vis.symtab_node"); |
e5b962d0 JH |
728 | error_found = true; |
729 | } | |
474ffc72 JH |
730 | } |
731 | if (assembler_name_hash) | |
732 | { | |
67348ccc DM |
733 | hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl)); |
734 | if (hashed_node && hashed_node->previous_sharing_asm_name) | |
474ffc72 JH |
735 | { |
736 | error ("assembler name hash list corrupted"); | |
737 | error_found = true; | |
738 | } | |
739 | while (hashed_node) | |
740 | { | |
741 | if (hashed_node == node) | |
742 | break; | |
67348ccc | 743 | hashed_node = hashed_node->next_sharing_asm_name; |
474ffc72 | 744 | } |
b5493fb2 | 745 | if (!hashed_node |
7de90a6c | 746 | && !(is_a <varpool_node *> (node) |
67348ccc | 747 | || DECL_HARD_REGISTER (node->decl))) |
474ffc72 JH |
748 | { |
749 | error ("node not found in symtab assembler name hash"); | |
750 | error_found = true; | |
751 | } | |
752 | } | |
67348ccc DM |
753 | if (node->previous_sharing_asm_name |
754 | && node->previous_sharing_asm_name->next_sharing_asm_name != node) | |
474ffc72 JH |
755 | { |
756 | error ("double linked list of assembler names corrupted"); | |
e70670cf JH |
757 | error_found = true; |
758 | } | |
67348ccc | 759 | if (node->analyzed && !node->definition) |
e70670cf JH |
760 | { |
761 | error ("node is analyzed byt it is not a definition"); | |
762 | error_found = true; | |
474ffc72 | 763 | } |
67348ccc | 764 | if (node->cpp_implicit_alias && !node->alias) |
40a7fe1e JH |
765 | { |
766 | error ("node is alias but not implicit alias"); | |
767 | error_found = true; | |
768 | } | |
67348ccc DM |
769 | if (node->alias && !node->definition |
770 | && !node->weakref) | |
40a7fe1e JH |
771 | { |
772 | error ("node is alias but not definition"); | |
773 | error_found = true; | |
774 | } | |
67348ccc | 775 | if (node->weakref && !node->alias) |
08346abd JH |
776 | { |
777 | error ("node is weakref but not an alias"); | |
778 | error_found = true; | |
779 | } | |
67348ccc | 780 | if (node->same_comdat_group) |
474ffc72 | 781 | { |
5e20cdc9 | 782 | symtab_node *n = node->same_comdat_group; |
474ffc72 | 783 | |
aede2c10 | 784 | if (!n->get_comdat_group ()) |
474ffc72 | 785 | { |
aede2c10 | 786 | error ("node is in same_comdat_group list but has no comdat_group"); |
474ffc72 JH |
787 | error_found = true; |
788 | } | |
aede2c10 | 789 | if (n->get_comdat_group () != node->get_comdat_group ()) |
7b3376a0 JH |
790 | { |
791 | error ("same_comdat_group list across different groups"); | |
792 | error_found = true; | |
793 | } | |
794 | if (!n->definition) | |
795 | { | |
796 | error ("Node has same_comdat_group but it is not a definition"); | |
797 | error_found = true; | |
798 | } | |
67348ccc | 799 | if (n->type != node->type) |
474ffc72 JH |
800 | { |
801 | error ("mixing different types of symbol in same comdat groups is not supported"); | |
802 | error_found = true; | |
803 | } | |
804 | if (n == node) | |
805 | { | |
806 | error ("node is alone in a comdat group"); | |
807 | error_found = true; | |
808 | } | |
809 | do | |
810 | { | |
67348ccc | 811 | if (!n->same_comdat_group) |
474ffc72 JH |
812 | { |
813 | error ("same_comdat_group is not a circular list"); | |
814 | error_found = true; | |
815 | break; | |
816 | } | |
67348ccc | 817 | n = n->same_comdat_group; |
474ffc72 JH |
818 | } |
819 | while (n != node); | |
1f26ac87 JM |
820 | if (symtab_comdat_local_p (node)) |
821 | { | |
822 | struct ipa_ref_list *refs = &node->ref_list; | |
823 | struct ipa_ref *ref; | |
e257a17c | 824 | |
1f26ac87 JM |
825 | for (int i = 0; ipa_ref_list_referring_iterate (refs, i, ref); ++i) |
826 | { | |
827 | if (!symtab_in_same_comdat_p (ref->referring, node)) | |
828 | { | |
829 | error ("comdat-local symbol referred to by %s outside its " | |
830 | "comdat", | |
831 | identifier_to_locale (ref->referring->name())); | |
832 | error_found = true; | |
833 | } | |
834 | } | |
835 | } | |
474ffc72 | 836 | } |
e257a17c JH |
837 | if (node->implicit_section && !node->get_section ()) |
838 | { | |
839 | error ("implicit_section flag is set but section isn't"); | |
840 | error_found = true; | |
841 | } | |
842 | if (node->get_section () && node->get_comdat_group () | |
843 | && !node->implicit_section) | |
844 | { | |
845 | error ("Both section and comdat group is set"); | |
846 | error_found = true; | |
847 | } | |
848 | /* TODO: Add string table for sections, so we do not keep holding duplicated | |
849 | strings. */ | |
850 | if (node->alias && node->definition | |
851 | && node->get_section () != symtab_alias_target (node)->get_section () | |
852 | && (!node->get_section() | |
853 | || !symtab_alias_target (node)->get_section () | |
854 | || strcmp (node->get_section(), | |
855 | symtab_alias_target (node)->get_section ()))) | |
856 | { | |
857 | error ("Alias and target's section differs"); | |
858 | dump_symtab_node (stderr, symtab_alias_target (node)); | |
859 | error_found = true; | |
860 | } | |
861 | if (node->alias && node->definition | |
862 | && node->get_comdat_group () != symtab_alias_target (node)->get_comdat_group ()) | |
863 | { | |
864 | error ("Alias and target's comdat groups differs"); | |
865 | dump_symtab_node (stderr, symtab_alias_target (node)); | |
866 | error_found = true; | |
867 | } | |
868 | ||
474ffc72 JH |
869 | return error_found; |
870 | } | |
871 | ||
872 | /* Verify consistency of NODE. */ | |
873 | ||
874 | DEBUG_FUNCTION void | |
5e20cdc9 | 875 | verify_symtab_node (symtab_node *node) |
474ffc72 JH |
876 | { |
877 | if (seen_error ()) | |
878 | return; | |
879 | ||
880 | timevar_push (TV_CGRAPH_VERIFY); | |
7de90a6c | 881 | if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) |
5d59b5e1 | 882 | verify_cgraph_node (cnode); |
474ffc72 JH |
883 | else |
884 | if (verify_symtab_base (node)) | |
885 | { | |
886 | dump_symtab_node (stderr, node); | |
887 | internal_error ("verify_symtab_node failed"); | |
888 | } | |
889 | timevar_pop (TV_CGRAPH_VERIFY); | |
890 | } | |
891 | ||
892 | /* Verify symbol table for internal consistency. */ | |
893 | ||
894 | DEBUG_FUNCTION void | |
895 | verify_symtab (void) | |
896 | { | |
5e20cdc9 | 897 | symtab_node *node; |
e257a17c JH |
898 | pointer_map<symtab_node *> comdat_head_map; |
899 | ||
474ffc72 | 900 | FOR_EACH_SYMBOL (node) |
e257a17c JH |
901 | { |
902 | verify_symtab_node (node); | |
903 | if (node->get_comdat_group ()) | |
904 | { | |
905 | symtab_node **entry, *s; | |
906 | bool existed; | |
907 | ||
908 | entry = comdat_head_map.insert (node->get_comdat_group (), &existed); | |
909 | if (!existed) | |
910 | *entry = node; | |
911 | else | |
912 | for (s = (*entry)->same_comdat_group; s != NULL && s != node; s = s->same_comdat_group) | |
913 | if (!s || s == *entry) | |
914 | { | |
915 | error ("Two symbols with same comdat_group are not linked by the same_comdat_group list."); | |
916 | dump_symtab_node (stderr, *entry); | |
917 | dump_symtab_node (stderr, s); | |
918 | internal_error ("verify_symtab failed"); | |
919 | } | |
920 | } | |
921 | } | |
474ffc72 JH |
922 | } |
923 | ||
65d630d4 JH |
924 | /* Return true when RESOLUTION indicate that linker will use |
925 | the symbol from non-LTO object files. */ | |
926 | ||
927 | bool | |
928 | resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) | |
929 | { | |
930 | return (resolution == LDPR_PREVAILING_DEF | |
931 | || resolution == LDPR_PREEMPTED_REG | |
932 | || resolution == LDPR_RESOLVED_EXEC | |
933 | || resolution == LDPR_RESOLVED_DYN); | |
934 | } | |
935 | ||
936 | /* Return true when NODE is known to be used from other (non-LTO) object file. | |
937 | Known only when doing LTO via linker plugin. */ | |
938 | ||
939 | bool | |
5e20cdc9 | 940 | symtab_used_from_object_file_p (symtab_node *node) |
65d630d4 | 941 | { |
67348ccc | 942 | if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) |
65d630d4 | 943 | return false; |
67348ccc | 944 | if (resolution_used_from_other_file_p (node->resolution)) |
65d630d4 JH |
945 | return true; |
946 | return false; | |
947 | } | |
948 | ||
949 | /* Make DECL local. FIXME: We shouldn't need to mess with rtl this early, | |
950 | but other code such as notice_global_symbol generates rtl. */ | |
40a7fe1e | 951 | |
65d630d4 JH |
952 | void |
953 | symtab_make_decl_local (tree decl) | |
954 | { | |
955 | rtx rtl, symbol; | |
956 | ||
aede2c10 | 957 | /* Avoid clearing comdat_groups on comdat-local decls. */ |
1f26ac87 JM |
958 | if (TREE_PUBLIC (decl) == 0) |
959 | return; | |
960 | ||
65d630d4 JH |
961 | if (TREE_CODE (decl) == VAR_DECL) |
962 | DECL_COMMON (decl) = 0; | |
963 | else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); | |
964 | ||
24d047a3 | 965 | DECL_COMDAT (decl) = 0; |
65d630d4 JH |
966 | DECL_WEAK (decl) = 0; |
967 | DECL_EXTERNAL (decl) = 0; | |
b5493fb2 JH |
968 | DECL_VISIBILITY_SPECIFIED (decl) = 0; |
969 | DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; | |
65d630d4 JH |
970 | TREE_PUBLIC (decl) = 0; |
971 | if (!DECL_RTL_SET_P (decl)) | |
972 | return; | |
973 | ||
974 | /* Update rtl flags. */ | |
975 | make_decl_rtl (decl); | |
976 | ||
977 | rtl = DECL_RTL (decl); | |
978 | if (!MEM_P (rtl)) | |
979 | return; | |
980 | ||
981 | symbol = XEXP (rtl, 0); | |
982 | if (GET_CODE (symbol) != SYMBOL_REF) | |
983 | return; | |
984 | ||
985 | SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl); | |
986 | } | |
e70670cf | 987 | |
40a7fe1e JH |
988 | /* Return availability of NODE. */ |
989 | ||
990 | enum availability | |
5e20cdc9 | 991 | symtab_node_availability (symtab_node *node) |
40a7fe1e | 992 | { |
7de90a6c | 993 | if (is_a <cgraph_node *> (node)) |
40a7fe1e JH |
994 | return cgraph_function_body_availability (cgraph (node)); |
995 | else | |
996 | return cgraph_variable_initializer_availability (varpool (node)); | |
997 | } | |
998 | ||
e70670cf JH |
999 | /* Given NODE, walk the alias chain to return the symbol NODE is alias of. |
1000 | If NODE is not an alias, return NODE. | |
1001 | When AVAILABILITY is non-NULL, get minimal availability in the chain. */ | |
1002 | ||
5e20cdc9 DM |
1003 | symtab_node * |
1004 | symtab_alias_ultimate_target (symtab_node *node, enum availability *availability) | |
e70670cf | 1005 | { |
aaae719d JH |
1006 | bool weakref_p = false; |
1007 | ||
67348ccc | 1008 | if (!node->alias) |
aaae719d JH |
1009 | { |
1010 | if (availability) | |
1011 | *availability = symtab_node_availability (node); | |
1012 | return node; | |
1013 | } | |
1014 | ||
1015 | /* To determine visibility of the target, we follow ELF semantic of aliases. | |
1016 | Here alias is an alternative assembler name of a given definition. Its | |
1aa95df7 | 1017 | availability prevails the availability of its target (i.e. static alias of |
aaae719d JH |
1018 | weak definition is available. |
1019 | ||
1020 | Weakref is a different animal (and not part of ELF per se). It is just | |
1021 | alternative name of a given symbol used within one complation unit | |
1022 | and is translated prior hitting the object file. It inherits the | |
1023 | visibility of its target (i.e. weakref of non-overwritable definition | |
1024 | is non-overwritable, while weakref of weak definition is weak). | |
1025 | ||
1026 | If we ever get into supporting targets with different semantics, a target | |
1027 | hook will be needed here. */ | |
1028 | ||
e70670cf | 1029 | if (availability) |
aaae719d | 1030 | { |
67348ccc | 1031 | weakref_p = node->weakref; |
aaae719d JH |
1032 | if (!weakref_p) |
1033 | *availability = symtab_node_availability (node); | |
1034 | else | |
1035 | *availability = AVAIL_LOCAL; | |
1036 | } | |
e70670cf JH |
1037 | while (node) |
1038 | { | |
67348ccc | 1039 | if (node->alias && node->analyzed) |
e70670cf JH |
1040 | node = symtab_alias_target (node); |
1041 | else | |
aaae719d JH |
1042 | { |
1043 | if (!availability) | |
1044 | ; | |
67348ccc | 1045 | else if (node->analyzed) |
aaae719d JH |
1046 | { |
1047 | if (weakref_p) | |
1048 | { | |
1049 | enum availability a = symtab_node_availability (node); | |
1050 | if (a < *availability) | |
1051 | *availability = a; | |
1052 | } | |
1053 | } | |
1054 | else | |
1055 | *availability = AVAIL_NOT_AVAILABLE; | |
1056 | return node; | |
1057 | } | |
1058 | if (node && availability && weakref_p) | |
e70670cf | 1059 | { |
40a7fe1e | 1060 | enum availability a = symtab_node_availability (node); |
e70670cf JH |
1061 | if (a < *availability) |
1062 | *availability = a; | |
67348ccc | 1063 | weakref_p = node->weakref; |
e70670cf JH |
1064 | } |
1065 | } | |
1066 | if (availability) | |
1067 | *availability = AVAIL_NOT_AVAILABLE; | |
1068 | return NULL; | |
1069 | } | |
40a7fe1e JH |
1070 | |
1071 | /* C++ FE sometimes change linkage flags after producing same body aliases. | |
1072 | ||
1073 | FIXME: C++ produce implicit aliases for virtual functions and vtables that | |
1074 | are obviously equivalent. The way it is doing so is however somewhat | |
1075 | kludgy and interferes with the visibility code. As a result we need to | |
1076 | copy the visibility from the target to get things right. */ | |
1077 | ||
1078 | void | |
5e20cdc9 | 1079 | fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) |
40a7fe1e | 1080 | { |
7de90a6c | 1081 | if (is_a <cgraph_node *> (node)) |
40a7fe1e | 1082 | { |
67348ccc DM |
1083 | DECL_DECLARED_INLINE_P (node->decl) |
1084 | = DECL_DECLARED_INLINE_P (target->decl); | |
1085 | DECL_DISREGARD_INLINE_LIMITS (node->decl) | |
1086 | = DECL_DISREGARD_INLINE_LIMITS (target->decl); | |
40a7fe1e JH |
1087 | } |
1088 | /* FIXME: It is not really clear why those flags should not be copied for | |
1089 | functions, too. */ | |
1090 | else | |
1091 | { | |
67348ccc DM |
1092 | DECL_WEAK (node->decl) = DECL_WEAK (target->decl); |
1093 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); | |
1094 | DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (target->decl); | |
40a7fe1e | 1095 | } |
67348ccc DM |
1096 | DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl); |
1097 | if (TREE_PUBLIC (node->decl)) | |
40a7fe1e | 1098 | { |
aede2c10 JH |
1099 | tree group; |
1100 | ||
67348ccc DM |
1101 | DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); |
1102 | DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl); | |
aede2c10 JH |
1103 | group = target->get_comdat_group (); |
1104 | node->set_comdat_group (group); | |
1105 | if (group | |
67348ccc DM |
1106 | && !node->same_comdat_group) |
1107 | symtab_add_to_same_comdat_group (node, target); | |
40a7fe1e | 1108 | } |
67348ccc | 1109 | node->externally_visible = target->externally_visible; |
40a7fe1e JH |
1110 | } |
1111 | ||
f961457f JH |
1112 | /* Hash sections by their names. */ |
1113 | ||
1114 | static hashval_t | |
1115 | hash_section_hash_entry (const void *p) | |
1116 | { | |
1117 | const section_hash_entry *n = (const section_hash_entry *) p; | |
1118 | return htab_hash_string (n->name); | |
1119 | } | |
1120 | ||
1121 | /* Return true if section P1 name equals to P2. */ | |
1122 | ||
1123 | static int | |
1124 | eq_sections (const void *p1, const void *p2) | |
1125 | { | |
1126 | const section_hash_entry *n1 = (const section_hash_entry *) p1; | |
1127 | const char *name = (const char *)p2; | |
1128 | return n1->name == name || !strcmp (n1->name, name); | |
1129 | } | |
1130 | ||
1131 | /* Set section, do not recurse into aliases. | |
1132 | When one wants to change section of symbol and its aliases, | |
1133 | use set_section */ | |
1134 | ||
1135 | void | |
1136 | symtab_node::set_section_for_node (const char *section) | |
1137 | { | |
1138 | const char *current = get_section (); | |
1139 | void **slot; | |
1140 | ||
1141 | if (current == section | |
1142 | || (current && section | |
1143 | && !strcmp (current, section))) | |
1144 | return; | |
1145 | ||
1146 | if (current) | |
1147 | { | |
1148 | x_section->ref_count--; | |
1149 | if (!x_section->ref_count) | |
1150 | { | |
1151 | slot = htab_find_slot_with_hash (section_hash, x_section->name, | |
1152 | htab_hash_string (x_section->name), | |
1153 | INSERT); | |
1154 | ggc_free (x_section); | |
1155 | htab_clear_slot (section_hash, slot); | |
1156 | } | |
1157 | x_section = NULL; | |
1158 | } | |
1159 | if (!section) | |
1160 | { | |
1161 | implicit_section = false; | |
1162 | return; | |
1163 | } | |
1164 | if (!section_hash) | |
1165 | section_hash = htab_create_ggc (10, hash_section_hash_entry, | |
1166 | eq_sections, NULL); | |
1167 | slot = htab_find_slot_with_hash (section_hash, section, | |
1168 | htab_hash_string (section), | |
1169 | INSERT); | |
1170 | if (*slot) | |
1171 | x_section = (section_hash_entry *)*slot; | |
1172 | else | |
1173 | { | |
1174 | int len = strlen (section); | |
1175 | *slot = x_section = ggc_cleared_alloc<section_hash_entry> (); | |
1176 | x_section->name = ggc_vec_alloc<char> (len + 1); | |
1177 | memcpy (x_section->name, section, len + 1); | |
1178 | } | |
1179 | x_section->ref_count++; | |
1180 | } | |
1181 | ||
e257a17c JH |
1182 | /* Worker for set_section. */ |
1183 | ||
1184 | static bool | |
1185 | set_section_1 (struct symtab_node *n, void *s) | |
1186 | { | |
f961457f | 1187 | n->set_section_for_node ((char *)s); |
e257a17c JH |
1188 | return false; |
1189 | } | |
1190 | ||
1191 | /* Set section of symbol and its aliases. */ | |
1192 | ||
1193 | void | |
f961457f | 1194 | symtab_node::set_section (const char *section) |
e257a17c JH |
1195 | { |
1196 | gcc_assert (!this->alias); | |
f961457f | 1197 | symtab_for_node_and_aliases (this, set_section_1, const_cast<char *>(section), true); |
e257a17c JH |
1198 | } |
1199 | ||
569b1784 JH |
1200 | /* Return the initialization priority. */ |
1201 | ||
1202 | priority_type | |
1203 | symtab_node::get_init_priority () | |
1204 | { | |
1205 | struct symbol_priority_map *h; | |
1206 | struct symbol_priority_map in; | |
1207 | ||
1208 | if (!this->in_init_priority_hash) | |
1209 | return DEFAULT_INIT_PRIORITY; | |
1210 | in.symbol = this; | |
1211 | h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); | |
1212 | return h ? h->init : DEFAULT_INIT_PRIORITY; | |
1213 | } | |
1214 | ||
1215 | /* Return the finalization priority. */ | |
1216 | ||
1217 | priority_type | |
1218 | cgraph_node::get_fini_priority () | |
1219 | { | |
1220 | struct symbol_priority_map *h; | |
1221 | struct symbol_priority_map in; | |
1222 | ||
1223 | if (!this->in_init_priority_hash) | |
1224 | return DEFAULT_INIT_PRIORITY; | |
1225 | in.symbol = this; | |
1226 | h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in); | |
1227 | return h ? h->fini : DEFAULT_INIT_PRIORITY; | |
1228 | } | |
1229 | ||
1230 | /* Return true if the from tree in both priority maps are equal. */ | |
1231 | ||
1232 | int | |
1233 | symbol_priority_map_eq (const void *va, const void *vb) | |
1234 | { | |
1235 | const struct symbol_priority_map *const a = (const struct symbol_priority_map *) va, | |
1236 | *const b = (const struct symbol_priority_map *) vb; | |
1237 | return (a->symbol == b->symbol); | |
1238 | } | |
1239 | ||
1240 | /* Hash a from symbol in a symbol_priority_map. */ | |
1241 | ||
1242 | unsigned int | |
1243 | symbol_priority_map_hash (const void *item) | |
1244 | { | |
1245 | return htab_hash_pointer (((const struct symbol_priority_map *)item)->symbol); | |
1246 | } | |
1247 | ||
1248 | /* Return the initialization and finalization priority information for | |
1249 | DECL. If there is no previous priority information, a freshly | |
1250 | allocated structure is returned. */ | |
1251 | ||
1252 | static struct symbol_priority_map * | |
1253 | symbol_priority_info (struct symtab_node *symbol) | |
1254 | { | |
1255 | struct symbol_priority_map in; | |
1256 | struct symbol_priority_map *h; | |
1257 | void **loc; | |
1258 | ||
1259 | in.symbol = symbol; | |
1260 | if (!init_priority_hash) | |
1261 | init_priority_hash = htab_create_ggc (512, symbol_priority_map_hash, | |
1262 | symbol_priority_map_eq, 0); | |
1263 | ||
1264 | loc = htab_find_slot (init_priority_hash, &in, INSERT); | |
1265 | h = (struct symbol_priority_map *) *loc; | |
1266 | if (!h) | |
1267 | { | |
1268 | h = ggc_cleared_alloc<symbol_priority_map> (); | |
1269 | *loc = h; | |
1270 | h->symbol = symbol; | |
1271 | h->init = DEFAULT_INIT_PRIORITY; | |
1272 | h->fini = DEFAULT_INIT_PRIORITY; | |
1273 | symbol->in_init_priority_hash = true; | |
1274 | } | |
1275 | ||
1276 | return h; | |
1277 | } | |
1278 | ||
1279 | /* Set initialization priority to PRIORITY. */ | |
1280 | ||
1281 | void | |
1282 | symtab_node::set_init_priority (priority_type priority) | |
1283 | { | |
1284 | struct symbol_priority_map *h; | |
1285 | ||
1286 | if (is_a <cgraph_node *> (this)) | |
1287 | gcc_assert (DECL_STATIC_CONSTRUCTOR (this->decl)); | |
1288 | ||
1289 | if (priority == DEFAULT_INIT_PRIORITY) | |
1290 | { | |
1291 | gcc_assert (get_init_priority() == priority); | |
1292 | return; | |
1293 | } | |
1294 | h = symbol_priority_info (this); | |
1295 | h->init = priority; | |
1296 | } | |
1297 | ||
1298 | /* Set fialization priority to PRIORITY. */ | |
1299 | ||
1300 | void | |
1301 | cgraph_node::set_fini_priority (priority_type priority) | |
1302 | { | |
1303 | struct symbol_priority_map *h; | |
1304 | ||
1305 | gcc_assert (DECL_STATIC_DESTRUCTOR (this->decl)); | |
1306 | ||
1307 | if (priority == DEFAULT_INIT_PRIORITY) | |
1308 | { | |
1309 | gcc_assert (get_fini_priority() == priority); | |
1310 | return; | |
1311 | } | |
1312 | h = symbol_priority_info (this); | |
1313 | h->fini = priority; | |
1314 | } | |
1315 | ||
e257a17c JH |
1316 | /* Worker for symtab_resolve_alias. */ |
1317 | ||
1318 | static bool | |
1319 | set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED) | |
1320 | { | |
1321 | n->implicit_section = true; | |
1322 | return false; | |
1323 | } | |
1324 | ||
40a7fe1e JH |
1325 | /* Add reference recording that NODE is alias of TARGET. |
1326 | The function can fail in the case of aliasing cycles; in this case | |
1327 | it returns false. */ | |
1328 | ||
1329 | bool | |
5e20cdc9 | 1330 | symtab_resolve_alias (symtab_node *node, symtab_node *target) |
40a7fe1e | 1331 | { |
5e20cdc9 | 1332 | symtab_node *n; |
40a7fe1e | 1333 | |
67348ccc DM |
1334 | gcc_assert (!node->analyzed |
1335 | && !vec_safe_length (node->ref_list.references)); | |
40a7fe1e JH |
1336 | |
1337 | /* Never let cycles to creep into the symbol table alias references; | |
1338 | those will make alias walkers to be infinite. */ | |
67348ccc DM |
1339 | for (n = target; n && n->alias; |
1340 | n = n->analyzed ? symtab_alias_target (n) : NULL) | |
40a7fe1e JH |
1341 | if (n == node) |
1342 | { | |
7de90a6c | 1343 | if (is_a <cgraph_node *> (node)) |
67348ccc | 1344 | error ("function %q+D part of alias cycle", node->decl); |
7de90a6c | 1345 | else if (is_a <varpool_node *> (node)) |
67348ccc | 1346 | error ("variable %q+D part of alias cycle", node->decl); |
40a7fe1e JH |
1347 | else |
1348 | gcc_unreachable (); | |
67348ccc | 1349 | node->alias = false; |
40a7fe1e JH |
1350 | return false; |
1351 | } | |
1352 | ||
1353 | /* "analyze" the node - i.e. mark the reference. */ | |
67348ccc DM |
1354 | node->definition = true; |
1355 | node->alias = true; | |
1356 | node->analyzed = true; | |
40a7fe1e JH |
1357 | ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); |
1358 | ||
e257a17c JH |
1359 | /* Add alias into the comdat group of its target unless it is already there. */ |
1360 | if (node->same_comdat_group) | |
1361 | symtab_remove_from_same_comdat_group (node); | |
1362 | node->set_comdat_group (NULL); | |
1363 | if (target->get_comdat_group ()) | |
1364 | symtab_add_to_same_comdat_group (node, target); | |
1365 | ||
1366 | if ((node->get_section () != target->get_section () | |
1367 | || target->get_comdat_group ()) | |
1368 | && node->get_section () && !node->implicit_section) | |
1369 | { | |
1370 | error ("section of alias %q+D must match section of its target", | |
1371 | node->decl); | |
1372 | } | |
f961457f JH |
1373 | symtab_for_node_and_aliases (node, set_section_1, |
1374 | const_cast<char *>(target->get_section ()), true); | |
e257a17c JH |
1375 | if (target->implicit_section) |
1376 | symtab_for_node_and_aliases (node, | |
1377 | set_implicit_section, NULL, true); | |
1378 | ||
d67ff7b7 | 1379 | /* Alias targets become redundant after alias is resolved into an reference. |
40a7fe1e JH |
1380 | We do not want to keep it around or we would have to mind updating them |
1381 | when renaming symbols. */ | |
67348ccc | 1382 | node->alias_target = NULL; |
40a7fe1e | 1383 | |
67348ccc | 1384 | if (node->cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) |
40a7fe1e JH |
1385 | fixup_same_cpp_alias_visibility (node, target); |
1386 | ||
1387 | /* If alias has address taken, so does the target. */ | |
67348ccc DM |
1388 | if (node->address_taken) |
1389 | symtab_alias_ultimate_target (target, NULL)->address_taken = true; | |
40a7fe1e JH |
1390 | return true; |
1391 | } | |
af15184a JH |
1392 | |
1393 | /* Call calback on NODE and aliases associated to NODE. | |
1394 | When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are | |
1395 | skipped. */ | |
1396 | ||
1397 | bool | |
5e20cdc9 DM |
1398 | symtab_for_node_and_aliases (symtab_node *node, |
1399 | bool (*callback) (symtab_node *, void *), | |
af15184a JH |
1400 | void *data, |
1401 | bool include_overwritable) | |
1402 | { | |
1403 | int i; | |
1404 | struct ipa_ref *ref; | |
1405 | ||
1406 | if (callback (node, data)) | |
1407 | return true; | |
67348ccc | 1408 | for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) |
af15184a JH |
1409 | if (ref->use == IPA_REF_ALIAS) |
1410 | { | |
5e20cdc9 | 1411 | symtab_node *alias = ref->referring; |
af15184a JH |
1412 | if (include_overwritable |
1413 | || symtab_node_availability (alias) > AVAIL_OVERWRITABLE) | |
1414 | if (symtab_for_node_and_aliases (alias, callback, data, | |
1415 | include_overwritable)) | |
1416 | return true; | |
1417 | } | |
1418 | return false; | |
1419 | } | |
1420 | ||
1421 | /* Worker searching nonoverwritable alias. */ | |
1422 | ||
1423 | static bool | |
5e20cdc9 | 1424 | symtab_nonoverwritable_alias_1 (symtab_node *node, void *data) |
af15184a | 1425 | { |
67348ccc | 1426 | if (decl_binds_to_current_def_p (node->decl)) |
af15184a | 1427 | { |
5e20cdc9 | 1428 | *(symtab_node **)data = node; |
af15184a JH |
1429 | return true; |
1430 | } | |
1431 | return false; | |
1432 | } | |
1433 | ||
1434 | /* If NODE can not be overwriten by static or dynamic linker to point to different | |
1435 | definition, return NODE. Otherwise look for alias with such property and if | |
1436 | none exists, introduce new one. */ | |
1437 | ||
5e20cdc9 DM |
1438 | symtab_node * |
1439 | symtab_nonoverwritable_alias (symtab_node *node) | |
af15184a JH |
1440 | { |
1441 | tree new_decl; | |
5e20cdc9 | 1442 | symtab_node *new_node = NULL; |
8a41354f JH |
1443 | |
1444 | /* First try to look up existing alias or base object | |
1445 | (if that is already non-overwritable). */ | |
1446 | node = symtab_alias_ultimate_target (node, NULL); | |
67348ccc | 1447 | gcc_assert (!node->alias && !node->weakref); |
af15184a JH |
1448 | symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, |
1449 | (void *)&new_node, true); | |
1450 | if (new_node) | |
1451 | return new_node; | |
cdb87c08 JH |
1452 | #ifndef ASM_OUTPUT_DEF |
1453 | /* If aliases aren't supported by the assembler, fail. */ | |
1454 | return NULL; | |
1455 | #endif | |
af15184a | 1456 | |
8a41354f | 1457 | /* Otherwise create a new one. */ |
67348ccc DM |
1458 | new_decl = copy_node (node->decl); |
1459 | DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias"); | |
af15184a JH |
1460 | if (TREE_CODE (new_decl) == FUNCTION_DECL) |
1461 | DECL_STRUCT_FUNCTION (new_decl) = NULL; | |
1462 | DECL_INITIAL (new_decl) = NULL; | |
1463 | SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); | |
1464 | SET_DECL_RTL (new_decl, NULL); | |
1465 | ||
1466 | /* Update the properties. */ | |
1467 | DECL_EXTERNAL (new_decl) = 0; | |
af15184a JH |
1468 | TREE_PUBLIC (new_decl) = 0; |
1469 | DECL_COMDAT (new_decl) = 0; | |
1470 | DECL_WEAK (new_decl) = 0; | |
80bc9b6e JH |
1471 | |
1472 | /* Since the aliases can be added to vtables, keep DECL_VIRTUAL flag. */ | |
1473 | DECL_VIRTUAL_P (new_decl) = DECL_VIRTUAL_P (node->decl); | |
af15184a JH |
1474 | if (TREE_CODE (new_decl) == FUNCTION_DECL) |
1475 | { | |
1476 | DECL_STATIC_CONSTRUCTOR (new_decl) = 0; | |
1477 | DECL_STATIC_DESTRUCTOR (new_decl) = 0; | |
67348ccc DM |
1478 | new_node = cgraph_create_function_alias |
1479 | (new_decl, node->decl); | |
af15184a JH |
1480 | } |
1481 | else | |
97ae6b64 JH |
1482 | { |
1483 | TREE_READONLY (new_decl) = TREE_READONLY (node->decl); | |
80bc9b6e | 1484 | DECL_INITIAL (new_decl) = error_mark_node; |
97ae6b64 JH |
1485 | new_node = varpool_create_variable_alias (new_decl, node->decl); |
1486 | } | |
af15184a | 1487 | symtab_resolve_alias (new_node, node); |
97ae6b64 JH |
1488 | gcc_assert (decl_binds_to_current_def_p (new_decl) |
1489 | && targetm.binds_local_p (new_decl)); | |
af15184a JH |
1490 | return new_node; |
1491 | } | |
fc11f321 JH |
1492 | |
1493 | /* Return true if A and B represents semantically equivalent symbols. */ | |
1494 | ||
1495 | bool | |
5e20cdc9 DM |
1496 | symtab_semantically_equivalent_p (symtab_node *a, |
1497 | symtab_node *b) | |
fc11f321 JH |
1498 | { |
1499 | enum availability avail; | |
5e20cdc9 DM |
1500 | symtab_node *ba; |
1501 | symtab_node *bb; | |
fc11f321 JH |
1502 | |
1503 | /* Equivalent functions are equivalent. */ | |
67348ccc | 1504 | if (a->decl == b->decl) |
fc11f321 JH |
1505 | return true; |
1506 | ||
1507 | /* If symbol is not overwritable by different implementation, | |
1508 | walk to the base object it defines. */ | |
1509 | ba = symtab_alias_ultimate_target (a, &avail); | |
1510 | if (avail >= AVAIL_AVAILABLE) | |
1511 | { | |
1512 | if (ba == b) | |
1513 | return true; | |
1514 | } | |
1515 | else | |
1516 | ba = a; | |
1517 | bb = symtab_alias_ultimate_target (b, &avail); | |
1518 | if (avail >= AVAIL_AVAILABLE) | |
1519 | { | |
1520 | if (a == bb) | |
1521 | return true; | |
1522 | } | |
1523 | else | |
1524 | bb = b; | |
1525 | return bb == ba; | |
1526 | } | |
ddb3e20a JH |
1527 | |
1528 | /* Classify symbol NODE for partitioning. */ | |
1529 | ||
1530 | enum symbol_partitioning_class | |
1531 | symtab_get_symbol_partitioning_class (symtab_node *node) | |
1532 | { | |
1533 | /* Inline clones are always duplicated. | |
1534 | This include external delcarations. */ | |
7de90a6c | 1535 | cgraph_node *cnode = dyn_cast <cgraph_node *> (node); |
ddb3e20a JH |
1536 | |
1537 | if (DECL_ABSTRACT (node->decl)) | |
1538 | return SYMBOL_EXTERNAL; | |
1539 | ||
1540 | if (cnode && cnode->global.inlined_to) | |
1541 | return SYMBOL_DUPLICATE; | |
1542 | ||
1543 | /* Weakref aliases are always duplicated. */ | |
1544 | if (node->weakref) | |
1545 | return SYMBOL_DUPLICATE; | |
1546 | ||
1547 | /* External declarations are external. */ | |
1548 | if (DECL_EXTERNAL (node->decl)) | |
1549 | return SYMBOL_EXTERNAL; | |
1550 | ||
7de90a6c | 1551 | if (varpool_node *vnode = dyn_cast <varpool_node *> (node)) |
ddb3e20a JH |
1552 | { |
1553 | /* Constant pool references use local symbol names that can not | |
1554 | be promoted global. We should never put into a constant pool | |
1555 | objects that can not be duplicated across partitions. */ | |
1556 | if (DECL_IN_CONSTANT_POOL (node->decl)) | |
1557 | return SYMBOL_DUPLICATE; | |
1558 | gcc_checking_assert (vnode->definition); | |
1559 | } | |
1560 | /* Functions that are cloned may stay in callgraph even if they are unused. | |
1561 | Handle them as external; compute_ltrans_boundary take care to make | |
1562 | proper things to happen (i.e. to make them appear in the boundary but | |
1563 | with body streamed, so clone can me materialized). */ | |
1564 | else if (!cgraph (node)->definition) | |
1565 | return SYMBOL_EXTERNAL; | |
1566 | ||
1567 | /* Linker discardable symbols are duplicated to every use unless they are | |
cf288ed3 | 1568 | keyed. */ |
ddb3e20a JH |
1569 | if (DECL_ONE_ONLY (node->decl) |
1570 | && !node->force_output | |
1571 | && !node->forced_by_abi | |
1572 | && !symtab_used_from_object_file_p (node)) | |
1573 | return SYMBOL_DUPLICATE; | |
1574 | ||
1575 | return SYMBOL_PARTITION; | |
1576 | } | |
1ab24192 | 1577 | #include "gt-symtab.h" |