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