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