]>
Commit | Line | Data |
---|---|---|
1d416bd7 | 1 | /* Callgraph handling code. |
d353bf18 | 2 | Copyright (C) 2003-2015 Free Software Foundation, Inc. |
1d416bd7 | 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 | |
8c4c00c1 | 9 | Software Foundation; either version 3, or (at your option) any later |
1d416bd7 | 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 | |
8c4c00c1 | 18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
1d416bd7 | 20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
b20a8bb4 | 25 | #include "alias.h" |
26 | #include "symtab.h" | |
1d416bd7 | 27 | #include "tree.h" |
b20a8bb4 | 28 | #include "fold-const.h" |
9ed99284 | 29 | #include "varasm.h" |
94ea8568 | 30 | #include "predict.h" |
31 | #include "basic-block.h" | |
1140c305 | 32 | #include "plugin-api.h" |
1140c305 | 33 | #include "hard-reg-set.h" |
1140c305 | 34 | #include "function.h" |
35 | #include "ipa-ref.h" | |
1d416bd7 | 36 | #include "cgraph.h" |
37 | #include "langhooks.h" | |
852f689e | 38 | #include "diagnostic-core.h" |
1d416bd7 | 39 | #include "timevar.h" |
48e1416a | 40 | #include "debug.h" |
1d416bd7 | 41 | #include "target.h" |
42 | #include "output.h" | |
bc61cadb | 43 | #include "gimple-expr.h" |
59dd4830 | 44 | #include "flags.h" |
afb0d513 | 45 | #include "tree-ssa-alias.h" |
46 | #include "gimple.h" | |
47 | #include "lto-streamer.h" | |
b0c5e347 | 48 | #include "context.h" |
dccabdd1 | 49 | #include "omp-low.h" |
1d416bd7 | 50 | |
8b741ed1 | 51 | const char * const tls_model_names[]={"none", "emulated", |
52 | "global-dynamic", "local-dynamic", | |
53 | "initial-exec", "local-exec"}; | |
b7393cee | 54 | |
332db80a | 55 | /* List of hooks triggered on varpool_node events. */ |
56 | struct varpool_node_hook_list { | |
57 | varpool_node_hook hook; | |
58 | void *data; | |
59 | struct varpool_node_hook_list *next; | |
60 | }; | |
61 | ||
332db80a | 62 | /* Register HOOK to be called with DATA on each removed node. */ |
35ee1c66 | 63 | varpool_node_hook_list * |
64 | symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data) | |
332db80a | 65 | { |
35ee1c66 | 66 | varpool_node_hook_list *entry; |
67 | varpool_node_hook_list **ptr = &m_first_varpool_removal_hook; | |
332db80a | 68 | |
35ee1c66 | 69 | entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry)); |
332db80a | 70 | entry->hook = hook; |
71 | entry->data = data; | |
72 | entry->next = NULL; | |
73 | while (*ptr) | |
74 | ptr = &(*ptr)->next; | |
75 | *ptr = entry; | |
76 | return entry; | |
77 | } | |
78 | ||
79 | /* Remove ENTRY from the list of hooks called on removing nodes. */ | |
80 | void | |
35ee1c66 | 81 | symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry) |
332db80a | 82 | { |
35ee1c66 | 83 | varpool_node_hook_list **ptr = &m_first_varpool_removal_hook; |
332db80a | 84 | |
85 | while (*ptr != entry) | |
86 | ptr = &(*ptr)->next; | |
87 | *ptr = entry->next; | |
88 | free (entry); | |
89 | } | |
90 | ||
91 | /* Call all node removal hooks. */ | |
35ee1c66 | 92 | void |
93 | symbol_table::call_varpool_removal_hooks (varpool_node *node) | |
332db80a | 94 | { |
35ee1c66 | 95 | varpool_node_hook_list *entry = m_first_varpool_removal_hook; |
332db80a | 96 | while (entry) |
97 | { | |
98 | entry->hook (node, entry->data); | |
99 | entry = entry->next; | |
100 | } | |
101 | } | |
102 | ||
103 | /* Register HOOK to be called with DATA on each inserted node. */ | |
35ee1c66 | 104 | varpool_node_hook_list * |
105 | symbol_table::add_varpool_insertion_hook (varpool_node_hook hook, void *data) | |
332db80a | 106 | { |
35ee1c66 | 107 | varpool_node_hook_list *entry; |
108 | varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook; | |
332db80a | 109 | |
35ee1c66 | 110 | entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry)); |
332db80a | 111 | entry->hook = hook; |
112 | entry->data = data; | |
113 | entry->next = NULL; | |
114 | while (*ptr) | |
115 | ptr = &(*ptr)->next; | |
116 | *ptr = entry; | |
117 | return entry; | |
118 | } | |
119 | ||
120 | /* Remove ENTRY from the list of hooks called on inserted nodes. */ | |
121 | void | |
35ee1c66 | 122 | symbol_table::remove_varpool_insertion_hook (varpool_node_hook_list *entry) |
332db80a | 123 | { |
35ee1c66 | 124 | varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook; |
332db80a | 125 | |
126 | while (*ptr != entry) | |
127 | ptr = &(*ptr)->next; | |
128 | *ptr = entry->next; | |
129 | free (entry); | |
130 | } | |
131 | ||
132 | /* Call all node insertion hooks. */ | |
133 | void | |
35ee1c66 | 134 | symbol_table::call_varpool_insertion_hooks (varpool_node *node) |
332db80a | 135 | { |
35ee1c66 | 136 | varpool_node_hook_list *entry = m_first_varpool_insertion_hook; |
332db80a | 137 | while (entry) |
138 | { | |
139 | entry->hook (node, entry->data); | |
140 | entry = entry->next; | |
141 | } | |
142 | } | |
143 | ||
9e9c3e92 | 144 | /* Allocate new callgraph node and insert it into basic data structures. */ |
145 | ||
098f44bc | 146 | varpool_node * |
97221fd7 | 147 | varpool_node::create_empty (void) |
9e9c3e92 | 148 | { |
25a27413 | 149 | varpool_node *node = ggc_cleared_alloc<varpool_node> (); |
02774f2d | 150 | node->type = SYMTAB_VARIABLE; |
9e9c3e92 | 151 | return node; |
152 | } | |
153 | ||
1d416bd7 | 154 | /* Return varpool node assigned to DECL. Create new one when needed. */ |
098f44bc | 155 | varpool_node * |
97221fd7 | 156 | varpool_node::get_create (tree decl) |
1d416bd7 | 157 | { |
97221fd7 | 158 | varpool_node *node = varpool_node::get (decl); |
9e9c3e92 | 159 | gcc_checking_assert (TREE_CODE (decl) == VAR_DECL); |
cfbe30aa | 160 | if (node) |
161 | return node; | |
1d416bd7 | 162 | |
97221fd7 | 163 | node = varpool_node::create_empty (); |
02774f2d | 164 | node->decl = decl; |
b0c5e347 | 165 | |
69409999 | 166 | if ((flag_openacc || flag_openmp) && !DECL_EXTERNAL (decl) |
b0c5e347 | 167 | && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))) |
168 | { | |
169 | node->offloadable = 1; | |
7114ebdd | 170 | #ifdef ENABLE_OFFLOADING |
b0c5e347 | 171 | g->have_offload = true; |
dccabdd1 | 172 | if (!in_lto_p) |
173 | vec_safe_push (offload_vars, decl); | |
67b75493 | 174 | node->force_output = 1; |
7114ebdd | 175 | #endif |
b0c5e347 | 176 | } |
177 | ||
415d1b9a | 178 | node->register_symbol (); |
1d416bd7 | 179 | return node; |
180 | } | |
181 | ||
415d1b9a | 182 | /* Remove variable from symbol table. */ |
183 | ||
0cddb138 | 184 | void |
415d1b9a | 185 | varpool_node::remove (void) |
0cddb138 | 186 | { |
35ee1c66 | 187 | symtab->call_varpool_removal_hooks (this); |
e9e2b82f | 188 | if (lto_file_data) |
189 | { | |
190 | lto_free_function_in_decl_state_for_node (this); | |
191 | lto_file_data = NULL; | |
192 | } | |
15ca8f90 | 193 | |
afb0d513 | 194 | /* When streaming we can have multiple nodes associated with decl. */ |
35ee1c66 | 195 | if (symtab->state == LTO_STREAMING) |
1a8f6e9c | 196 | ; |
afb0d513 | 197 | /* Keep constructor when it may be used for folding. We remove |
198 | references to external variables before final compilation. */ | |
415d1b9a | 199 | else if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node |
97221fd7 | 200 | && !ctor_useable_for_folding_p ()) |
201 | remove_initializer (); | |
a70a8c3a | 202 | |
203 | unregister (); | |
415d1b9a | 204 | ggc_free (this); |
15ca8f90 | 205 | } |
206 | ||
97221fd7 | 207 | /* Remove node initializer when it is no longer needed. */ |
15ca8f90 | 208 | void |
97221fd7 | 209 | varpool_node::remove_initializer (void) |
15ca8f90 | 210 | { |
97221fd7 | 211 | if (DECL_INITIAL (decl) |
212 | && !DECL_IN_CONSTANT_POOL (decl) | |
aa419a52 | 213 | /* Keep vtables for BINFO folding. */ |
97221fd7 | 214 | && !DECL_VIRTUAL_P (decl) |
dc6f13e3 | 215 | /* FIXME: http://gcc.gnu.org/PR55395 */ |
8ceff600 | 216 | && debug_info_level == DINFO_LEVEL_NONE |
217 | /* When doing declaration merging we have duplicate | |
218 | entries for given decl. Do not attempt to remove | |
219 | the boides, or we will end up remiving | |
220 | wrong one. */ | |
35ee1c66 | 221 | && symtab->state != LTO_STREAMING) |
97221fd7 | 222 | DECL_INITIAL (decl) = error_mark_node; |
0cddb138 | 223 | } |
224 | ||
97221fd7 | 225 | /* Dump given varpool node to F. */ |
1d416bd7 | 226 | void |
415d1b9a | 227 | varpool_node::dump (FILE *f) |
1d416bd7 | 228 | { |
415d1b9a | 229 | dump_base (f); |
18841b0c | 230 | fprintf (f, " Availability: %s\n", |
35ee1c66 | 231 | symtab->function_flags_ready |
97221fd7 | 232 | ? cgraph_availability_names[get_availability ()] |
1d416bd7 | 233 | : "not-ready"); |
18841b0c | 234 | fprintf (f, " Varpool flags:"); |
415d1b9a | 235 | if (DECL_INITIAL (decl)) |
1d416bd7 | 236 | fprintf (f, " initialized"); |
415d1b9a | 237 | if (output) |
1d416bd7 | 238 | fprintf (f, " output"); |
415d1b9a | 239 | if (used_by_single_function) |
3f1f2be0 | 240 | fprintf (f, " used-by-single-function"); |
058a1b7a | 241 | if (need_bounds_init) |
242 | fprintf (f, " need-bounds-init"); | |
415d1b9a | 243 | if (TREE_READONLY (decl)) |
33864132 | 244 | fprintf (f, " read-only"); |
97221fd7 | 245 | if (ctor_useable_for_folding_p ()) |
33864132 | 246 | fprintf (f, " const-value-known"); |
415d1b9a | 247 | if (writeonly) |
703ad42c | 248 | fprintf (f, " write-only"); |
415d1b9a | 249 | if (tls_model) |
8b741ed1 | 250 | fprintf (f, " tls-%s", tls_model_names [tls_model]); |
1d416bd7 | 251 | fprintf (f, "\n"); |
252 | } | |
253 | ||
97221fd7 | 254 | |
255 | /* Dump given varpool node to stderr. */ | |
256 | void varpool_node::debug (void) | |
257 | { | |
258 | varpool_node::dump (stderr); | |
259 | } | |
260 | ||
415d1b9a | 261 | /* Dump the variable pool to F. */ |
1d416bd7 | 262 | void |
97221fd7 | 263 | varpool_node::dump_varpool (FILE *f) |
1d416bd7 | 264 | { |
098f44bc | 265 | varpool_node *node; |
1d416bd7 | 266 | |
267 | fprintf (f, "variable pool:\n\n"); | |
7c455d87 | 268 | FOR_EACH_VARIABLE (node) |
415d1b9a | 269 | node->dump (f); |
1d416bd7 | 270 | } |
271 | ||
64f3398b | 272 | /* Dump the variable pool to stderr. */ |
273 | ||
4b987fac | 274 | DEBUG_FUNCTION void |
97221fd7 | 275 | varpool_node::debug_varpool (void) |
64f3398b | 276 | { |
277 | dump_varpool (stderr); | |
278 | } | |
279 | ||
1d416bd7 | 280 | /* Given an assembler name, lookup node. */ |
098f44bc | 281 | varpool_node * |
97221fd7 | 282 | varpool_node::get_for_asmname (tree asmname) |
1d416bd7 | 283 | { |
35ee1c66 | 284 | if (symtab_node *node = symtab_node::get_for_asmname (asmname)) |
13cbeaac | 285 | return dyn_cast <varpool_node *> (node); |
15ca8f90 | 286 | else |
287 | return NULL; | |
1d416bd7 | 288 | } |
289 | ||
97221fd7 | 290 | /* When doing LTO, read variable's constructor from disk if |
291 | it is not already present. */ | |
afb0d513 | 292 | |
293 | tree | |
97221fd7 | 294 | varpool_node::get_constructor (void) |
afb0d513 | 295 | { |
35ee1c66 | 296 | lto_file_decl_data *file_data; |
afb0d513 | 297 | const char *data, *name; |
298 | size_t len; | |
afb0d513 | 299 | |
97221fd7 | 300 | if (DECL_INITIAL (decl) != error_mark_node |
00984d17 | 301 | || !in_lto_p |
302 | || !lto_file_data) | |
97221fd7 | 303 | return DECL_INITIAL (decl); |
afb0d513 | 304 | |
e52d4978 | 305 | timevar_push (TV_IPA_LTO_CTORS_IN); |
306 | ||
97221fd7 | 307 | file_data = lto_file_data; |
afb0d513 | 308 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
309 | ||
310 | /* We may have renamed the declaration, e.g., a static function. */ | |
311 | name = lto_get_decl_name_mapping (file_data, name); | |
312 | ||
313 | data = lto_get_section_data (file_data, LTO_section_function_body, | |
314 | name, &len); | |
315 | if (!data) | |
c05be867 | 316 | fatal_error (input_location, "%s: section %s is missing", |
afb0d513 | 317 | file_data->file_name, |
318 | name); | |
319 | ||
97221fd7 | 320 | lto_input_variable_constructor (file_data, this, data); |
e9e2b82f | 321 | gcc_assert (DECL_INITIAL (decl) != error_mark_node); |
afb0d513 | 322 | lto_stats.num_function_bodies++; |
323 | lto_free_section_data (file_data, LTO_section_function_body, name, | |
324 | data, len); | |
97221fd7 | 325 | lto_free_function_in_decl_state_for_node (this); |
e52d4978 | 326 | timevar_pop (TV_IPA_LTO_CTORS_IN); |
97221fd7 | 327 | return DECL_INITIAL (decl); |
afb0d513 | 328 | } |
329 | ||
97221fd7 | 330 | /* Return true if variable has constructor that can be used for folding. */ |
afb0d513 | 331 | |
332 | bool | |
97221fd7 | 333 | varpool_node::ctor_useable_for_folding_p (void) |
afb0d513 | 334 | { |
97221fd7 | 335 | varpool_node *real_node = this; |
afb0d513 | 336 | |
337 | if (real_node->alias && real_node->definition) | |
97221fd7 | 338 | real_node = ultimate_alias_target (); |
afb0d513 | 339 | |
97221fd7 | 340 | if (TREE_CODE (decl) == CONST_DECL |
341 | || DECL_IN_CONSTANT_POOL (decl)) | |
afb0d513 | 342 | return true; |
97221fd7 | 343 | if (TREE_THIS_VOLATILE (decl)) |
afb0d513 | 344 | return false; |
345 | ||
346 | /* If we do not have a constructor, we can't use it. */ | |
347 | if (DECL_INITIAL (real_node->decl) == error_mark_node | |
348 | && !real_node->lto_file_data) | |
349 | return false; | |
350 | ||
8640c571 | 351 | /* Avoid attempts to load constructors that was not streamed. */ |
352 | if (flag_ltrans && DECL_INITIAL (real_node->decl) == error_mark_node | |
353 | && real_node->body_removed) | |
354 | return false; | |
355 | ||
afb0d513 | 356 | /* Vtables are defined by their types and must match no matter of interposition |
357 | rules. */ | |
97221fd7 | 358 | if (DECL_VIRTUAL_P (decl)) |
afb0d513 | 359 | { |
360 | /* The C++ front end creates VAR_DECLs for vtables of typeinfo | |
361 | classes not defined in the current TU so that it can refer | |
362 | to them from typeinfo objects. Avoid returning NULL_TREE. */ | |
363 | return DECL_INITIAL (real_node->decl) != NULL; | |
364 | } | |
365 | ||
366 | /* Alias of readonly variable is also readonly, since the variable is stored | |
367 | in readonly memory. We also accept readonly aliases of non-readonly | |
368 | locations assuming that user knows what he is asking for. */ | |
97221fd7 | 369 | if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl)) |
afb0d513 | 370 | return false; |
371 | ||
372 | /* Variables declared 'const' without an initializer | |
373 | have zero as the initializer if they may not be | |
fb6c6e54 | 374 | overridden at link or run time. |
375 | ||
376 | It is actually requirement for C++ compiler to optimize const variables | |
377 | consistently. As a GNU extension, do not enfore this rule for user defined | |
378 | weak variables, so we support interposition on: | |
379 | static const int dummy = 0; | |
380 | extern const int foo __attribute__((__weak__, __alias__("dummy"))); | |
381 | */ | |
382 | if ((!DECL_INITIAL (real_node->decl) | |
383 | || (DECL_WEAK (decl) && !DECL_COMDAT (decl))) | |
97221fd7 | 384 | && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl))) |
afb0d513 | 385 | return false; |
386 | ||
387 | /* Variables declared `const' with an initializer are considered | |
388 | to not be overwritable with different initializer by default. | |
389 | ||
390 | ??? Previously we behaved so for scalar variables but not for array | |
391 | accesses. */ | |
392 | return true; | |
393 | } | |
394 | ||
97221fd7 | 395 | /* If DECLARATION is constant variable and its initial value is known |
396 | (so we can do constant folding), return its constructor (DECL_INITIAL). | |
397 | This may be an expression or NULL when DECL is initialized to 0. | |
afb0d513 | 398 | Return ERROR_MARK_NODE otherwise. |
399 | ||
400 | In LTO this may actually trigger reading the constructor from disk. | |
401 | For this reason varpool_ctor_useable_for_folding_p should be used when | |
402 | the actual constructor value is not needed. */ | |
9d924a14 | 403 | |
df8d3e89 | 404 | tree |
405 | ctor_for_folding (tree decl) | |
9d924a14 | 406 | { |
098f44bc | 407 | varpool_node *node, *real_node; |
df8d3e89 | 408 | tree real_decl; |
409 | ||
93b79643 | 410 | if (TREE_CODE (decl) != VAR_DECL |
df8d3e89 | 411 | && TREE_CODE (decl) != CONST_DECL) |
412 | return error_mark_node; | |
7ae8b539 | 413 | |
058a1b7a | 414 | /* Static constant bounds are created to be |
415 | used instead of constants and therefore | |
416 | do not let folding it. */ | |
417 | if (POINTER_BOUNDS_P (decl)) | |
418 | return error_mark_node; | |
419 | ||
7ae8b539 | 420 | if (TREE_CODE (decl) == CONST_DECL |
421 | || DECL_IN_CONSTANT_POOL (decl)) | |
df8d3e89 | 422 | return DECL_INITIAL (decl); |
7ae8b539 | 423 | |
df8d3e89 | 424 | if (TREE_THIS_VOLATILE (decl)) |
425 | return error_mark_node; | |
7ae8b539 | 426 | |
df8d3e89 | 427 | /* Do not care about automatic variables. Those are never initialized |
5c3e0e39 | 428 | anyway, because gimplifier exapnds the code. */ |
7ae8b539 | 429 | if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) |
df8d3e89 | 430 | { |
431 | gcc_assert (!TREE_PUBLIC (decl)); | |
432 | return error_mark_node; | |
433 | } | |
7ae8b539 | 434 | |
df8d3e89 | 435 | gcc_assert (TREE_CODE (decl) == VAR_DECL); |
436 | ||
97221fd7 | 437 | real_node = node = varpool_node::get (decl); |
df8d3e89 | 438 | if (node) |
439 | { | |
97221fd7 | 440 | real_node = node->ultimate_alias_target (); |
02774f2d | 441 | real_decl = real_node->decl; |
df8d3e89 | 442 | } |
443 | else | |
444 | real_decl = decl; | |
445 | ||
446 | /* See if we are dealing with alias. | |
447 | In most cases alias is just alternative symbol pointing to a given | |
448 | constructor. This allows us to use interposition rules of DECL | |
449 | constructor of REAL_NODE. However weakrefs are special by being just | |
450 | alternative name of their target (if defined). */ | |
451 | if (decl != real_decl) | |
452 | { | |
453 | gcc_assert (!DECL_INITIAL (decl) | |
09809ecc | 454 | || (node->alias && node->get_alias_target () == real_node) |
df8d3e89 | 455 | || DECL_INITIAL (decl) == error_mark_node); |
afb0d513 | 456 | if (node->weakref) |
df8d3e89 | 457 | { |
97221fd7 | 458 | node = node->get_alias_target (); |
02774f2d | 459 | decl = node->decl; |
df8d3e89 | 460 | } |
461 | } | |
462 | ||
afb0d513 | 463 | if ((!DECL_VIRTUAL_P (real_decl) |
464 | || DECL_INITIAL (real_decl) == error_mark_node | |
465 | || !DECL_INITIAL (real_decl)) | |
97221fd7 | 466 | && (!node || !node->ctor_useable_for_folding_p ())) |
df8d3e89 | 467 | return error_mark_node; |
9d924a14 | 468 | |
afb0d513 | 469 | /* OK, we can return constructor. See if we need to fetch it from disk |
470 | in LTO mode. */ | |
471 | if (DECL_INITIAL (real_decl) != error_mark_node | |
472 | || !in_lto_p) | |
473 | return DECL_INITIAL (real_decl); | |
97221fd7 | 474 | return real_node->get_constructor (); |
9d924a14 | 475 | } |
476 | ||
124f4875 | 477 | /* Add the variable DECL to the varpool. |
35ee1c66 | 478 | Unlike finalize_decl function is intended to be used |
124f4875 | 479 | by middle end and allows insertion of new variable at arbitrary point |
480 | of compilation. */ | |
481 | void | |
35ee1c66 | 482 | varpool_node::add (tree decl) |
124f4875 | 483 | { |
098f44bc | 484 | varpool_node *node; |
97221fd7 | 485 | varpool_node::finalize_decl (decl); |
486 | node = varpool_node::get_create (decl); | |
35ee1c66 | 487 | symtab->call_varpool_insertion_hooks (node); |
97221fd7 | 488 | if (node->externally_visible_p ()) |
02774f2d | 489 | node->externally_visible = true; |
10a29027 | 490 | if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl))) |
6b722052 | 491 | node->no_reorder = 1; |
124f4875 | 492 | } |
493 | ||
1d416bd7 | 494 | /* Return variable availability. See cgraph.h for description of individual |
495 | return values. */ | |
496 | enum availability | |
97221fd7 | 497 | varpool_node::get_availability (void) |
1d416bd7 | 498 | { |
97221fd7 | 499 | if (!definition) |
1d416bd7 | 500 | return AVAIL_NOT_AVAILABLE; |
97221fd7 | 501 | if (!TREE_PUBLIC (decl)) |
1d416bd7 | 502 | return AVAIL_AVAILABLE; |
97221fd7 | 503 | if (DECL_IN_CONSTANT_POOL (decl) |
504 | || DECL_VIRTUAL_P (decl)) | |
2fe870c5 | 505 | return AVAIL_AVAILABLE; |
97221fd7 | 506 | if (alias && weakref) |
2fe870c5 | 507 | { |
508 | enum availability avail; | |
509 | ||
97221fd7 | 510 | ultimate_alias_target (&avail)->get_availability (); |
2fe870c5 | 511 | return avail; |
512 | } | |
1d416bd7 | 513 | /* If the variable can be overwritten, return OVERWRITABLE. Takes |
15ca8f90 | 514 | care of at least one notable extension - the COMDAT variables |
1d416bd7 | 515 | used to share template instantiations in C++. */ |
97221fd7 | 516 | if (decl_replaceable_p (decl) |
517 | || DECL_EXTERNAL (decl)) | |
415d1b9a | 518 | return AVAIL_INTERPOSABLE; |
1d416bd7 | 519 | return AVAIL_AVAILABLE; |
520 | } | |
521 | ||
ff2a5ada | 522 | void |
97221fd7 | 523 | varpool_node::analyze (void) |
1d416bd7 | 524 | { |
ff2a5ada | 525 | /* When reading back varpool at LTO time, we re-construct the queue in order |
526 | to have "needed" list right by inserting all needed nodes into varpool. | |
527 | We however don't want to re-analyze already analyzed nodes. */ | |
97221fd7 | 528 | if (!analyzed) |
1d416bd7 | 529 | { |
35ee1c66 | 530 | gcc_assert (!in_lto_p || symtab->function_flags_ready); |
ff2a5ada | 531 | /* Compute the alignment early so function body expanders are |
532 | already informed about increased alignment. */ | |
533 | align_variable (decl, 0); | |
534 | } | |
97221fd7 | 535 | if (alias) |
536 | resolve_alias (varpool_node::get (alias_target)); | |
ff2a5ada | 537 | else if (DECL_INITIAL (decl)) |
97221fd7 | 538 | record_references_in_initializer (decl, analyzed); |
539 | analyzed = true; | |
1d416bd7 | 540 | } |
541 | ||
97221fd7 | 542 | /* Assemble thunks and aliases associated to varpool node. */ |
e0eaac80 | 543 | |
97221fd7 | 544 | void |
545 | varpool_node::assemble_aliases (void) | |
e0eaac80 | 546 | { |
35ee1c66 | 547 | ipa_ref *ref; |
51ce5652 | 548 | |
97221fd7 | 549 | FOR_EACH_ALIAS (this, ref) |
e4a2b488 | 550 | { |
551 | varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); | |
552 | do_assemble_alias (alias->decl, | |
97221fd7 | 553 | DECL_ASSEMBLER_NAME (decl)); |
554 | alias->assemble_aliases (); | |
e4a2b488 | 555 | } |
e0eaac80 | 556 | } |
557 | ||
1d416bd7 | 558 | /* Output one variable, if necessary. Return whether we output it. */ |
3d1c0354 | 559 | |
1d416bd7 | 560 | bool |
97221fd7 | 561 | varpool_node::assemble_decl (void) |
1d416bd7 | 562 | { |
3d1c0354 | 563 | /* Aliases are outout when their target is produced or by |
564 | output_weakrefs. */ | |
97221fd7 | 565 | if (alias) |
3d1c0354 | 566 | return false; |
567 | ||
568 | /* Constant pool is output from RTL land when the reference | |
569 | survive till this level. */ | |
015a842e | 570 | if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl)) |
3d1c0354 | 571 | return false; |
572 | ||
573 | /* Decls with VALUE_EXPR should not be in the varpool at all. They | |
574 | are not real variables, but just info for debugging and codegen. | |
575 | Unfortunately at the moment emutls is not updating varpool correctly | |
576 | after turning real vars into value_expr vars. */ | |
577 | if (DECL_HAS_VALUE_EXPR_P (decl) | |
578 | && !targetm.have_tls) | |
579 | return false; | |
580 | ||
c9aa6453 | 581 | /* Hard register vars do not need to be output. */ |
582 | if (DECL_HARD_REGISTER (decl)) | |
583 | return false; | |
584 | ||
3d1c0354 | 585 | gcc_checking_assert (!TREE_ASM_WRITTEN (decl) |
586 | && TREE_CODE (decl) == VAR_DECL | |
587 | && !DECL_HAS_VALUE_EXPR_P (decl)); | |
588 | ||
97221fd7 | 589 | if (!in_other_partition |
3d1c0354 | 590 | && !DECL_EXTERNAL (decl)) |
1d416bd7 | 591 | { |
97221fd7 | 592 | get_constructor (); |
1d416bd7 | 593 | assemble_variable (decl, 0, 1, 0); |
3d1c0354 | 594 | gcc_assert (TREE_ASM_WRITTEN (decl)); |
97221fd7 | 595 | gcc_assert (definition); |
596 | assemble_aliases (); | |
3d1c0354 | 597 | return true; |
1d416bd7 | 598 | } |
599 | ||
600 | return false; | |
601 | } | |
602 | ||
ff2a5ada | 603 | /* Add NODE to queue starting at FIRST. |
604 | The queue is linked via AUX pointers and terminated by pointer to 1. */ | |
605 | ||
606 | static void | |
098f44bc | 607 | enqueue_node (varpool_node *node, varpool_node **first) |
ff2a5ada | 608 | { |
02774f2d | 609 | if (node->aux) |
ff2a5ada | 610 | return; |
611 | gcc_checking_assert (*first); | |
02774f2d | 612 | node->aux = *first; |
ff2a5ada | 613 | *first = node; |
614 | } | |
615 | ||
1d416bd7 | 616 | /* Optimization of function bodies might've rendered some variables as |
ff2a5ada | 617 | unnecessary so we want to avoid these from being compiled. Re-do |
618 | reachability starting from variables that are either externally visible | |
619 | or was referred from the asm output routines. */ | |
1d416bd7 | 620 | |
35ee1c66 | 621 | void |
622 | symbol_table::remove_unreferenced_decls (void) | |
1d416bd7 | 623 | { |
098f44bc | 624 | varpool_node *next, *node; |
625 | varpool_node *first = (varpool_node *)(void *)1; | |
ff2a5ada | 626 | int i; |
35ee1c66 | 627 | ipa_ref *ref = NULL; |
431205b7 | 628 | hash_set<varpool_node *> referenced; |
1d416bd7 | 629 | |
852f689e | 630 | if (seen_error ()) |
1d416bd7 | 631 | return; |
632 | ||
35ee1c66 | 633 | if (dump_file) |
634 | fprintf (dump_file, "Trivially needed variables:"); | |
ff2a5ada | 635 | FOR_EACH_DEFINED_VARIABLE (node) |
1d416bd7 | 636 | { |
02774f2d | 637 | if (node->analyzed |
97221fd7 | 638 | && (!node->can_remove_if_no_refs_p () |
7410370b | 639 | /* We just expanded all function bodies. See if any of |
640 | them needed the variable. */ | |
02774f2d | 641 | || DECL_RTL_SET_P (node->decl))) |
ff2a5ada | 642 | { |
643 | enqueue_node (node, &first); | |
35ee1c66 | 644 | if (dump_file) |
645 | fprintf (dump_file, " %s", node->asm_name ()); | |
ff2a5ada | 646 | } |
647 | } | |
098f44bc | 648 | while (first != (varpool_node *)(void *)1) |
ff2a5ada | 649 | { |
650 | node = first; | |
098f44bc | 651 | first = (varpool_node *)first->aux; |
1d416bd7 | 652 | |
02774f2d | 653 | if (node->same_comdat_group) |
ff2a5ada | 654 | { |
452659af | 655 | symtab_node *next; |
02774f2d | 656 | for (next = node->same_comdat_group; |
657 | next != node; | |
658 | next = next->same_comdat_group) | |
2dc9831f | 659 | { |
13cbeaac | 660 | varpool_node *vnext = dyn_cast <varpool_node *> (next); |
415d1b9a | 661 | if (vnext && vnext->analyzed && !next->comdat_local_p ()) |
2dc9831f | 662 | enqueue_node (vnext, &first); |
663 | } | |
ff2a5ada | 664 | } |
51ce5652 | 665 | for (i = 0; node->iterate_reference (i, ref); i++) |
2dc9831f | 666 | { |
13cbeaac | 667 | varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred); |
2dc9831f | 668 | if (vnode |
5c3e0e39 | 669 | && !vnode->in_other_partition |
02774f2d | 670 | && (!DECL_EXTERNAL (ref->referred->decl) |
671 | || vnode->alias) | |
672 | && vnode->analyzed) | |
2dc9831f | 673 | enqueue_node (vnode, &first); |
5c3e0e39 | 674 | else |
431205b7 | 675 | referenced.add (node); |
2dc9831f | 676 | } |
1d416bd7 | 677 | } |
35ee1c66 | 678 | if (dump_file) |
679 | fprintf (dump_file, "\nRemoving variables:"); | |
680 | for (node = first_defined_variable (); node; node = next) | |
ff2a5ada | 681 | { |
35ee1c66 | 682 | next = next_defined_variable (node); |
6b722052 | 683 | if (!node->aux && !node->no_reorder) |
ff2a5ada | 684 | { |
35ee1c66 | 685 | if (dump_file) |
686 | fprintf (dump_file, " %s", node->asm_name ()); | |
687 | if (referenced.contains(node)) | |
97221fd7 | 688 | node->remove_initializer (); |
5c3e0e39 | 689 | else |
415d1b9a | 690 | node->remove (); |
ff2a5ada | 691 | } |
692 | } | |
431205b7 | 693 | |
35ee1c66 | 694 | if (dump_file) |
695 | fprintf (dump_file, "\n"); | |
1d416bd7 | 696 | } |
697 | ||
91da0f1c | 698 | /* For variables in named sections make sure get_variable_section |
699 | is called before we switch to those sections. Then section | |
700 | conflicts between read-only and read-only requiring relocations | |
701 | sections can be resolved. */ | |
702 | void | |
97221fd7 | 703 | varpool_node::finalize_named_section_flags (void) |
91da0f1c | 704 | { |
97221fd7 | 705 | if (!TREE_ASM_WRITTEN (decl) |
706 | && !alias | |
707 | && !in_other_partition | |
708 | && !DECL_EXTERNAL (decl) | |
709 | && TREE_CODE (decl) == VAR_DECL | |
710 | && !DECL_HAS_VALUE_EXPR_P (decl) | |
711 | && get_section ()) | |
712 | get_variable_section (decl, false); | |
91da0f1c | 713 | } |
714 | ||
1d416bd7 | 715 | /* Output all variables enqueued to be assembled. */ |
716 | bool | |
35ee1c66 | 717 | symbol_table::output_variables (void) |
1d416bd7 | 718 | { |
719 | bool changed = false; | |
098f44bc | 720 | varpool_node *node; |
1d416bd7 | 721 | |
852f689e | 722 | if (seen_error ()) |
1d416bd7 | 723 | return false; |
724 | ||
35ee1c66 | 725 | remove_unreferenced_decls (); |
cf951b1a | 726 | |
57305941 | 727 | timevar_push (TV_VAROUT); |
1d416bd7 | 728 | |
7260826d | 729 | FOR_EACH_VARIABLE (node) |
d1528ba2 | 730 | if (!node->definition |
731 | && !DECL_HAS_VALUE_EXPR_P (node->decl) | |
732 | && !DECL_HARD_REGISTER (node->decl)) | |
7260826d | 733 | assemble_undefined_decl (node->decl); |
7c455d87 | 734 | FOR_EACH_DEFINED_VARIABLE (node) |
6b722052 | 735 | { |
736 | /* Handled in output_in_order. */ | |
737 | if (node->no_reorder) | |
738 | continue; | |
739 | ||
740 | node->finalize_named_section_flags (); | |
741 | } | |
91da0f1c | 742 | |
ff2a5ada | 743 | FOR_EACH_DEFINED_VARIABLE (node) |
6b722052 | 744 | { |
745 | /* Handled in output_in_order. */ | |
746 | if (node->no_reorder) | |
747 | continue; | |
748 | if (node->assemble_decl ()) | |
749 | changed = true; | |
750 | } | |
57305941 | 751 | timevar_pop (TV_VAROUT); |
1d416bd7 | 752 | return changed; |
753 | } | |
754 | ||
f7496db6 | 755 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
756 | Extra name aliases are output whenever DECL is output. */ | |
757 | ||
098f44bc | 758 | varpool_node * |
97221fd7 | 759 | varpool_node::create_alias (tree alias, tree decl) |
f7496db6 | 760 | { |
098f44bc | 761 | varpool_node *alias_node; |
f7496db6 | 762 | |
763 | gcc_assert (TREE_CODE (decl) == VAR_DECL); | |
764 | gcc_assert (TREE_CODE (alias) == VAR_DECL); | |
97221fd7 | 765 | alias_node = varpool_node::get_create (alias); |
02774f2d | 766 | alias_node->alias = true; |
767 | alias_node->definition = true; | |
768 | alias_node->alias_target = decl; | |
f2526cce | 769 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) |
02774f2d | 770 | alias_node->weakref = true; |
e0eaac80 | 771 | return alias_node; |
772 | } | |
f7496db6 | 773 | |
e0eaac80 | 774 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
775 | Extra name aliases are output whenever DECL is output. */ | |
f7496db6 | 776 | |
098f44bc | 777 | varpool_node * |
97221fd7 | 778 | varpool_node::create_extra_name_alias (tree alias, tree decl) |
e0eaac80 | 779 | { |
098f44bc | 780 | varpool_node *alias_node; |
f7496db6 | 781 | |
e0eaac80 | 782 | #ifndef ASM_OUTPUT_DEF |
783 | /* If aliases aren't supported by the assembler, fail. */ | |
784 | return NULL; | |
785 | #endif | |
97221fd7 | 786 | alias_node = varpool_node::create_alias (alias, decl); |
02774f2d | 787 | alias_node->cpp_implicit_alias = true; |
48669653 | 788 | |
789 | /* Extra name alias mechanizm creates aliases really late | |
790 | via DECL_ASSEMBLER_NAME mechanizm. | |
791 | This is unfortunate because they are not going through the | |
792 | standard channels. Ensure they get output. */ | |
35ee1c66 | 793 | if (symtab->cpp_implicit_aliases_done) |
97221fd7 | 794 | alias_node->resolve_alias (varpool_node::get_create (decl)); |
9ced88d0 | 795 | return alias_node; |
796 | } | |
797 | ||
50f2a18b | 798 | /* Worker for call_for_symbol_and_aliases. */ |
e0eaac80 | 799 | |
800 | bool | |
50f2a18b | 801 | varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, |
802 | void *), | |
803 | void *data, | |
804 | bool include_overwritable) | |
e0eaac80 | 805 | { |
35ee1c66 | 806 | ipa_ref *ref; |
e0eaac80 | 807 | |
97221fd7 | 808 | FOR_EACH_ALIAS (this, ref) |
e4a2b488 | 809 | { |
810 | varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); | |
811 | if (include_overwritable | |
97221fd7 | 812 | || alias->get_availability () > AVAIL_INTERPOSABLE) |
50f2a18b | 813 | if (alias->call_for_symbol_and_aliases (callback, data, |
814 | include_overwritable)) | |
e4a2b488 | 815 | return true; |
816 | } | |
e0eaac80 | 817 | return false; |
818 | } |