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