]>
Commit | Line | Data |
---|---|---|
8a4a83ed | 1 | /* Callgraph handling code. |
66058468 | 2 | Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012 |
66647d44 | 3 | Free Software Foundation, Inc. |
8a4a83ed JH |
4 | Contributed by Jan Hubicka |
5 | ||
6 | This file is part of GCC. | |
7 | ||
8 | GCC is free software; you can redistribute it and/or modify it under | |
9 | the terms of the GNU General Public License as published by the Free | |
9dcd6f09 | 10 | Software Foundation; either version 3, or (at your option) any later |
8a4a83ed JH |
11 | version. |
12 | ||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ | |
8a4a83ed JH |
21 | |
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "tree.h" | |
27 | #include "cgraph.h" | |
28 | #include "langhooks.h" | |
1da2ed5f | 29 | #include "diagnostic-core.h" |
8a4a83ed JH |
30 | #include "hashtab.h" |
31 | #include "ggc.h" | |
32 | #include "timevar.h" | |
b8698a0f | 33 | #include "debug.h" |
8a4a83ed JH |
34 | #include "target.h" |
35 | #include "output.h" | |
726a989a | 36 | #include "gimple.h" |
43d861a5 | 37 | #include "tree-flow.h" |
b20996ff | 38 | #include "flags.h" |
8a4a83ed | 39 | |
8a4a83ed JH |
40 | /* Return varpool node assigned to DECL. Create new one when needed. */ |
41 | struct varpool_node * | |
42 | varpool_node (tree decl) | |
43 | { | |
1ab24192 | 44 | struct varpool_node *node = varpool_get_node (decl); |
a482b1f5 | 45 | gcc_assert (TREE_CODE (decl) == VAR_DECL |
cd35bcf7 | 46 | && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p)); |
1ab24192 JH |
47 | if (node) |
48 | return node; | |
8a4a83ed | 49 | |
a9429e29 | 50 | node = ggc_alloc_cleared_varpool_node (); |
1f00098b | 51 | node->symbol.type = SYMTAB_VARIABLE; |
960bfb69 | 52 | node->symbol.decl = decl; |
2aae7680 | 53 | symtab_register_node ((symtab_node)node); |
8a4a83ed JH |
54 | return node; |
55 | } | |
56 | ||
2942c502 JH |
57 | /* Remove node from the varpool. */ |
58 | void | |
59 | varpool_remove_node (struct varpool_node *node) | |
60 | { | |
2aae7680 | 61 | symtab_unregister_node ((symtab_node)node); |
6649df51 JH |
62 | if (DECL_INITIAL (node->symbol.decl) |
63 | && !DECL_IN_CONSTANT_POOL (node->symbol.decl) | |
64 | /* Keep vtables for BINFO folding. */ | |
65 | && !DECL_VIRTUAL_P (node->symbol.decl) | |
66 | /* dbxout output constant initializers for readonly vars. */ | |
67 | && (!host_integerp (DECL_INITIAL (node->symbol.decl), 0) | |
68 | || !TREE_READONLY (node->symbol.decl))) | |
69 | DECL_INITIAL (node->symbol.decl) = error_mark_node; | |
688a10c2 | 70 | ggc_free (node); |
2942c502 JH |
71 | } |
72 | ||
8a4a83ed JH |
73 | /* Dump given cgraph node. */ |
74 | void | |
75 | dump_varpool_node (FILE *f, struct varpool_node *node) | |
76 | { | |
8f940ee6 JH |
77 | dump_symtab_base (f, (symtab_node)node); |
78 | fprintf (f, " Availability: %s\n", | |
8a4a83ed JH |
79 | cgraph_function_flags_ready |
80 | ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] | |
81 | : "not-ready"); | |
8f940ee6 | 82 | fprintf (f, " Varpool flags:"); |
960bfb69 | 83 | if (DECL_INITIAL (node->symbol.decl)) |
8a4a83ed | 84 | fprintf (f, " initialized"); |
8a4a83ed JH |
85 | if (node->analyzed) |
86 | fprintf (f, " analyzed"); | |
87 | if (node->finalized) | |
88 | fprintf (f, " finalized"); | |
89 | if (node->output) | |
90 | fprintf (f, " output"); | |
8a4a83ed JH |
91 | fprintf (f, "\n"); |
92 | } | |
93 | ||
94 | /* Dump the variable pool. */ | |
95 | void | |
96 | dump_varpool (FILE *f) | |
97 | { | |
98 | struct varpool_node *node; | |
99 | ||
100 | fprintf (f, "variable pool:\n\n"); | |
65c70e6b | 101 | FOR_EACH_VARIABLE (node) |
8a4a83ed JH |
102 | dump_varpool_node (f, node); |
103 | } | |
104 | ||
d85478c2 RAE |
105 | /* Dump the variable pool to stderr. */ |
106 | ||
24e47c76 | 107 | DEBUG_FUNCTION void |
d85478c2 RAE |
108 | debug_varpool (void) |
109 | { | |
110 | dump_varpool (stderr); | |
111 | } | |
112 | ||
8a4a83ed JH |
113 | /* Given an assembler name, lookup node. */ |
114 | struct varpool_node * | |
115 | varpool_node_for_asm (tree asmname) | |
116 | { | |
1ab24192 JH |
117 | symtab_node node = symtab_node_for_asm (asmname); |
118 | if (node && symtab_variable_p (node)) | |
119 | return varpool (node); | |
8a4a83ed JH |
120 | return NULL; |
121 | } | |
122 | ||
8a4a83ed JH |
123 | /* Determine if variable DECL is needed. That is, visible to something |
124 | either outside this translation unit, something magic in the system | |
7e8b322a | 125 | configury */ |
8a4a83ed JH |
126 | bool |
127 | decide_is_variable_needed (struct varpool_node *node, tree decl) | |
128 | { | |
6649df51 JH |
129 | if (DECL_EXTERNAL (decl)) |
130 | return false; | |
131 | ||
8a4a83ed | 132 | /* If the user told us it is used, then it must be so. */ |
ead84f73 | 133 | if (node->symbol.force_output) |
8a4a83ed | 134 | return true; |
8a4a83ed | 135 | |
8a4a83ed JH |
136 | /* Externally visible variables must be output. The exception is |
137 | COMDAT variables that must be output only when they are needed. */ | |
b20996ff | 138 | if (TREE_PUBLIC (decl) |
6649df51 | 139 | && !DECL_COMDAT (decl)) |
8a4a83ed JH |
140 | return true; |
141 | ||
df7705b1 | 142 | return false; |
8a4a83ed JH |
143 | } |
144 | ||
64e0f5ff JH |
145 | /* Return if DECL is constant and its initial value is known (so we can do |
146 | constant folding using DECL_INITIAL (decl)). */ | |
155c92a7 JH |
147 | |
148 | bool | |
64e0f5ff | 149 | const_value_known_p (tree decl) |
155c92a7 | 150 | { |
1d0804d4 JH |
151 | if (TREE_CODE (decl) != VAR_DECL |
152 | &&TREE_CODE (decl) != CONST_DECL) | |
64e0f5ff JH |
153 | return false; |
154 | ||
155 | if (TREE_CODE (decl) == CONST_DECL | |
156 | || DECL_IN_CONSTANT_POOL (decl)) | |
157 | return true; | |
155c92a7 | 158 | |
155c92a7 | 159 | gcc_assert (TREE_CODE (decl) == VAR_DECL); |
64e0f5ff | 160 | |
3a2df831 | 161 | if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl)) |
155c92a7 | 162 | return false; |
64e0f5ff JH |
163 | |
164 | /* Gimplifier takes away constructors of local vars */ | |
165 | if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) | |
166 | return DECL_INITIAL (decl) != NULL; | |
167 | ||
168 | gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); | |
169 | ||
155c92a7 JH |
170 | /* Variables declared 'const' without an initializer |
171 | have zero as the initializer if they may not be | |
172 | overridden at link or run time. */ | |
173 | if (!DECL_INITIAL (decl) | |
174 | && (DECL_EXTERNAL (decl) | |
051f8cc6 | 175 | || decl_replaceable_p (decl))) |
155c92a7 JH |
176 | return false; |
177 | ||
178 | /* Variables declared `const' with an initializer are considered | |
179 | to not be overwritable with different initializer by default. | |
180 | ||
181 | ??? Previously we behaved so for scalar variables but not for array | |
182 | accesses. */ | |
183 | return true; | |
184 | } | |
185 | ||
38877e98 ZM |
186 | /* Add the variable DECL to the varpool. |
187 | Unlike varpool_finalize_decl function is intended to be used | |
188 | by middle end and allows insertion of new variable at arbitrary point | |
189 | of compilation. */ | |
190 | void | |
191 | varpool_add_new_variable (tree decl) | |
192 | { | |
193 | struct varpool_node *node; | |
194 | varpool_finalize_decl (decl); | |
195 | node = varpool_node (decl); | |
196 | if (varpool_externally_visible_p (node, false)) | |
960bfb69 | 197 | node->symbol.externally_visible = true; |
38877e98 ZM |
198 | } |
199 | ||
8a4a83ed JH |
200 | /* Return variable availability. See cgraph.h for description of individual |
201 | return values. */ | |
202 | enum availability | |
203 | cgraph_variable_initializer_availability (struct varpool_node *node) | |
204 | { | |
205 | gcc_assert (cgraph_function_flags_ready); | |
206 | if (!node->finalized) | |
207 | return AVAIL_NOT_AVAILABLE; | |
960bfb69 | 208 | if (!TREE_PUBLIC (node->symbol.decl)) |
8a4a83ed JH |
209 | return AVAIL_AVAILABLE; |
210 | /* If the variable can be overwritten, return OVERWRITABLE. Takes | |
211 | care of at least two notable extensions - the COMDAT variables | |
212 | used to share template instantiations in C++. */ | |
960bfb69 | 213 | if (!decl_replaceable_p (node->symbol.decl)) |
8a4a83ed JH |
214 | return AVAIL_OVERWRITABLE; |
215 | return AVAIL_AVAILABLE; | |
216 | } | |
217 | ||
66058468 JH |
218 | void |
219 | varpool_analyze_node (struct varpool_node *node) | |
8a4a83ed | 220 | { |
66058468 | 221 | tree decl = node->symbol.decl; |
8a4a83ed | 222 | |
66058468 JH |
223 | /* When reading back varpool at LTO time, we re-construct the queue in order |
224 | to have "needed" list right by inserting all needed nodes into varpool. | |
225 | We however don't want to re-analyze already analyzed nodes. */ | |
226 | if (!node->analyzed) | |
8a4a83ed | 227 | { |
66058468 JH |
228 | gcc_assert (!in_lto_p || cgraph_function_flags_ready); |
229 | /* Compute the alignment early so function body expanders are | |
230 | already informed about increased alignment. */ | |
231 | align_variable (decl, 0); | |
232 | } | |
233 | if (node->alias && node->alias_of) | |
234 | { | |
235 | struct varpool_node *tgt = varpool_node (node->alias_of); | |
236 | struct varpool_node *n; | |
237 | ||
238 | for (n = tgt; n && n->alias; | |
239 | n = n->analyzed ? varpool_alias_aliased_node (n) : NULL) | |
240 | if (n == node) | |
241 | { | |
242 | error ("variable %q+D part of alias cycle", node->symbol.decl); | |
243 | node->alias = false; | |
244 | continue; | |
245 | } | |
246 | if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references)) | |
247 | ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL); | |
66058468 | 248 | if (node->extra_name_alias) |
cd35bcf7 | 249 | { |
66058468 | 250 | DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of); |
66058468 JH |
251 | DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of); |
252 | DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of); | |
65d630d4 JH |
253 | fixup_same_cpp_alias_visibility ((symtab_node) node, |
254 | (symtab_node) tgt, node->alias_of); | |
9f90e80a | 255 | } |
8a4a83ed | 256 | } |
66058468 JH |
257 | else if (DECL_INITIAL (decl)) |
258 | record_references_in_initializer (decl, node->analyzed); | |
259 | node->analyzed = true; | |
8a4a83ed JH |
260 | } |
261 | ||
cd35bcf7 JH |
262 | /* Assemble thunks and aliases asociated to NODE. */ |
263 | ||
264 | static void | |
265 | assemble_aliases (struct varpool_node *node) | |
266 | { | |
267 | int i; | |
268 | struct ipa_ref *ref; | |
5932a4d4 | 269 | for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) |
cd35bcf7 JH |
270 | if (ref->use == IPA_REF_ALIAS) |
271 | { | |
5932a4d4 | 272 | struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); |
07250f0e | 273 | do_assemble_alias (alias->symbol.decl, |
cd35bcf7 JH |
274 | DECL_ASSEMBLER_NAME (alias->alias_of)); |
275 | assemble_aliases (alias); | |
276 | } | |
277 | } | |
278 | ||
8a4a83ed | 279 | /* Output one variable, if necessary. Return whether we output it. */ |
0d6bf48c | 280 | |
8a4a83ed JH |
281 | bool |
282 | varpool_assemble_decl (struct varpool_node *node) | |
283 | { | |
960bfb69 | 284 | tree decl = node->symbol.decl; |
8a4a83ed | 285 | |
0d6bf48c JH |
286 | /* Aliases are outout when their target is produced or by |
287 | output_weakrefs. */ | |
288 | if (node->alias) | |
289 | return false; | |
290 | ||
291 | /* Constant pool is output from RTL land when the reference | |
292 | survive till this level. */ | |
8fc17ddc | 293 | if (DECL_IN_CONSTANT_POOL (decl) && TREE_ASM_WRITTEN (decl)) |
0d6bf48c JH |
294 | return false; |
295 | ||
296 | /* Decls with VALUE_EXPR should not be in the varpool at all. They | |
297 | are not real variables, but just info for debugging and codegen. | |
298 | Unfortunately at the moment emutls is not updating varpool correctly | |
299 | after turning real vars into value_expr vars. */ | |
300 | if (DECL_HAS_VALUE_EXPR_P (decl) | |
301 | && !targetm.have_tls) | |
302 | return false; | |
303 | ||
304 | gcc_checking_assert (!TREE_ASM_WRITTEN (decl) | |
305 | && TREE_CODE (decl) == VAR_DECL | |
306 | && !DECL_HAS_VALUE_EXPR_P (decl)); | |
307 | ||
308 | if (!node->symbol.in_other_partition | |
309 | && !DECL_EXTERNAL (decl)) | |
8a4a83ed JH |
310 | { |
311 | assemble_variable (decl, 0, 1, 0); | |
0d6bf48c JH |
312 | gcc_assert (TREE_ASM_WRITTEN (decl)); |
313 | node->finalized = 1; | |
314 | assemble_aliases (node); | |
315 | return true; | |
8a4a83ed JH |
316 | } |
317 | ||
318 | return false; | |
319 | } | |
320 | ||
66058468 JH |
321 | /* Add NODE to queue starting at FIRST. |
322 | The queue is linked via AUX pointers and terminated by pointer to 1. */ | |
323 | ||
324 | static void | |
325 | enqueue_node (struct varpool_node *node, struct varpool_node **first) | |
326 | { | |
327 | if (node->symbol.aux) | |
328 | return; | |
329 | gcc_checking_assert (*first); | |
330 | node->symbol.aux = *first; | |
331 | *first = node; | |
332 | } | |
333 | ||
8a4a83ed | 334 | /* Optimization of function bodies might've rendered some variables as |
66058468 JH |
335 | unnecessary so we want to avoid these from being compiled. Re-do |
336 | reachability starting from variables that are either externally visible | |
337 | or was referred from the asm output routines. */ | |
8a4a83ed | 338 | |
65d630d4 | 339 | static void |
8a4a83ed JH |
340 | varpool_remove_unreferenced_decls (void) |
341 | { | |
66058468 JH |
342 | struct varpool_node *next, *node; |
343 | struct varpool_node *first = (struct varpool_node *)(void *)1; | |
344 | int i; | |
345 | struct ipa_ref *ref; | |
8a4a83ed | 346 | |
1da2ed5f | 347 | if (seen_error ()) |
8a4a83ed JH |
348 | return; |
349 | ||
66058468 JH |
350 | if (cgraph_dump_file) |
351 | fprintf (cgraph_dump_file, "Trivially needed variables:"); | |
66058468 | 352 | FOR_EACH_DEFINED_VARIABLE (node) |
8a4a83ed | 353 | { |
df7705b1 JH |
354 | if (node->analyzed |
355 | && (!varpool_can_remove_if_no_refs (node) | |
356 | /* We just expanded all function bodies. See if any of | |
357 | them needed the variable. */ | |
6649df51 JH |
358 | || (!DECL_EXTERNAL (node->symbol.decl) |
359 | && DECL_RTL_SET_P (node->symbol.decl)))) | |
66058468 JH |
360 | { |
361 | enqueue_node (node, &first); | |
362 | if (cgraph_dump_file) | |
363 | fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); | |
364 | } | |
365 | } | |
366 | while (first != (struct varpool_node *)(void *)1) | |
367 | { | |
368 | node = first; | |
369 | first = (struct varpool_node *)first->symbol.aux; | |
8a4a83ed | 370 | |
66058468 JH |
371 | if (node->symbol.same_comdat_group) |
372 | { | |
373 | symtab_node next; | |
374 | for (next = node->symbol.same_comdat_group; | |
375 | next != (symtab_node)node; | |
376 | next = next->symbol.same_comdat_group) | |
377 | if (symtab_variable_p (next) | |
378 | && varpool (next)->analyzed) | |
379 | enqueue_node (varpool (next), &first); | |
380 | } | |
381 | for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) | |
382 | if (symtab_variable_p (ref->referred) | |
6649df51 JH |
383 | && (!DECL_EXTERNAL (ref->referred->symbol.decl) |
384 | || varpool (ref->referred)->alias) | |
66058468 JH |
385 | && varpool (ref->referred)->analyzed) |
386 | enqueue_node (varpool (ref->referred), &first); | |
8a4a83ed | 387 | } |
66058468 JH |
388 | if (cgraph_dump_file) |
389 | fprintf (cgraph_dump_file, "\nRemoving variables:"); | |
390 | for (node = varpool_first_defined_variable (); node; node = next) | |
391 | { | |
392 | next = varpool_next_defined_variable (node); | |
393 | if (!node->symbol.aux) | |
394 | { | |
395 | if (cgraph_dump_file) | |
396 | fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); | |
397 | varpool_remove_node (node); | |
398 | } | |
399 | } | |
400 | if (cgraph_dump_file) | |
401 | fprintf (cgraph_dump_file, "\n"); | |
8a4a83ed JH |
402 | } |
403 | ||
7fece979 JJ |
404 | /* For variables in named sections make sure get_variable_section |
405 | is called before we switch to those sections. Then section | |
406 | conflicts between read-only and read-only requiring relocations | |
407 | sections can be resolved. */ | |
408 | void | |
409 | varpool_finalize_named_section_flags (struct varpool_node *node) | |
410 | { | |
960bfb69 | 411 | if (!TREE_ASM_WRITTEN (node->symbol.decl) |
7fece979 | 412 | && !node->alias |
960bfb69 JH |
413 | && !node->symbol.in_other_partition |
414 | && !DECL_EXTERNAL (node->symbol.decl) | |
415 | && TREE_CODE (node->symbol.decl) == VAR_DECL | |
416 | && !DECL_HAS_VALUE_EXPR_P (node->symbol.decl) | |
417 | && DECL_SECTION_NAME (node->symbol.decl)) | |
418 | get_variable_section (node->symbol.decl, false); | |
7fece979 JJ |
419 | } |
420 | ||
8a4a83ed JH |
421 | /* Output all variables enqueued to be assembled. */ |
422 | bool | |
65d630d4 | 423 | varpool_output_variables (void) |
8a4a83ed JH |
424 | { |
425 | bool changed = false; | |
7fece979 | 426 | struct varpool_node *node; |
8a4a83ed | 427 | |
1da2ed5f | 428 | if (seen_error ()) |
8a4a83ed JH |
429 | return false; |
430 | ||
65d630d4 JH |
431 | varpool_remove_unreferenced_decls (); |
432 | ||
49ba8180 | 433 | timevar_push (TV_VAROUT); |
8a4a83ed | 434 | |
65c70e6b | 435 | FOR_EACH_DEFINED_VARIABLE (node) |
7fece979 JJ |
436 | varpool_finalize_named_section_flags (node); |
437 | ||
66058468 JH |
438 | FOR_EACH_DEFINED_VARIABLE (node) |
439 | if (varpool_assemble_decl (node)) | |
440 | changed = true; | |
49ba8180 | 441 | timevar_pop (TV_VAROUT); |
8a4a83ed JH |
442 | return changed; |
443 | } | |
444 | ||
43d861a5 RL |
445 | /* Create a new global variable of type TYPE. */ |
446 | tree | |
447 | add_new_static_var (tree type) | |
448 | { | |
449 | tree new_decl; | |
450 | struct varpool_node *new_node; | |
451 | ||
452 | new_decl = create_tmp_var (type, NULL); | |
453 | DECL_NAME (new_decl) = create_tmp_var_name (NULL); | |
454 | TREE_READONLY (new_decl) = 0; | |
455 | TREE_STATIC (new_decl) = 1; | |
456 | TREE_USED (new_decl) = 1; | |
457 | DECL_CONTEXT (new_decl) = NULL_TREE; | |
458 | DECL_ABSTRACT (new_decl) = 0; | |
459 | lang_hooks.dup_lang_specific_decl (new_decl); | |
43d861a5 | 460 | new_node = varpool_node (new_decl); |
43d861a5 RL |
461 | varpool_finalize_decl (new_decl); |
462 | ||
960bfb69 | 463 | return new_node->symbol.decl; |
43d861a5 RL |
464 | } |
465 | ||
2c71ac78 JM |
466 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
467 | Extra name aliases are output whenever DECL is output. */ | |
468 | ||
051f8cc6 | 469 | struct varpool_node * |
cd35bcf7 | 470 | varpool_create_variable_alias (tree alias, tree decl) |
2c71ac78 | 471 | { |
cd35bcf7 | 472 | struct varpool_node *alias_node; |
2c71ac78 JM |
473 | |
474 | gcc_assert (TREE_CODE (decl) == VAR_DECL); | |
475 | gcc_assert (TREE_CODE (alias) == VAR_DECL); | |
cd35bcf7 JH |
476 | alias_node = varpool_node (alias); |
477 | alias_node->alias = 1; | |
ead84f73 | 478 | alias_node->finalized = 1; |
cd35bcf7 | 479 | alias_node->alias_of = decl; |
66058468 JH |
480 | |
481 | /* Extra name alias mechanizm creates aliases really late | |
482 | via DECL_ASSEMBLER_NAME mechanizm. | |
483 | This is unfortunate because they are not going through the | |
484 | standard channels. Ensure they get output. */ | |
485 | if (cgraph_state >= CGRAPH_STATE_IPA) | |
486 | { | |
487 | varpool_analyze_node (alias_node); | |
488 | if (TREE_PUBLIC (alias)) | |
489 | alias_node->symbol.externally_visible = true; | |
490 | } | |
cd35bcf7 JH |
491 | return alias_node; |
492 | } | |
2c71ac78 | 493 | |
cd35bcf7 JH |
494 | /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. |
495 | Extra name aliases are output whenever DECL is output. */ | |
2c71ac78 | 496 | |
cd35bcf7 JH |
497 | struct varpool_node * |
498 | varpool_extra_name_alias (tree alias, tree decl) | |
499 | { | |
500 | struct varpool_node *alias_node; | |
2c71ac78 | 501 | |
cd35bcf7 JH |
502 | #ifndef ASM_OUTPUT_DEF |
503 | /* If aliases aren't supported by the assembler, fail. */ | |
504 | return NULL; | |
505 | #endif | |
506 | alias_node = varpool_create_variable_alias (alias, decl); | |
507 | alias_node->extra_name_alias = true; | |
051f8cc6 JH |
508 | return alias_node; |
509 | } | |
510 | ||
cd35bcf7 JH |
511 | /* Call calback on NODE and aliases asociated to NODE. |
512 | When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are | |
513 | skipped. */ | |
514 | ||
515 | bool | |
516 | varpool_for_node_and_aliases (struct varpool_node *node, | |
517 | bool (*callback) (struct varpool_node *, void *), | |
518 | void *data, | |
519 | bool include_overwritable) | |
520 | { | |
521 | int i; | |
522 | struct ipa_ref *ref; | |
523 | ||
524 | if (callback (node, data)) | |
525 | return true; | |
5932a4d4 | 526 | for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) |
cd35bcf7 JH |
527 | if (ref->use == IPA_REF_ALIAS) |
528 | { | |
5932a4d4 | 529 | struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); |
cd35bcf7 JH |
530 | if (include_overwritable |
531 | || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) | |
532 | if (varpool_for_node_and_aliases (alias, callback, data, | |
533 | include_overwritable)) | |
534 | return true; | |
535 | } | |
536 | return false; | |
537 | } |