]>
Commit | Line | Data |
---|---|---|
8a4a83ed | 1 | /* Callgraph handling code. |
8d9254fc | 2 | Copyright (C) 2003-2020 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" |
629b3d75 | 34 | #include "omp-offload.h" |
2631d4eb | 35 | #include "context.h" |
314e6352 ML |
36 | #include "stringpool.h" |
37 | #include "attribs.h" | |
8a4a83ed | 38 | |
b1474d30 JH |
39 | const char * const tls_model_names[]={"none", "emulated", |
40 | "global-dynamic", "local-dynamic", | |
41 | "initial-exec", "local-exec"}; | |
714c800f | 42 | |
26e5b0fd JH |
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 | ||
26e5b0fd | 50 | /* Register HOOK to be called with DATA on each removed node. */ |
3dafb85c ML |
51 | varpool_node_hook_list * |
52 | symbol_table::add_varpool_removal_hook (varpool_node_hook hook, void *data) | |
26e5b0fd | 53 | { |
3dafb85c ML |
54 | varpool_node_hook_list *entry; |
55 | varpool_node_hook_list **ptr = &m_first_varpool_removal_hook; | |
26e5b0fd | 56 | |
3dafb85c | 57 | entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry)); |
26e5b0fd JH |
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 | |
3dafb85c | 69 | symbol_table::remove_varpool_removal_hook (varpool_node_hook_list *entry) |
26e5b0fd | 70 | { |
3dafb85c | 71 | varpool_node_hook_list **ptr = &m_first_varpool_removal_hook; |
26e5b0fd JH |
72 | |
73 | while (*ptr != entry) | |
74 | ptr = &(*ptr)->next; | |
75 | *ptr = entry->next; | |
76 | free (entry); | |
77 | } | |
78 | ||
79 | /* Call all node removal hooks. */ | |
3dafb85c ML |
80 | void |
81 | symbol_table::call_varpool_removal_hooks (varpool_node *node) | |
26e5b0fd | 82 | { |
3dafb85c | 83 | varpool_node_hook_list *entry = m_first_varpool_removal_hook; |
26e5b0fd JH |
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. */ | |
3dafb85c ML |
92 | varpool_node_hook_list * |
93 | symbol_table::add_varpool_insertion_hook (varpool_node_hook hook, void *data) | |
26e5b0fd | 94 | { |
3dafb85c ML |
95 | varpool_node_hook_list *entry; |
96 | varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook; | |
26e5b0fd | 97 | |
3dafb85c | 98 | entry = (varpool_node_hook_list *) xmalloc (sizeof (*entry)); |
26e5b0fd JH |
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 | |
3dafb85c | 110 | symbol_table::remove_varpool_insertion_hook (varpool_node_hook_list *entry) |
26e5b0fd | 111 | { |
3dafb85c | 112 | varpool_node_hook_list **ptr = &m_first_varpool_insertion_hook; |
26e5b0fd JH |
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 | |
3dafb85c | 122 | symbol_table::call_varpool_insertion_hooks (varpool_node *node) |
26e5b0fd | 123 | { |
3dafb85c | 124 | varpool_node_hook_list *entry = m_first_varpool_insertion_hook; |
26e5b0fd JH |
125 | while (entry) |
126 | { | |
127 | entry->hook (node, entry->data); | |
128 | entry = entry->next; | |
129 | } | |
130 | } | |
131 | ||
bbf9ad07 JH |
132 | /* Allocate new callgraph node and insert it into basic data structures. */ |
133 | ||
2c8326a5 | 134 | varpool_node * |
9041d2e6 | 135 | varpool_node::create_empty (void) |
a65d584d ML |
136 | { |
137 | return new (ggc_alloc<varpool_node> ()) varpool_node (); | |
bbf9ad07 JH |
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 | |
dfea3d6f | 205 | the bodies, or we will end up removing |
ee03e71d | 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"); |
d52f5295 | 227 | if (TREE_READONLY (decl)) |
2d6e4603 | 228 | fprintf (f, " read-only"); |
9041d2e6 | 229 | if (ctor_useable_for_folding_p ()) |
2d6e4603 | 230 | fprintf (f, " const-value-known"); |
d52f5295 | 231 | if (writeonly) |
6de88c6a | 232 | fprintf (f, " write-only"); |
d52f5295 | 233 | if (tls_model) |
b1474d30 | 234 | fprintf (f, " tls-%s", tls_model_names [tls_model]); |
8a4a83ed JH |
235 | fprintf (f, "\n"); |
236 | } | |
237 | ||
9041d2e6 ML |
238 | |
239 | /* Dump given varpool node to stderr. */ | |
240 | void varpool_node::debug (void) | |
241 | { | |
242 | varpool_node::dump (stderr); | |
243 | } | |
244 | ||
d52f5295 | 245 | /* Dump the variable pool to F. */ |
8a4a83ed | 246 | void |
9041d2e6 | 247 | varpool_node::dump_varpool (FILE *f) |
8a4a83ed | 248 | { |
2c8326a5 | 249 | varpool_node *node; |
8a4a83ed JH |
250 | |
251 | fprintf (f, "variable pool:\n\n"); | |
65c70e6b | 252 | FOR_EACH_VARIABLE (node) |
d52f5295 | 253 | node->dump (f); |
8a4a83ed JH |
254 | } |
255 | ||
d85478c2 RAE |
256 | /* Dump the variable pool to stderr. */ |
257 | ||
24e47c76 | 258 | DEBUG_FUNCTION void |
9041d2e6 | 259 | varpool_node::debug_varpool (void) |
d85478c2 RAE |
260 | { |
261 | dump_varpool (stderr); | |
262 | } | |
263 | ||
8a4a83ed | 264 | /* Given an assembler name, lookup node. */ |
2c8326a5 | 265 | varpool_node * |
9041d2e6 | 266 | varpool_node::get_for_asmname (tree asmname) |
8a4a83ed | 267 | { |
3dafb85c | 268 | if (symtab_node *node = symtab_node::get_for_asmname (asmname)) |
7de90a6c | 269 | return dyn_cast <varpool_node *> (node); |
e70670cf JH |
270 | else |
271 | return NULL; | |
8a4a83ed JH |
272 | } |
273 | ||
9041d2e6 ML |
274 | /* When doing LTO, read variable's constructor from disk if |
275 | it is not already present. */ | |
0b83e688 JH |
276 | |
277 | tree | |
9041d2e6 | 278 | varpool_node::get_constructor (void) |
0b83e688 | 279 | { |
3dafb85c | 280 | lto_file_decl_data *file_data; |
0b83e688 JH |
281 | const char *data, *name; |
282 | size_t len; | |
0b83e688 | 283 | |
9041d2e6 | 284 | if (DECL_INITIAL (decl) != error_mark_node |
176ca71c JJ |
285 | || !in_lto_p |
286 | || !lto_file_data) | |
9041d2e6 | 287 | return DECL_INITIAL (decl); |
0b83e688 | 288 | |
917dd9bf JH |
289 | timevar_push (TV_IPA_LTO_CTORS_IN); |
290 | ||
9041d2e6 | 291 | file_data = lto_file_data; |
0b83e688 JH |
292 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
293 | ||
294 | /* We may have renamed the declaration, e.g., a static function. */ | |
295 | name = lto_get_decl_name_mapping (file_data, name); | |
ca834876 JH |
296 | struct lto_in_decl_state *decl_state |
297 | = lto_get_function_in_decl_state (file_data, decl); | |
0b83e688 JH |
298 | |
299 | data = lto_get_section_data (file_data, LTO_section_function_body, | |
3c56d8d8 ML |
300 | name, order - file_data->order_base, |
301 | &len, decl_state->compressed); | |
0b83e688 | 302 | if (!data) |
3c56d8d8 | 303 | fatal_error (input_location, "%s: section %s.%d is missing", |
0b83e688 | 304 | file_data->file_name, |
3c56d8d8 | 305 | name, order - file_data->order_base); |
0b83e688 | 306 | |
b4da704c JH |
307 | if (!quiet_flag) |
308 | fprintf (stderr, " in:%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); | |
9041d2e6 | 309 | lto_input_variable_constructor (file_data, this, data); |
1c4db829 | 310 | gcc_assert (DECL_INITIAL (decl) != error_mark_node); |
0b83e688 JH |
311 | lto_stats.num_function_bodies++; |
312 | lto_free_section_data (file_data, LTO_section_function_body, name, | |
ca834876 | 313 | data, len, decl_state->compressed); |
9041d2e6 | 314 | lto_free_function_in_decl_state_for_node (this); |
917dd9bf | 315 | timevar_pop (TV_IPA_LTO_CTORS_IN); |
9041d2e6 | 316 | return DECL_INITIAL (decl); |
0b83e688 JH |
317 | } |
318 | ||
9041d2e6 | 319 | /* Return true if variable has constructor that can be used for folding. */ |
0b83e688 JH |
320 | |
321 | bool | |
9041d2e6 | 322 | varpool_node::ctor_useable_for_folding_p (void) |
0b83e688 | 323 | { |
9041d2e6 | 324 | varpool_node *real_node = this; |
0b83e688 JH |
325 | |
326 | if (real_node->alias && real_node->definition) | |
9041d2e6 | 327 | real_node = ultimate_alias_target (); |
0b83e688 | 328 | |
9041d2e6 ML |
329 | if (TREE_CODE (decl) == CONST_DECL |
330 | || DECL_IN_CONSTANT_POOL (decl)) | |
0b83e688 | 331 | return true; |
9041d2e6 | 332 | if (TREE_THIS_VOLATILE (decl)) |
0b83e688 JH |
333 | return false; |
334 | ||
3b456f8d JH |
335 | /* Avoid attempts to load constructors that was not streamed. */ |
336 | if (in_lto_p && DECL_INITIAL (real_node->decl) == error_mark_node | |
337 | && real_node->body_removed) | |
338 | return false; | |
339 | ||
0b83e688 JH |
340 | /* If we do not have a constructor, we can't use it. */ |
341 | if (DECL_INITIAL (real_node->decl) == error_mark_node | |
342 | && !real_node->lto_file_data) | |
343 | return false; | |
344 | ||
345 | /* Vtables are defined by their types and must match no matter of interposition | |
346 | rules. */ | |
9041d2e6 | 347 | if (DECL_VIRTUAL_P (decl)) |
0b83e688 JH |
348 | { |
349 | /* The C++ front end creates VAR_DECLs for vtables of typeinfo | |
350 | classes not defined in the current TU so that it can refer | |
351 | to them from typeinfo objects. Avoid returning NULL_TREE. */ | |
352 | return DECL_INITIAL (real_node->decl) != NULL; | |
353 | } | |
354 | ||
5a715667 GP |
355 | /* An alias of a read-only variable is also read-only, since the variable |
356 | is stored in read-only memory. We also accept read-only aliases of | |
357 | non-read-only locations assuming that the user knows what he is asking | |
358 | for. */ | |
9041d2e6 | 359 | if (!TREE_READONLY (decl) && !TREE_READONLY (real_node->decl)) |
0b83e688 JH |
360 | return false; |
361 | ||
362 | /* Variables declared 'const' without an initializer | |
363 | have zero as the initializer if they may not be | |
91bc34a9 JH |
364 | overridden at link or run time. |
365 | ||
366 | It is actually requirement for C++ compiler to optimize const variables | |
dfea3d6f | 367 | consistently. As a GNU extension, do not enforce this rule for user defined |
91bc34a9 JH |
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))) | |
9041d2e6 | 374 | && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl))) |
0b83e688 JH |
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 | ||
9041d2e6 ML |
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. | |
0b83e688 JH |
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. */ | |
155c92a7 | 393 | |
6a6dac52 JH |
394 | tree |
395 | ctor_for_folding (tree decl) | |
155c92a7 | 396 | { |
2c8326a5 | 397 | varpool_node *node, *real_node; |
6a6dac52 JH |
398 | tree real_decl; |
399 | ||
8813a647 | 400 | if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL) |
6a6dac52 | 401 | return error_mark_node; |
64e0f5ff JH |
402 | |
403 | if (TREE_CODE (decl) == CONST_DECL | |
404 | || DECL_IN_CONSTANT_POOL (decl)) | |
6a6dac52 | 405 | return DECL_INITIAL (decl); |
64e0f5ff | 406 | |
6a6dac52 JH |
407 | if (TREE_THIS_VOLATILE (decl)) |
408 | return error_mark_node; | |
64e0f5ff | 409 | |
6a6dac52 | 410 | /* Do not care about automatic variables. Those are never initialized |
dfea3d6f | 411 | anyway, because gimplifier expands the code. */ |
64e0f5ff | 412 | if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) |
6a6dac52 JH |
413 | { |
414 | gcc_assert (!TREE_PUBLIC (decl)); | |
415 | return error_mark_node; | |
416 | } | |
64e0f5ff | 417 | |
8813a647 | 418 | gcc_assert (VAR_P (decl)); |
6a6dac52 | 419 | |
9041d2e6 | 420 | real_node = node = varpool_node::get (decl); |
6a6dac52 JH |
421 | if (node) |
422 | { | |
9041d2e6 | 423 | real_node = node->ultimate_alias_target (); |
67348ccc | 424 | real_decl = real_node->decl; |
6a6dac52 JH |
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) | |
fd29c024 | 437 | || (node->alias && node->get_alias_target () == real_node) |
6a6dac52 | 438 | || DECL_INITIAL (decl) == error_mark_node); |
71e54687 | 439 | while (node->transparent_alias && node->analyzed) |
6a6dac52 | 440 | { |
9041d2e6 | 441 | node = node->get_alias_target (); |
67348ccc | 442 | decl = node->decl; |
6a6dac52 JH |
443 | } |
444 | } | |
445 | ||
0b83e688 JH |
446 | if ((!DECL_VIRTUAL_P (real_decl) |
447 | || DECL_INITIAL (real_decl) == error_mark_node | |
448 | || !DECL_INITIAL (real_decl)) | |
9041d2e6 | 449 | && (!node || !node->ctor_useable_for_folding_p ())) |
6a6dac52 | 450 | return error_mark_node; |
155c92a7 | 451 | |
0b83e688 JH |
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); | |
9041d2e6 | 457 | return real_node->get_constructor (); |
155c92a7 JH |
458 | } |
459 | ||
38877e98 | 460 | /* Add the variable DECL to the varpool. |
3dafb85c | 461 | Unlike finalize_decl function is intended to be used |
38877e98 ZM |
462 | by middle end and allows insertion of new variable at arbitrary point |
463 | of compilation. */ | |
464 | void | |
3dafb85c | 465 | varpool_node::add (tree decl) |
38877e98 | 466 | { |
2c8326a5 | 467 | varpool_node *node; |
9041d2e6 ML |
468 | varpool_node::finalize_decl (decl); |
469 | node = varpool_node::get_create (decl); | |
3dafb85c | 470 | symtab->call_varpool_insertion_hooks (node); |
9041d2e6 | 471 | if (node->externally_visible_p ()) |
67348ccc | 472 | node->externally_visible = true; |
0f549a67 | 473 | if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl))) |
7861b648 | 474 | node->no_reorder = 1; |
38877e98 ZM |
475 | } |
476 | ||
8a4a83ed JH |
477 | /* Return variable availability. See cgraph.h for description of individual |
478 | return values. */ | |
479 | enum availability | |
f13fe18b | 480 | varpool_node::get_availability (symtab_node *ref) |
8a4a83ed | 481 | { |
9041d2e6 | 482 | if (!definition) |
8a4a83ed | 483 | return AVAIL_NOT_AVAILABLE; |
9041d2e6 | 484 | if (!TREE_PUBLIC (decl)) |
8a4a83ed | 485 | return AVAIL_AVAILABLE; |
9041d2e6 ML |
486 | if (DECL_IN_CONSTANT_POOL (decl) |
487 | || DECL_VIRTUAL_P (decl)) | |
8a41354f | 488 | return AVAIL_AVAILABLE; |
9b21e866 | 489 | if (transparent_alias && definition) |
8a41354f JH |
490 | { |
491 | enum availability avail; | |
492 | ||
f13fe18b | 493 | ultimate_alias_target (&avail, ref); |
8a41354f JH |
494 | return avail; |
495 | } | |
f13fe18b | 496 | /* If this is a reference from symbol itself and there are no aliases, we |
65c74eb2 | 497 | may be sure that the symbol was not interposed by something else because |
f13fe18b JH |
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; | |
8a4a83ed | 503 | /* If the variable can be overwritten, return OVERWRITABLE. Takes |
e70670cf | 504 | care of at least one notable extension - the COMDAT variables |
8a4a83ed | 505 | used to share template instantiations in C++. */ |
9041d2e6 ML |
506 | if (decl_replaceable_p (decl) |
507 | || DECL_EXTERNAL (decl)) | |
d52f5295 | 508 | return AVAIL_INTERPOSABLE; |
8a4a83ed JH |
509 | return AVAIL_AVAILABLE; |
510 | } | |
511 | ||
66058468 | 512 | void |
9041d2e6 | 513 | varpool_node::analyze (void) |
8a4a83ed | 514 | { |
66058468 JH |
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. */ | |
9041d2e6 | 518 | if (!analyzed) |
8a4a83ed | 519 | { |
3dafb85c | 520 | gcc_assert (!in_lto_p || symtab->function_flags_ready); |
66058468 JH |
521 | /* Compute the alignment early so function body expanders are |
522 | already informed about increased alignment. */ | |
523 | align_variable (decl, 0); | |
524 | } | |
9041d2e6 ML |
525 | if (alias) |
526 | resolve_alias (varpool_node::get (alias_target)); | |
66058468 | 527 | else if (DECL_INITIAL (decl)) |
9041d2e6 ML |
528 | record_references_in_initializer (decl, analyzed); |
529 | analyzed = true; | |
8a4a83ed JH |
530 | } |
531 | ||
9041d2e6 | 532 | /* Assemble thunks and aliases associated to varpool node. */ |
cd35bcf7 | 533 | |
9041d2e6 ML |
534 | void |
535 | varpool_node::assemble_aliases (void) | |
cd35bcf7 | 536 | { |
3dafb85c | 537 | ipa_ref *ref; |
d122681a | 538 | |
9041d2e6 | 539 | FOR_EACH_ALIAS (this, ref) |
e55637b7 ML |
540 | { |
541 | varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); | |
d7ddfbcb JH |
542 | if (alias->symver) |
543 | do_assemble_symver (alias->decl, | |
544 | DECL_ASSEMBLER_NAME (decl)); | |
545 | else if (!alias->transparent_alias) | |
71e54687 JH |
546 | do_assemble_alias (alias->decl, |
547 | DECL_ASSEMBLER_NAME (decl)); | |
9041d2e6 | 548 | alias->assemble_aliases (); |
e55637b7 | 549 | } |
cd35bcf7 JH |
550 | } |
551 | ||
8a4a83ed | 552 | /* Output one variable, if necessary. Return whether we output it. */ |
0d6bf48c | 553 | |
8a4a83ed | 554 | bool |
9041d2e6 | 555 | varpool_node::assemble_decl (void) |
8a4a83ed | 556 | { |
dfea3d6f | 557 | /* Aliases are output when their target is produced or by |
0d6bf48c | 558 | output_weakrefs. */ |
9041d2e6 | 559 | if (alias) |
0d6bf48c JH |
560 | return false; |
561 | ||
562 | /* Constant pool is output from RTL land when the reference | |
563 | survive till this level. */ | |
8fc17ddc | 564 | if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl)) |
0d6bf48c JH |
565 | return false; |
566 | ||
567 | /* Decls with VALUE_EXPR should not be in the varpool at all. They | |
568 | are not real variables, but just info for debugging and codegen. | |
569 | Unfortunately at the moment emutls is not updating varpool correctly | |
570 | after turning real vars into value_expr vars. */ | |
571 | if (DECL_HAS_VALUE_EXPR_P (decl) | |
572 | && !targetm.have_tls) | |
573 | return false; | |
574 | ||
b5493fb2 JH |
575 | /* Hard register vars do not need to be output. */ |
576 | if (DECL_HARD_REGISTER (decl)) | |
577 | return false; | |
578 | ||
0d6bf48c | 579 | gcc_checking_assert (!TREE_ASM_WRITTEN (decl) |
8813a647 | 580 | && VAR_P (decl) |
0d6bf48c JH |
581 | && !DECL_HAS_VALUE_EXPR_P (decl)); |
582 | ||
9041d2e6 | 583 | if (!in_other_partition |
0d6bf48c | 584 | && !DECL_EXTERNAL (decl)) |
8a4a83ed | 585 | { |
9041d2e6 | 586 | get_constructor (); |
8a4a83ed | 587 | assemble_variable (decl, 0, 1, 0); |
0d6bf48c | 588 | gcc_assert (TREE_ASM_WRITTEN (decl)); |
9041d2e6 ML |
589 | gcc_assert (definition); |
590 | assemble_aliases (); | |
5fc6ae7d RB |
591 | /* After the parser has generated debugging information, augment |
592 | this information with any new location/etc information that may | |
593 | have become available after the compilation proper. */ | |
5fc6ae7d | 594 | debug_hooks->late_global_decl (decl); |
0d6bf48c | 595 | return true; |
8a4a83ed JH |
596 | } |
597 | ||
598 | return false; | |
599 | } | |
600 | ||
66058468 JH |
601 | /* Add NODE to queue starting at FIRST. |
602 | The queue is linked via AUX pointers and terminated by pointer to 1. */ | |
603 | ||
604 | static void | |
2c8326a5 | 605 | enqueue_node (varpool_node *node, varpool_node **first) |
66058468 | 606 | { |
67348ccc | 607 | if (node->aux) |
66058468 JH |
608 | return; |
609 | gcc_checking_assert (*first); | |
67348ccc | 610 | node->aux = *first; |
66058468 JH |
611 | *first = node; |
612 | } | |
613 | ||
8a4a83ed | 614 | /* Optimization of function bodies might've rendered some variables as |
66058468 JH |
615 | unnecessary so we want to avoid these from being compiled. Re-do |
616 | reachability starting from variables that are either externally visible | |
617 | or was referred from the asm output routines. */ | |
8a4a83ed | 618 | |
3dafb85c ML |
619 | void |
620 | symbol_table::remove_unreferenced_decls (void) | |
8a4a83ed | 621 | { |
2c8326a5 OE |
622 | varpool_node *next, *node; |
623 | varpool_node *first = (varpool_node *)(void *)1; | |
66058468 | 624 | int i; |
3dafb85c | 625 | ipa_ref *ref = NULL; |
6e2830c3 | 626 | hash_set<varpool_node *> referenced; |
8a4a83ed | 627 | |
1da2ed5f | 628 | if (seen_error ()) |
8a4a83ed JH |
629 | return; |
630 | ||
3dafb85c ML |
631 | if (dump_file) |
632 | fprintf (dump_file, "Trivially needed variables:"); | |
66058468 | 633 | FOR_EACH_DEFINED_VARIABLE (node) |
8a4a83ed | 634 | { |
67348ccc | 635 | if (node->analyzed |
9041d2e6 | 636 | && (!node->can_remove_if_no_refs_p () |
df7705b1 JH |
637 | /* We just expanded all function bodies. See if any of |
638 | them needed the variable. */ | |
67348ccc | 639 | || DECL_RTL_SET_P (node->decl))) |
66058468 JH |
640 | { |
641 | enqueue_node (node, &first); | |
3dafb85c | 642 | if (dump_file) |
3629ff8a | 643 | fprintf (dump_file, " %s", node->dump_asm_name ()); |
66058468 JH |
644 | } |
645 | } | |
2c8326a5 | 646 | while (first != (varpool_node *)(void *)1) |
66058468 JH |
647 | { |
648 | node = first; | |
2c8326a5 | 649 | first = (varpool_node *)first->aux; |
8a4a83ed | 650 | |
67348ccc | 651 | if (node->same_comdat_group) |
66058468 | 652 | { |
5e20cdc9 | 653 | symtab_node *next; |
67348ccc DM |
654 | for (next = node->same_comdat_group; |
655 | next != node; | |
656 | next = next->same_comdat_group) | |
5d59b5e1 | 657 | { |
7de90a6c | 658 | varpool_node *vnext = dyn_cast <varpool_node *> (next); |
d52f5295 | 659 | if (vnext && vnext->analyzed && !next->comdat_local_p ()) |
5d59b5e1 LC |
660 | enqueue_node (vnext, &first); |
661 | } | |
66058468 | 662 | } |
d122681a | 663 | for (i = 0; node->iterate_reference (i, ref); i++) |
5d59b5e1 | 664 | { |
7de90a6c | 665 | varpool_node *vnode = dyn_cast <varpool_node *> (ref->referred); |
5d59b5e1 | 666 | if (vnode |
a0a98fef | 667 | && !vnode->in_other_partition |
67348ccc DM |
668 | && (!DECL_EXTERNAL (ref->referred->decl) |
669 | || vnode->alias) | |
670 | && vnode->analyzed) | |
5d59b5e1 | 671 | enqueue_node (vnode, &first); |
a0a98fef | 672 | else |
71e54687 | 673 | { |
9b21e866 JH |
674 | referenced.add (vnode); |
675 | while (vnode && vnode->alias && vnode->definition) | |
71e54687 | 676 | { |
9b21e866 JH |
677 | vnode = vnode->get_alias_target (); |
678 | referenced.add (vnode); | |
71e54687 JH |
679 | } |
680 | } | |
5d59b5e1 | 681 | } |
8a4a83ed | 682 | } |
3dafb85c ML |
683 | if (dump_file) |
684 | fprintf (dump_file, "\nRemoving variables:"); | |
685 | for (node = first_defined_variable (); node; node = next) | |
66058468 | 686 | { |
3dafb85c | 687 | next = next_defined_variable (node); |
7861b648 | 688 | if (!node->aux && !node->no_reorder) |
66058468 | 689 | { |
3dafb85c | 690 | if (dump_file) |
3629ff8a | 691 | fprintf (dump_file, " %s", node->dump_asm_name ()); |
3dafb85c | 692 | if (referenced.contains(node)) |
9041d2e6 | 693 | node->remove_initializer (); |
a0a98fef | 694 | else |
d52f5295 | 695 | node->remove (); |
66058468 JH |
696 | } |
697 | } | |
6e2830c3 | 698 | |
3dafb85c ML |
699 | if (dump_file) |
700 | fprintf (dump_file, "\n"); | |
8a4a83ed JH |
701 | } |
702 | ||
7fece979 JJ |
703 | /* For variables in named sections make sure get_variable_section |
704 | is called before we switch to those sections. Then section | |
705 | conflicts between read-only and read-only requiring relocations | |
706 | sections can be resolved. */ | |
707 | void | |
9041d2e6 | 708 | varpool_node::finalize_named_section_flags (void) |
7fece979 | 709 | { |
9041d2e6 ML |
710 | if (!TREE_ASM_WRITTEN (decl) |
711 | && !alias | |
712 | && !in_other_partition | |
713 | && !DECL_EXTERNAL (decl) | |
8813a647 | 714 | && VAR_P (decl) |
9041d2e6 ML |
715 | && !DECL_HAS_VALUE_EXPR_P (decl) |
716 | && get_section ()) | |
717 | get_variable_section (decl, false); | |
7fece979 JJ |
718 | } |
719 | ||
8a4a83ed JH |
720 | /* Output all variables enqueued to be assembled. */ |
721 | bool | |
3dafb85c | 722 | symbol_table::output_variables (void) |
8a4a83ed JH |
723 | { |
724 | bool changed = false; | |
2c8326a5 | 725 | varpool_node *node; |
8a4a83ed | 726 | |
1da2ed5f | 727 | if (seen_error ()) |
8a4a83ed JH |
728 | return false; |
729 | ||
3dafb85c | 730 | remove_unreferenced_decls (); |
65d630d4 | 731 | |
49ba8180 | 732 | timevar_push (TV_VAROUT); |
8a4a83ed | 733 | |
65c70e6b | 734 | FOR_EACH_DEFINED_VARIABLE (node) |
7861b648 AK |
735 | { |
736 | /* Handled in output_in_order. */ | |
737 | if (node->no_reorder) | |
738 | continue; | |
739 | ||
740 | node->finalize_named_section_flags (); | |
741 | } | |
7fece979 | 742 | |
3ef46782 AM |
743 | /* There is a similar loop in output_in_order. Please keep them in sync. */ |
744 | FOR_EACH_VARIABLE (node) | |
7861b648 AK |
745 | { |
746 | /* Handled in output_in_order. */ | |
747 | if (node->no_reorder) | |
748 | continue; | |
3ef46782 AM |
749 | if (DECL_HARD_REGISTER (node->decl) |
750 | || DECL_HAS_VALUE_EXPR_P (node->decl)) | |
4a38b02b | 751 | continue; |
3ef46782 AM |
752 | if (node->definition) |
753 | changed |= node->assemble_decl (); | |
754 | else | |
755 | assemble_undefined_decl (node->decl); | |
7861b648 | 756 | } |
49ba8180 | 757 | timevar_pop (TV_VAROUT); |
8a4a83ed JH |
758 | return changed; |
759 | } | |
760 | ||
2c71ac78 JM |
761 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
762 | Extra name aliases are output whenever DECL is output. */ | |
763 | ||
2c8326a5 | 764 | varpool_node * |
9041d2e6 | 765 | varpool_node::create_alias (tree alias, tree decl) |
2c71ac78 | 766 | { |
2c8326a5 | 767 | varpool_node *alias_node; |
2c71ac78 | 768 | |
8813a647 JJ |
769 | gcc_assert (VAR_P (decl)); |
770 | gcc_assert (VAR_P (alias)); | |
9041d2e6 | 771 | alias_node = varpool_node::get_create (alias); |
67348ccc DM |
772 | alias_node->alias = true; |
773 | alias_node->definition = true; | |
774 | alias_node->alias_target = decl; | |
08346abd | 775 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) |
71e54687 | 776 | alias_node->weakref = alias_node->transparent_alias = true; |
cd35bcf7 JH |
777 | return alias_node; |
778 | } | |
2c71ac78 | 779 | |
cd35bcf7 JH |
780 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
781 | Extra name aliases are output whenever DECL is output. */ | |
2c71ac78 | 782 | |
2c8326a5 | 783 | varpool_node * |
9041d2e6 | 784 | varpool_node::create_extra_name_alias (tree alias, tree decl) |
cd35bcf7 | 785 | { |
2c8326a5 | 786 | varpool_node *alias_node; |
2c71ac78 | 787 | |
cd35bcf7 | 788 | /* If aliases aren't supported by the assembler, fail. */ |
a8b522b4 ML |
789 | if (!TARGET_SUPPORTS_ALIASES) |
790 | return NULL; | |
791 | ||
9041d2e6 | 792 | alias_node = varpool_node::create_alias (alias, decl); |
67348ccc | 793 | alias_node->cpp_implicit_alias = true; |
40a7fe1e | 794 | |
dfea3d6f JJ |
795 | /* Extra name alias mechanism creates aliases really late |
796 | via DECL_ASSEMBLER_NAME mechanism. | |
40a7fe1e JH |
797 | This is unfortunate because they are not going through the |
798 | standard channels. Ensure they get output. */ | |
3dafb85c | 799 | if (symtab->cpp_implicit_aliases_done) |
9041d2e6 | 800 | alias_node->resolve_alias (varpool_node::get_create (decl)); |
051f8cc6 JH |
801 | return alias_node; |
802 | } | |
803 | ||
31de7606 | 804 | /* Worker for call_for_symbol_and_aliases. */ |
cd35bcf7 JH |
805 | |
806 | bool | |
31de7606 JH |
807 | varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, |
808 | void *), | |
809 | void *data, | |
810 | bool include_overwritable) | |
cd35bcf7 | 811 | { |
3dafb85c | 812 | ipa_ref *ref; |
cd35bcf7 | 813 | |
9041d2e6 | 814 | FOR_EACH_ALIAS (this, ref) |
e55637b7 ML |
815 | { |
816 | varpool_node *alias = dyn_cast <varpool_node *> (ref->referring); | |
817 | if (include_overwritable | |
9041d2e6 | 818 | || alias->get_availability () > AVAIL_INTERPOSABLE) |
31de7606 JH |
819 | if (alias->call_for_symbol_and_aliases (callback, data, |
820 | include_overwritable)) | |
e55637b7 ML |
821 | return true; |
822 | } | |
cd35bcf7 JH |
823 | return false; |
824 | } |