]>
Commit | Line | Data |
---|---|---|
8a4a83ed | 1 | /* Callgraph handling code. |
23a5b65a | 2 | Copyright (C) 2003-2014 Free Software Foundation, Inc. |
8a4a83ed 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 | |
9dcd6f09 | 9 | Software Foundation; either version 3, or (at your option) any later |
8a4a83ed JH |
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 | |
9dcd6f09 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
8a4a83ed JH |
20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
25 | #include "tree.h" | |
d8a2d370 | 26 | #include "varasm.h" |
8a4a83ed JH |
27 | #include "cgraph.h" |
28 | #include "langhooks.h" | |
1da2ed5f | 29 | #include "diagnostic-core.h" |
8a4a83ed | 30 | #include "hashtab.h" |
8a4a83ed | 31 | #include "timevar.h" |
b8698a0f | 32 | #include "debug.h" |
8a4a83ed JH |
33 | #include "target.h" |
34 | #include "output.h" | |
2fb9a547 | 35 | #include "gimple-expr.h" |
b20996ff | 36 | #include "flags.h" |
8a4a83ed | 37 | |
26e5b0fd JH |
38 | /* List of hooks triggered on varpool_node events. */ |
39 | struct varpool_node_hook_list { | |
40 | varpool_node_hook hook; | |
41 | void *data; | |
42 | struct varpool_node_hook_list *next; | |
43 | }; | |
44 | ||
45 | /* List of hooks triggered when a node is removed. */ | |
46 | struct varpool_node_hook_list *first_varpool_node_removal_hook; | |
47 | /* List of hooks triggered when an variable is inserted. */ | |
48 | struct varpool_node_hook_list *first_varpool_variable_insertion_hook; | |
49 | ||
50 | /* Register HOOK to be called with DATA on each removed node. */ | |
51 | struct varpool_node_hook_list * | |
52 | varpool_add_node_removal_hook (varpool_node_hook hook, void *data) | |
53 | { | |
54 | struct varpool_node_hook_list *entry; | |
55 | struct varpool_node_hook_list **ptr = &first_varpool_node_removal_hook; | |
56 | ||
57 | entry = (struct varpool_node_hook_list *) xmalloc (sizeof (*entry)); | |
58 | entry->hook = hook; | |
59 | entry->data = data; | |
60 | entry->next = NULL; | |
61 | while (*ptr) | |
62 | ptr = &(*ptr)->next; | |
63 | *ptr = entry; | |
64 | return entry; | |
65 | } | |
66 | ||
67 | /* Remove ENTRY from the list of hooks called on removing nodes. */ | |
68 | void | |
69 | varpool_remove_node_removal_hook (struct varpool_node_hook_list *entry) | |
70 | { | |
71 | struct varpool_node_hook_list **ptr = &first_varpool_node_removal_hook; | |
72 | ||
73 | while (*ptr != entry) | |
74 | ptr = &(*ptr)->next; | |
75 | *ptr = entry->next; | |
76 | free (entry); | |
77 | } | |
78 | ||
79 | /* Call all node removal hooks. */ | |
80 | static void | |
2c8326a5 | 81 | varpool_call_node_removal_hooks (varpool_node *node) |
26e5b0fd JH |
82 | { |
83 | struct varpool_node_hook_list *entry = first_varpool_node_removal_hook; | |
84 | while (entry) | |
85 | { | |
86 | entry->hook (node, entry->data); | |
87 | entry = entry->next; | |
88 | } | |
89 | } | |
90 | ||
91 | /* Register HOOK to be called with DATA on each inserted node. */ | |
92 | struct varpool_node_hook_list * | |
93 | varpool_add_variable_insertion_hook (varpool_node_hook hook, void *data) | |
94 | { | |
95 | struct varpool_node_hook_list *entry; | |
96 | struct varpool_node_hook_list **ptr = &first_varpool_variable_insertion_hook; | |
97 | ||
98 | entry = (struct varpool_node_hook_list *) xmalloc (sizeof (*entry)); | |
99 | entry->hook = hook; | |
100 | entry->data = data; | |
101 | entry->next = NULL; | |
102 | while (*ptr) | |
103 | ptr = &(*ptr)->next; | |
104 | *ptr = entry; | |
105 | return entry; | |
106 | } | |
107 | ||
108 | /* Remove ENTRY from the list of hooks called on inserted nodes. */ | |
109 | void | |
110 | varpool_remove_variable_insertion_hook (struct varpool_node_hook_list *entry) | |
111 | { | |
112 | struct varpool_node_hook_list **ptr = &first_varpool_variable_insertion_hook; | |
113 | ||
114 | while (*ptr != entry) | |
115 | ptr = &(*ptr)->next; | |
116 | *ptr = entry->next; | |
117 | free (entry); | |
118 | } | |
119 | ||
120 | /* Call all node insertion hooks. */ | |
121 | void | |
2c8326a5 | 122 | varpool_call_variable_insertion_hooks (varpool_node *node) |
26e5b0fd JH |
123 | { |
124 | struct varpool_node_hook_list *entry = first_varpool_variable_insertion_hook; | |
125 | while (entry) | |
126 | { | |
127 | entry->hook (node, entry->data); | |
128 | entry = entry->next; | |
129 | } | |
130 | } | |
131 | ||
bbf9ad07 JH |
132 | /* Allocate new callgraph node and insert it into basic data structures. */ |
133 | ||
2c8326a5 | 134 | varpool_node * |
bbf9ad07 JH |
135 | varpool_create_empty_node (void) |
136 | { | |
2c8326a5 | 137 | varpool_node *node = ggc_alloc_cleared_varpool_node (); |
67348ccc | 138 | node->type = SYMTAB_VARIABLE; |
bbf9ad07 JH |
139 | return node; |
140 | } | |
141 | ||
8a4a83ed | 142 | /* Return varpool node assigned to DECL. Create new one when needed. */ |
2c8326a5 | 143 | varpool_node * |
5d59b5e1 | 144 | varpool_node_for_decl (tree decl) |
8a4a83ed | 145 | { |
2c8326a5 | 146 | varpool_node *node = varpool_get_node (decl); |
bbf9ad07 | 147 | gcc_checking_assert (TREE_CODE (decl) == VAR_DECL); |
1ab24192 JH |
148 | if (node) |
149 | return node; | |
8a4a83ed | 150 | |
bbf9ad07 | 151 | node = varpool_create_empty_node (); |
67348ccc DM |
152 | node->decl = decl; |
153 | symtab_register_node (node); | |
8a4a83ed JH |
154 | return node; |
155 | } | |
156 | ||
2942c502 JH |
157 | /* Remove node from the varpool. */ |
158 | void | |
2c8326a5 | 159 | varpool_remove_node (varpool_node *node) |
2942c502 | 160 | { |
6a6dac52 | 161 | tree init; |
26e5b0fd | 162 | varpool_call_node_removal_hooks (node); |
67348ccc | 163 | symtab_unregister_node (node); |
e70670cf JH |
164 | |
165 | /* Because we remove references from external functions before final compilation, | |
166 | we may end up removing useful constructors. | |
167 | FIXME: We probably want to trace boundaries better. */ | |
67348ccc | 168 | if ((init = ctor_for_folding (node->decl)) == error_mark_node) |
e70670cf | 169 | varpool_remove_initializer (node); |
6a6dac52 | 170 | else |
67348ccc | 171 | DECL_INITIAL (node->decl) = init; |
e70670cf JH |
172 | ggc_free (node); |
173 | } | |
174 | ||
175 | /* Renove node initializer when it is no longer needed. */ | |
176 | void | |
2c8326a5 | 177 | varpool_remove_initializer (varpool_node *node) |
e70670cf | 178 | { |
67348ccc DM |
179 | if (DECL_INITIAL (node->decl) |
180 | && !DECL_IN_CONSTANT_POOL (node->decl) | |
6649df51 | 181 | /* Keep vtables for BINFO folding. */ |
67348ccc | 182 | && !DECL_VIRTUAL_P (node->decl) |
0bd0d3bc | 183 | /* FIXME: http://gcc.gnu.org/PR55395 */ |
ee03e71d RB |
184 | && debug_info_level == DINFO_LEVEL_NONE |
185 | /* When doing declaration merging we have duplicate | |
186 | entries for given decl. Do not attempt to remove | |
187 | the boides, or we will end up remiving | |
188 | wrong one. */ | |
189 | && cgraph_state != CGRAPH_LTO_STREAMING) | |
67348ccc | 190 | DECL_INITIAL (node->decl) = error_mark_node; |
2942c502 JH |
191 | } |
192 | ||
8a4a83ed JH |
193 | /* Dump given cgraph node. */ |
194 | void | |
2c8326a5 | 195 | dump_varpool_node (FILE *f, varpool_node *node) |
8a4a83ed | 196 | { |
67348ccc | 197 | dump_symtab_base (f, node); |
8f940ee6 | 198 | fprintf (f, " Availability: %s\n", |
8a4a83ed JH |
199 | cgraph_function_flags_ready |
200 | ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] | |
201 | : "not-ready"); | |
8f940ee6 | 202 | fprintf (f, " Varpool flags:"); |
67348ccc | 203 | if (DECL_INITIAL (node->decl)) |
8a4a83ed | 204 | fprintf (f, " initialized"); |
8a4a83ed JH |
205 | if (node->output) |
206 | fprintf (f, " output"); | |
67348ccc | 207 | if (TREE_READONLY (node->decl)) |
2d6e4603 | 208 | fprintf (f, " read-only"); |
67348ccc | 209 | if (ctor_for_folding (node->decl) != error_mark_node) |
2d6e4603 | 210 | fprintf (f, " const-value-known"); |
8a4a83ed JH |
211 | fprintf (f, "\n"); |
212 | } | |
213 | ||
214 | /* Dump the variable pool. */ | |
215 | void | |
216 | dump_varpool (FILE *f) | |
217 | { | |
2c8326a5 | 218 | varpool_node *node; |
8a4a83ed JH |
219 | |
220 | fprintf (f, "variable pool:\n\n"); | |
65c70e6b | 221 | FOR_EACH_VARIABLE (node) |
8a4a83ed JH |
222 | dump_varpool_node (f, node); |
223 | } | |
224 | ||
d85478c2 RAE |
225 | /* Dump the variable pool to stderr. */ |
226 | ||
24e47c76 | 227 | DEBUG_FUNCTION void |
d85478c2 RAE |
228 | debug_varpool (void) |
229 | { | |
230 | dump_varpool (stderr); | |
231 | } | |
232 | ||
8a4a83ed | 233 | /* Given an assembler name, lookup node. */ |
2c8326a5 | 234 | varpool_node * |
8a4a83ed JH |
235 | varpool_node_for_asm (tree asmname) |
236 | { | |
5e20cdc9 | 237 | if (symtab_node *node = symtab_node_for_asm (asmname)) |
e70670cf JH |
238 | return dyn_cast <varpool_node> (node); |
239 | else | |
240 | return NULL; | |
8a4a83ed JH |
241 | } |
242 | ||
64e0f5ff | 243 | /* Return if DECL is constant and its initial value is known (so we can do |
6a6dac52 JH |
244 | constant folding using DECL_INITIAL (decl)). |
245 | Return ERROR_MARK_NODE when value is unknown. */ | |
155c92a7 | 246 | |
6a6dac52 JH |
247 | tree |
248 | ctor_for_folding (tree decl) | |
155c92a7 | 249 | { |
2c8326a5 | 250 | varpool_node *node, *real_node; |
6a6dac52 JH |
251 | tree real_decl; |
252 | ||
1d0804d4 | 253 | if (TREE_CODE (decl) != VAR_DECL |
6a6dac52 JH |
254 | && TREE_CODE (decl) != CONST_DECL) |
255 | return error_mark_node; | |
64e0f5ff JH |
256 | |
257 | if (TREE_CODE (decl) == CONST_DECL | |
258 | || DECL_IN_CONSTANT_POOL (decl)) | |
6a6dac52 | 259 | return DECL_INITIAL (decl); |
64e0f5ff | 260 | |
6a6dac52 JH |
261 | if (TREE_THIS_VOLATILE (decl)) |
262 | return error_mark_node; | |
64e0f5ff | 263 | |
6a6dac52 JH |
264 | /* Do not care about automatic variables. Those are never initialized |
265 | anyway, because gimplifier exapnds the code*/ | |
64e0f5ff | 266 | if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) |
6a6dac52 JH |
267 | { |
268 | gcc_assert (!TREE_PUBLIC (decl)); | |
269 | return error_mark_node; | |
270 | } | |
64e0f5ff | 271 | |
6a6dac52 JH |
272 | gcc_assert (TREE_CODE (decl) == VAR_DECL); |
273 | ||
274 | node = varpool_get_node (decl); | |
275 | if (node) | |
276 | { | |
277 | real_node = varpool_variable_node (node); | |
67348ccc | 278 | real_decl = real_node->decl; |
6a6dac52 JH |
279 | } |
280 | else | |
281 | real_decl = decl; | |
282 | ||
283 | /* See if we are dealing with alias. | |
284 | In most cases alias is just alternative symbol pointing to a given | |
285 | constructor. This allows us to use interposition rules of DECL | |
286 | constructor of REAL_NODE. However weakrefs are special by being just | |
287 | alternative name of their target (if defined). */ | |
288 | if (decl != real_decl) | |
289 | { | |
290 | gcc_assert (!DECL_INITIAL (decl) | |
291 | || DECL_INITIAL (decl) == error_mark_node); | |
292 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) | |
293 | { | |
294 | node = varpool_alias_target (node); | |
67348ccc | 295 | decl = node->decl; |
6a6dac52 JH |
296 | } |
297 | } | |
298 | ||
299 | /* Vtables are defined by their types and must match no matter of interposition | |
300 | rules. */ | |
301 | if (DECL_VIRTUAL_P (real_decl)) | |
302 | { | |
303 | gcc_checking_assert (TREE_READONLY (real_decl)); | |
304 | return DECL_INITIAL (real_decl); | |
305 | } | |
306 | ||
6d0b7105 | 307 | /* If there is no constructor, we have nothing to do. */ |
6a6dac52 JH |
308 | if (DECL_INITIAL (real_decl) == error_mark_node) |
309 | return error_mark_node; | |
310 | ||
311 | /* Non-readonly alias of readonly variable is also de-facto readonly, | |
312 | because the variable itself is in readonly section. | |
313 | We also honnor READONLY flag on alias assuming that user knows | |
314 | what he is doing. */ | |
315 | if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl)) | |
316 | return error_mark_node; | |
64e0f5ff | 317 | |
155c92a7 JH |
318 | /* Variables declared 'const' without an initializer |
319 | have zero as the initializer if they may not be | |
320 | overridden at link or run time. */ | |
6a6dac52 JH |
321 | if (!DECL_INITIAL (real_decl) |
322 | && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl))) | |
323 | return error_mark_node; | |
155c92a7 JH |
324 | |
325 | /* Variables declared `const' with an initializer are considered | |
326 | to not be overwritable with different initializer by default. | |
327 | ||
328 | ??? Previously we behaved so for scalar variables but not for array | |
329 | accesses. */ | |
6a6dac52 | 330 | return DECL_INITIAL (real_decl); |
155c92a7 JH |
331 | } |
332 | ||
38877e98 ZM |
333 | /* Add the variable DECL to the varpool. |
334 | Unlike varpool_finalize_decl function is intended to be used | |
335 | by middle end and allows insertion of new variable at arbitrary point | |
336 | of compilation. */ | |
337 | void | |
338 | varpool_add_new_variable (tree decl) | |
339 | { | |
2c8326a5 | 340 | varpool_node *node; |
38877e98 | 341 | varpool_finalize_decl (decl); |
5d59b5e1 | 342 | node = varpool_node_for_decl (decl); |
26e5b0fd | 343 | varpool_call_variable_insertion_hooks (node); |
5ac42672 | 344 | if (varpool_externally_visible_p (node)) |
67348ccc | 345 | node->externally_visible = true; |
38877e98 ZM |
346 | } |
347 | ||
8a4a83ed JH |
348 | /* Return variable availability. See cgraph.h for description of individual |
349 | return values. */ | |
350 | enum availability | |
2c8326a5 | 351 | cgraph_variable_initializer_availability (varpool_node *node) |
8a4a83ed JH |
352 | { |
353 | gcc_assert (cgraph_function_flags_ready); | |
67348ccc | 354 | if (!node->definition) |
8a4a83ed | 355 | return AVAIL_NOT_AVAILABLE; |
67348ccc | 356 | if (!TREE_PUBLIC (node->decl)) |
8a4a83ed | 357 | return AVAIL_AVAILABLE; |
67348ccc DM |
358 | if (DECL_IN_CONSTANT_POOL (node->decl) |
359 | || DECL_VIRTUAL_P (node->decl)) | |
8a41354f | 360 | return AVAIL_AVAILABLE; |
67348ccc | 361 | if (node->alias && node->weakref) |
8a41354f JH |
362 | { |
363 | enum availability avail; | |
364 | ||
365 | cgraph_variable_initializer_availability | |
366 | (varpool_variable_node (node, &avail)); | |
367 | return avail; | |
368 | } | |
8a4a83ed | 369 | /* If the variable can be overwritten, return OVERWRITABLE. Takes |
e70670cf | 370 | care of at least one notable extension - the COMDAT variables |
8a4a83ed | 371 | used to share template instantiations in C++. */ |
67348ccc DM |
372 | if (decl_replaceable_p (node->decl) |
373 | || DECL_EXTERNAL (node->decl)) | |
8a4a83ed JH |
374 | return AVAIL_OVERWRITABLE; |
375 | return AVAIL_AVAILABLE; | |
376 | } | |
377 | ||
66058468 | 378 | void |
2c8326a5 | 379 | varpool_analyze_node (varpool_node *node) |
8a4a83ed | 380 | { |
67348ccc | 381 | tree decl = node->decl; |
8a4a83ed | 382 | |
66058468 JH |
383 | /* When reading back varpool at LTO time, we re-construct the queue in order |
384 | to have "needed" list right by inserting all needed nodes into varpool. | |
385 | We however don't want to re-analyze already analyzed nodes. */ | |
67348ccc | 386 | if (!node->analyzed) |
8a4a83ed | 387 | { |
66058468 JH |
388 | gcc_assert (!in_lto_p || cgraph_function_flags_ready); |
389 | /* Compute the alignment early so function body expanders are | |
390 | already informed about increased alignment. */ | |
391 | align_variable (decl, 0); | |
392 | } | |
67348ccc | 393 | if (node->alias) |
40a7fe1e | 394 | symtab_resolve_alias |
67348ccc | 395 | (node, varpool_get_node (node->alias_target)); |
66058468 | 396 | else if (DECL_INITIAL (decl)) |
67348ccc DM |
397 | record_references_in_initializer (decl, node->analyzed); |
398 | node->analyzed = true; | |
8a4a83ed JH |
399 | } |
400 | ||
073a8998 | 401 | /* Assemble thunks and aliases associated to NODE. */ |
cd35bcf7 JH |
402 | |
403 | static void | |
2c8326a5 | 404 | assemble_aliases (varpool_node *node) |
cd35bcf7 JH |
405 | { |
406 | int i; | |
407 | struct ipa_ref *ref; | |
67348ccc | 408 | for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) |
cd35bcf7 JH |
409 | if (ref->use == IPA_REF_ALIAS) |
410 | { | |
2c8326a5 | 411 | varpool_node *alias = ipa_ref_referring_varpool_node (ref); |
67348ccc DM |
412 | do_assemble_alias (alias->decl, |
413 | DECL_ASSEMBLER_NAME (node->decl)); | |
cd35bcf7 JH |
414 | assemble_aliases (alias); |
415 | } | |
416 | } | |
417 | ||
8a4a83ed | 418 | /* Output one variable, if necessary. Return whether we output it. */ |
0d6bf48c | 419 | |
8a4a83ed | 420 | bool |
2c8326a5 | 421 | varpool_assemble_decl (varpool_node *node) |
8a4a83ed | 422 | { |
67348ccc | 423 | tree decl = node->decl; |
8a4a83ed | 424 | |
0d6bf48c JH |
425 | /* Aliases are outout when their target is produced or by |
426 | output_weakrefs. */ | |
67348ccc | 427 | if (node->alias) |
0d6bf48c JH |
428 | return false; |
429 | ||
430 | /* Constant pool is output from RTL land when the reference | |
431 | survive till this level. */ | |
8fc17ddc | 432 | if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl)) |
0d6bf48c JH |
433 | return false; |
434 | ||
435 | /* Decls with VALUE_EXPR should not be in the varpool at all. They | |
436 | are not real variables, but just info for debugging and codegen. | |
437 | Unfortunately at the moment emutls is not updating varpool correctly | |
438 | after turning real vars into value_expr vars. */ | |
439 | if (DECL_HAS_VALUE_EXPR_P (decl) | |
440 | && !targetm.have_tls) | |
441 | return false; | |
442 | ||
b5493fb2 JH |
443 | /* Hard register vars do not need to be output. */ |
444 | if (DECL_HARD_REGISTER (decl)) | |
445 | return false; | |
446 | ||
0d6bf48c JH |
447 | gcc_checking_assert (!TREE_ASM_WRITTEN (decl) |
448 | && TREE_CODE (decl) == VAR_DECL | |
449 | && !DECL_HAS_VALUE_EXPR_P (decl)); | |
450 | ||
67348ccc | 451 | if (!node->in_other_partition |
0d6bf48c | 452 | && !DECL_EXTERNAL (decl)) |
8a4a83ed JH |
453 | { |
454 | assemble_variable (decl, 0, 1, 0); | |
0d6bf48c | 455 | gcc_assert (TREE_ASM_WRITTEN (decl)); |
67348ccc | 456 | node->definition = true; |
0d6bf48c JH |
457 | assemble_aliases (node); |
458 | return true; | |
8a4a83ed JH |
459 | } |
460 | ||
461 | return false; | |
462 | } | |
463 | ||
66058468 JH |
464 | /* Add NODE to queue starting at FIRST. |
465 | The queue is linked via AUX pointers and terminated by pointer to 1. */ | |
466 | ||
467 | static void | |
2c8326a5 | 468 | enqueue_node (varpool_node *node, varpool_node **first) |
66058468 | 469 | { |
67348ccc | 470 | if (node->aux) |
66058468 JH |
471 | return; |
472 | gcc_checking_assert (*first); | |
67348ccc | 473 | node->aux = *first; |
66058468 JH |
474 | *first = node; |
475 | } | |
476 | ||
8a4a83ed | 477 | /* Optimization of function bodies might've rendered some variables as |
66058468 JH |
478 | unnecessary so we want to avoid these from being compiled. Re-do |
479 | reachability starting from variables that are either externally visible | |
480 | or was referred from the asm output routines. */ | |
8a4a83ed | 481 | |
65d630d4 | 482 | static void |
8a4a83ed JH |
483 | varpool_remove_unreferenced_decls (void) |
484 | { | |
2c8326a5 OE |
485 | varpool_node *next, *node; |
486 | varpool_node *first = (varpool_node *)(void *)1; | |
66058468 JH |
487 | int i; |
488 | struct ipa_ref *ref; | |
8a4a83ed | 489 | |
1da2ed5f | 490 | if (seen_error ()) |
8a4a83ed JH |
491 | return; |
492 | ||
66058468 JH |
493 | if (cgraph_dump_file) |
494 | fprintf (cgraph_dump_file, "Trivially needed variables:"); | |
66058468 | 495 | FOR_EACH_DEFINED_VARIABLE (node) |
8a4a83ed | 496 | { |
67348ccc | 497 | if (node->analyzed |
df7705b1 JH |
498 | && (!varpool_can_remove_if_no_refs (node) |
499 | /* We just expanded all function bodies. See if any of | |
500 | them needed the variable. */ | |
67348ccc | 501 | || DECL_RTL_SET_P (node->decl))) |
66058468 JH |
502 | { |
503 | enqueue_node (node, &first); | |
504 | if (cgraph_dump_file) | |
fec39fa6 | 505 | fprintf (cgraph_dump_file, " %s", node->asm_name ()); |
66058468 JH |
506 | } |
507 | } | |
2c8326a5 | 508 | while (first != (varpool_node *)(void *)1) |
66058468 JH |
509 | { |
510 | node = first; | |
2c8326a5 | 511 | first = (varpool_node *)first->aux; |
8a4a83ed | 512 | |
67348ccc | 513 | if (node->same_comdat_group) |
66058468 | 514 | { |
5e20cdc9 | 515 | symtab_node *next; |
67348ccc DM |
516 | for (next = node->same_comdat_group; |
517 | next != node; | |
518 | next = next->same_comdat_group) | |
5d59b5e1 LC |
519 | { |
520 | varpool_node *vnext = dyn_cast <varpool_node> (next); | |
67348ccc | 521 | if (vnext && vnext->analyzed) |
5d59b5e1 LC |
522 | enqueue_node (vnext, &first); |
523 | } | |
66058468 | 524 | } |
67348ccc | 525 | for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) |
5d59b5e1 LC |
526 | { |
527 | varpool_node *vnode = dyn_cast <varpool_node> (ref->referred); | |
528 | if (vnode | |
67348ccc DM |
529 | && (!DECL_EXTERNAL (ref->referred->decl) |
530 | || vnode->alias) | |
531 | && vnode->analyzed) | |
5d59b5e1 LC |
532 | enqueue_node (vnode, &first); |
533 | } | |
8a4a83ed | 534 | } |
66058468 JH |
535 | if (cgraph_dump_file) |
536 | fprintf (cgraph_dump_file, "\nRemoving variables:"); | |
537 | for (node = varpool_first_defined_variable (); node; node = next) | |
538 | { | |
539 | next = varpool_next_defined_variable (node); | |
67348ccc | 540 | if (!node->aux) |
66058468 JH |
541 | { |
542 | if (cgraph_dump_file) | |
fec39fa6 | 543 | fprintf (cgraph_dump_file, " %s", node->asm_name ()); |
66058468 JH |
544 | varpool_remove_node (node); |
545 | } | |
546 | } | |
547 | if (cgraph_dump_file) | |
548 | fprintf (cgraph_dump_file, "\n"); | |
8a4a83ed JH |
549 | } |
550 | ||
7fece979 JJ |
551 | /* For variables in named sections make sure get_variable_section |
552 | is called before we switch to those sections. Then section | |
553 | conflicts between read-only and read-only requiring relocations | |
554 | sections can be resolved. */ | |
555 | void | |
2c8326a5 | 556 | varpool_finalize_named_section_flags (varpool_node *node) |
7fece979 | 557 | { |
67348ccc DM |
558 | if (!TREE_ASM_WRITTEN (node->decl) |
559 | && !node->alias | |
560 | && !node->in_other_partition | |
561 | && !DECL_EXTERNAL (node->decl) | |
562 | && TREE_CODE (node->decl) == VAR_DECL | |
563 | && !DECL_HAS_VALUE_EXPR_P (node->decl) | |
564 | && DECL_SECTION_NAME (node->decl)) | |
565 | get_variable_section (node->decl, false); | |
7fece979 JJ |
566 | } |
567 | ||
8a4a83ed JH |
568 | /* Output all variables enqueued to be assembled. */ |
569 | bool | |
65d630d4 | 570 | varpool_output_variables (void) |
8a4a83ed JH |
571 | { |
572 | bool changed = false; | |
2c8326a5 | 573 | varpool_node *node; |
8a4a83ed | 574 | |
1da2ed5f | 575 | if (seen_error ()) |
8a4a83ed JH |
576 | return false; |
577 | ||
65d630d4 JH |
578 | varpool_remove_unreferenced_decls (); |
579 | ||
49ba8180 | 580 | timevar_push (TV_VAROUT); |
8a4a83ed | 581 | |
65c70e6b | 582 | FOR_EACH_DEFINED_VARIABLE (node) |
7fece979 JJ |
583 | varpool_finalize_named_section_flags (node); |
584 | ||
66058468 JH |
585 | FOR_EACH_DEFINED_VARIABLE (node) |
586 | if (varpool_assemble_decl (node)) | |
587 | changed = true; | |
49ba8180 | 588 | timevar_pop (TV_VAROUT); |
8a4a83ed JH |
589 | return changed; |
590 | } | |
591 | ||
43d861a5 RL |
592 | /* Create a new global variable of type TYPE. */ |
593 | tree | |
594 | add_new_static_var (tree type) | |
595 | { | |
596 | tree new_decl; | |
2c8326a5 | 597 | varpool_node *new_node; |
43d861a5 | 598 | |
a502e677 | 599 | new_decl = create_tmp_var_raw (type, NULL); |
43d861a5 RL |
600 | DECL_NAME (new_decl) = create_tmp_var_name (NULL); |
601 | TREE_READONLY (new_decl) = 0; | |
602 | TREE_STATIC (new_decl) = 1; | |
603 | TREE_USED (new_decl) = 1; | |
604 | DECL_CONTEXT (new_decl) = NULL_TREE; | |
605 | DECL_ABSTRACT (new_decl) = 0; | |
606 | lang_hooks.dup_lang_specific_decl (new_decl); | |
5d59b5e1 | 607 | new_node = varpool_node_for_decl (new_decl); |
43d861a5 RL |
608 | varpool_finalize_decl (new_decl); |
609 | ||
67348ccc | 610 | return new_node->decl; |
43d861a5 RL |
611 | } |
612 | ||
2c71ac78 JM |
613 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
614 | Extra name aliases are output whenever DECL is output. */ | |
615 | ||
2c8326a5 | 616 | varpool_node * |
cd35bcf7 | 617 | varpool_create_variable_alias (tree alias, tree decl) |
2c71ac78 | 618 | { |
2c8326a5 | 619 | varpool_node *alias_node; |
2c71ac78 JM |
620 | |
621 | gcc_assert (TREE_CODE (decl) == VAR_DECL); | |
622 | gcc_assert (TREE_CODE (alias) == VAR_DECL); | |
5d59b5e1 | 623 | alias_node = varpool_node_for_decl (alias); |
67348ccc DM |
624 | alias_node->alias = true; |
625 | alias_node->definition = true; | |
626 | alias_node->alias_target = decl; | |
08346abd | 627 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) |
67348ccc | 628 | alias_node->weakref = true; |
cd35bcf7 JH |
629 | return alias_node; |
630 | } | |
2c71ac78 | 631 | |
cd35bcf7 JH |
632 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
633 | Extra name aliases are output whenever DECL is output. */ | |
2c71ac78 | 634 | |
2c8326a5 | 635 | varpool_node * |
cd35bcf7 JH |
636 | varpool_extra_name_alias (tree alias, tree decl) |
637 | { | |
2c8326a5 | 638 | varpool_node *alias_node; |
2c71ac78 | 639 | |
cd35bcf7 JH |
640 | #ifndef ASM_OUTPUT_DEF |
641 | /* If aliases aren't supported by the assembler, fail. */ | |
642 | return NULL; | |
643 | #endif | |
644 | alias_node = varpool_create_variable_alias (alias, decl); | |
67348ccc | 645 | alias_node->cpp_implicit_alias = true; |
40a7fe1e JH |
646 | |
647 | /* Extra name alias mechanizm creates aliases really late | |
648 | via DECL_ASSEMBLER_NAME mechanizm. | |
649 | This is unfortunate because they are not going through the | |
650 | standard channels. Ensure they get output. */ | |
651 | if (cpp_implicit_aliases_done) | |
67348ccc DM |
652 | symtab_resolve_alias (alias_node, |
653 | varpool_node_for_decl (decl)); | |
051f8cc6 JH |
654 | return alias_node; |
655 | } | |
656 | ||
073a8998 | 657 | /* Call calback on NODE and aliases associated to NODE. |
cd35bcf7 JH |
658 | When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are |
659 | skipped. */ | |
660 | ||
661 | bool | |
2c8326a5 OE |
662 | varpool_for_node_and_aliases (varpool_node *node, |
663 | bool (*callback) (varpool_node *, void *), | |
cd35bcf7 JH |
664 | void *data, |
665 | bool include_overwritable) | |
666 | { | |
667 | int i; | |
668 | struct ipa_ref *ref; | |
669 | ||
670 | if (callback (node, data)) | |
671 | return true; | |
67348ccc | 672 | for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) |
cd35bcf7 JH |
673 | if (ref->use == IPA_REF_ALIAS) |
674 | { | |
2c8326a5 | 675 | varpool_node *alias = ipa_ref_referring_varpool_node (ref); |
cd35bcf7 JH |
676 | if (include_overwritable |
677 | || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) | |
678 | if (varpool_for_node_and_aliases (alias, callback, data, | |
679 | include_overwritable)) | |
680 | return true; | |
681 | } | |
682 | return false; | |
683 | } |