]>
Commit | Line | Data |
---|---|---|
8a4a83ed | 1 | /* Callgraph handling code. |
d1e082c2 | 2 | Copyright (C) 2003-2013 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" | |
26 | #include "cgraph.h" | |
27 | #include "langhooks.h" | |
1da2ed5f | 28 | #include "diagnostic-core.h" |
8a4a83ed JH |
29 | #include "hashtab.h" |
30 | #include "ggc.h" | |
31 | #include "timevar.h" | |
b8698a0f | 32 | #include "debug.h" |
8a4a83ed JH |
33 | #include "target.h" |
34 | #include "output.h" | |
726a989a | 35 | #include "gimple.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 | |
81 | varpool_call_node_removal_hooks (struct varpool_node *node) | |
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 | |
122 | varpool_call_variable_insertion_hooks (struct varpool_node *node) | |
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 | ||
134 | struct varpool_node * | |
135 | varpool_create_empty_node (void) | |
136 | { | |
137 | struct varpool_node *node = ggc_alloc_cleared_varpool_node (); | |
138 | node->symbol.type = SYMTAB_VARIABLE; | |
139 | return node; | |
140 | } | |
141 | ||
8a4a83ed JH |
142 | /* Return varpool node assigned to DECL. Create new one when needed. */ |
143 | struct varpool_node * | |
5d59b5e1 | 144 | varpool_node_for_decl (tree decl) |
8a4a83ed | 145 | { |
1ab24192 | 146 | struct 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 (); |
960bfb69 | 152 | node->symbol.decl = decl; |
2aae7680 | 153 | symtab_register_node ((symtab_node)node); |
8a4a83ed JH |
154 | return node; |
155 | } | |
156 | ||
2942c502 JH |
157 | /* Remove node from the varpool. */ |
158 | void | |
159 | varpool_remove_node (struct varpool_node *node) | |
160 | { | |
6a6dac52 | 161 | tree init; |
26e5b0fd JH |
162 | varpool_call_node_removal_hooks (node); |
163 | symtab_unregister_node ((symtab_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. */ | |
6a6dac52 | 168 | if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node) |
e70670cf | 169 | varpool_remove_initializer (node); |
6a6dac52 JH |
170 | else |
171 | DECL_INITIAL (node->symbol.decl) = init; | |
e70670cf JH |
172 | ggc_free (node); |
173 | } | |
174 | ||
175 | /* Renove node initializer when it is no longer needed. */ | |
176 | void | |
177 | varpool_remove_initializer (struct varpool_node *node) | |
178 | { | |
6649df51 JH |
179 | if (DECL_INITIAL (node->symbol.decl) |
180 | && !DECL_IN_CONSTANT_POOL (node->symbol.decl) | |
181 | /* Keep vtables for BINFO folding. */ | |
182 | && !DECL_VIRTUAL_P (node->symbol.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) | |
6649df51 | 190 | DECL_INITIAL (node->symbol.decl) = error_mark_node; |
2942c502 JH |
191 | } |
192 | ||
8a4a83ed JH |
193 | /* Dump given cgraph node. */ |
194 | void | |
195 | dump_varpool_node (FILE *f, struct varpool_node *node) | |
196 | { | |
8f940ee6 JH |
197 | dump_symtab_base (f, (symtab_node)node); |
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:"); |
960bfb69 | 203 | if (DECL_INITIAL (node->symbol.decl)) |
8a4a83ed | 204 | fprintf (f, " initialized"); |
8a4a83ed JH |
205 | if (node->output) |
206 | fprintf (f, " output"); | |
2d6e4603 JH |
207 | if (TREE_READONLY (node->symbol.decl)) |
208 | fprintf (f, " read-only"); | |
6a6dac52 | 209 | if (ctor_for_folding (node->symbol.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 | { | |
218 | struct varpool_node *node; | |
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 JH |
233 | /* Given an assembler name, lookup node. */ |
234 | struct varpool_node * | |
235 | varpool_node_for_asm (tree asmname) | |
236 | { | |
5d59b5e1 | 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 | { |
6a6dac52 JH |
250 | struct varpool_node *node, *real_node; |
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); | |
278 | real_decl = real_node->symbol.decl; | |
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); | |
295 | decl = node->symbol.decl; | |
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 | ||
307 | /* If thre is no constructor, we have nothing to do. */ | |
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 | { | |
340 | struct varpool_node *node; | |
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)) |
960bfb69 | 345 | node->symbol.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 | |
351 | cgraph_variable_initializer_availability (struct varpool_node *node) | |
352 | { | |
353 | gcc_assert (cgraph_function_flags_ready); | |
e70670cf | 354 | if (!node->symbol.definition) |
8a4a83ed | 355 | return AVAIL_NOT_AVAILABLE; |
960bfb69 | 356 | if (!TREE_PUBLIC (node->symbol.decl)) |
8a4a83ed | 357 | return AVAIL_AVAILABLE; |
8a41354f JH |
358 | if (DECL_IN_CONSTANT_POOL (node->symbol.decl) |
359 | || DECL_VIRTUAL_P (node->symbol.decl)) | |
360 | return AVAIL_AVAILABLE; | |
361 | if (node->symbol.alias && node->symbol.weakref) | |
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++. */ |
8a41354f JH |
372 | if (decl_replaceable_p (node->symbol.decl) |
373 | || DECL_EXTERNAL (node->symbol.decl)) | |
8a4a83ed JH |
374 | return AVAIL_OVERWRITABLE; |
375 | return AVAIL_AVAILABLE; | |
376 | } | |
377 | ||
66058468 JH |
378 | void |
379 | varpool_analyze_node (struct varpool_node *node) | |
8a4a83ed | 380 | { |
66058468 | 381 | tree decl = node->symbol.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. */ | |
e70670cf | 386 | if (!node->symbol.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 | } | |
40a7fe1e JH |
393 | if (node->symbol.alias) |
394 | symtab_resolve_alias | |
395 | ((symtab_node) node, (symtab_node) varpool_get_node (node->symbol.alias_target)); | |
66058468 | 396 | else if (DECL_INITIAL (decl)) |
e70670cf JH |
397 | record_references_in_initializer (decl, node->symbol.analyzed); |
398 | node->symbol.analyzed = true; | |
8a4a83ed JH |
399 | } |
400 | ||
073a8998 | 401 | /* Assemble thunks and aliases associated to NODE. */ |
cd35bcf7 JH |
402 | |
403 | static void | |
404 | assemble_aliases (struct varpool_node *node) | |
405 | { | |
406 | int i; | |
407 | struct ipa_ref *ref; | |
5932a4d4 | 408 | for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) |
cd35bcf7 JH |
409 | if (ref->use == IPA_REF_ALIAS) |
410 | { | |
5932a4d4 | 411 | struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); |
07250f0e | 412 | do_assemble_alias (alias->symbol.decl, |
40a7fe1e | 413 | DECL_ASSEMBLER_NAME (node->symbol.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 JH |
420 | bool |
421 | varpool_assemble_decl (struct varpool_node *node) | |
422 | { | |
960bfb69 | 423 | tree decl = node->symbol.decl; |
8a4a83ed | 424 | |
0d6bf48c JH |
425 | /* Aliases are outout when their target is produced or by |
426 | output_weakrefs. */ | |
e70670cf | 427 | if (node->symbol.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 | ||
451 | if (!node->symbol.in_other_partition | |
452 | && !DECL_EXTERNAL (decl)) | |
8a4a83ed JH |
453 | { |
454 | assemble_variable (decl, 0, 1, 0); | |
0d6bf48c | 455 | gcc_assert (TREE_ASM_WRITTEN (decl)); |
e70670cf | 456 | node->symbol.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 | |
468 | enqueue_node (struct varpool_node *node, struct varpool_node **first) | |
469 | { | |
470 | if (node->symbol.aux) | |
471 | return; | |
472 | gcc_checking_assert (*first); | |
473 | node->symbol.aux = *first; | |
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 | { | |
66058468 JH |
485 | struct varpool_node *next, *node; |
486 | struct varpool_node *first = (struct varpool_node *)(void *)1; | |
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 | { |
e70670cf | 497 | if (node->symbol.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. */ | |
3deafb32 | 501 | || DECL_RTL_SET_P (node->symbol.decl))) |
66058468 JH |
502 | { |
503 | enqueue_node (node, &first); | |
504 | if (cgraph_dump_file) | |
505 | fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); | |
506 | } | |
507 | } | |
508 | while (first != (struct varpool_node *)(void *)1) | |
509 | { | |
510 | node = first; | |
511 | first = (struct varpool_node *)first->symbol.aux; | |
8a4a83ed | 512 | |
66058468 JH |
513 | if (node->symbol.same_comdat_group) |
514 | { | |
515 | symtab_node next; | |
516 | for (next = node->symbol.same_comdat_group; | |
517 | next != (symtab_node)node; | |
518 | next = next->symbol.same_comdat_group) | |
5d59b5e1 LC |
519 | { |
520 | varpool_node *vnext = dyn_cast <varpool_node> (next); | |
e70670cf | 521 | if (vnext && vnext->symbol.analyzed) |
5d59b5e1 LC |
522 | enqueue_node (vnext, &first); |
523 | } | |
66058468 JH |
524 | } |
525 | for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) | |
5d59b5e1 LC |
526 | { |
527 | varpool_node *vnode = dyn_cast <varpool_node> (ref->referred); | |
528 | if (vnode | |
529 | && (!DECL_EXTERNAL (ref->referred->symbol.decl) | |
e70670cf JH |
530 | || vnode->symbol.alias) |
531 | && vnode->symbol.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); | |
540 | if (!node->symbol.aux) | |
541 | { | |
542 | if (cgraph_dump_file) | |
543 | fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); | |
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 | |
556 | varpool_finalize_named_section_flags (struct varpool_node *node) | |
557 | { | |
960bfb69 | 558 | if (!TREE_ASM_WRITTEN (node->symbol.decl) |
e70670cf | 559 | && !node->symbol.alias |
960bfb69 JH |
560 | && !node->symbol.in_other_partition |
561 | && !DECL_EXTERNAL (node->symbol.decl) | |
562 | && TREE_CODE (node->symbol.decl) == VAR_DECL | |
563 | && !DECL_HAS_VALUE_EXPR_P (node->symbol.decl) | |
564 | && DECL_SECTION_NAME (node->symbol.decl)) | |
565 | get_variable_section (node->symbol.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; | |
7fece979 | 573 | struct 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; | |
597 | struct varpool_node *new_node; | |
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 | ||
960bfb69 | 610 | return new_node->symbol.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 | ||
051f8cc6 | 616 | struct varpool_node * |
cd35bcf7 | 617 | varpool_create_variable_alias (tree alias, tree decl) |
2c71ac78 | 618 | { |
cd35bcf7 | 619 | struct 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); |
e70670cf JH |
624 | alias_node->symbol.alias = true; |
625 | alias_node->symbol.definition = true; | |
40a7fe1e | 626 | alias_node->symbol.alias_target = decl; |
08346abd JH |
627 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) |
628 | alias_node->symbol.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 | |
cd35bcf7 JH |
635 | struct varpool_node * |
636 | varpool_extra_name_alias (tree alias, tree decl) | |
637 | { | |
638 | struct 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); | |
40a7fe1e JH |
645 | alias_node->symbol.cpp_implicit_alias = true; |
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) | |
652 | symtab_resolve_alias ((symtab_node)alias_node, | |
653 | (symtab_node)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 | |
662 | varpool_for_node_and_aliases (struct varpool_node *node, | |
663 | bool (*callback) (struct varpool_node *, void *), | |
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; | |
5932a4d4 | 672 | for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) |
cd35bcf7 JH |
673 | if (ref->use == IPA_REF_ALIAS) |
674 | { | |
5932a4d4 | 675 | struct 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 | } |