Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-visibility.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* IPA visibility pass | |
2 Copyright (C) 2003-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 /* This file implements two related passes: | |
21 | |
22 - pass_data_ipa_function_and_variable_visibility run just after | |
23 symbol table, references and callgraph are built | |
24 | |
25 - pass_data_ipa_function_and_variable_visibility run as first | |
26 proper IPA pass (that is after early optimization, or, (with LTO) | |
27 as a first pass done at link-time. | |
28 | |
29 Purpose of both passes is to set correctly visibility properties | |
30 of all symbols. This includes: | |
31 | |
32 - Symbol privatization: | |
33 | |
34 Some symbols that are declared public by frontend may be | |
35 turned local (either by -fwhole-program flag, by linker plugin feedback | |
36 or by other reasons) | |
37 | |
38 - Discovery of local functions: | |
39 | |
40 A local function is one whose calls can occur only in the current | |
41 compilation unit and all its calls are explicit, so we can change | |
42 its calling convention. We simply mark all static functions whose | |
43 address is not taken as local. | |
44 | |
45 externally_visible flag is set for symbols that can not be privatized. | |
46 For privatized symbols we clear TREE_PUBLIC flag and dismantle comdat | |
47 group. | |
48 | |
49 - Dismantling of comdat groups: | |
50 | |
51 Comdat group represent a section that may be replaced by linker by | |
52 a different copy of the same section from other unit. | |
53 If we have resolution information (from linker plugin) and we know that | |
54 a given comdat gorup is prevailing, we can dismantle it and turn symbols | |
55 into normal symbols. If the resolution information says that the | |
56 section was previaled by copy from non-LTO code, we can also dismantle | |
57 it and turn all symbols into external. | |
58 | |
59 - Local aliases: | |
60 | |
61 Some symbols can be interposed by dynamic linker. Refering to these | |
62 symbols is expensive, since it needs to be overwritable by the dynamic | |
63 linker. In some cases we know that the interposition does not change | |
64 semantic and we can always refer to a local copy (as in the case of | |
65 inline function). In this case we produce a local alias and redirect | |
66 calls to it. | |
67 | |
68 TODO: This should be done for references, too. | |
69 | |
70 - Removal of static ocnstructors and destructors that have no side effects. | |
71 | |
72 - Regularization of several oddities introduced by frontends that may | |
73 be impractical later in the optimization queue. */ | |
74 | |
75 #include "config.h" | |
76 #include "system.h" | |
77 #include "coretypes.h" | |
78 #include "tm.h" | |
79 #include "function.h" | |
80 #include "tree.h" | |
81 #include "gimple-expr.h" | |
82 #include "tree-pass.h" | |
83 #include "cgraph.h" | |
84 #include "calls.h" | |
85 #include "varasm.h" | |
86 #include "ipa-utils.h" | |
87 #include "stringpool.h" | |
88 #include "attribs.h" | |
89 | |
90 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */ | |
91 | |
92 static bool | |
93 non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) | |
94 { | |
95 return !(node->only_called_directly_or_aliased_p () | |
96 /* i386 would need update to output thunk with local calling | |
97 conventions. */ | |
98 && !node->thunk.thunk_p | |
99 && node->definition | |
100 && !DECL_EXTERNAL (node->decl) | |
101 && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)) | |
102 && !node->externally_visible | |
103 && !node->used_from_other_partition | |
104 && !node->in_other_partition | |
105 && node->get_availability () >= AVAIL_AVAILABLE); | |
106 } | |
107 | |
108 /* Return true when function can be marked local. */ | |
109 | |
110 bool | |
111 cgraph_node::local_p (void) | |
112 { | |
113 cgraph_node *n = ultimate_alias_target (); | |
114 | |
115 if (n->thunk.thunk_p) | |
116 return n->callees->callee->local_p (); | |
117 return !n->call_for_symbol_thunks_and_aliases (non_local_p, | |
118 NULL, true); | |
119 | |
120 } | |
121 | |
122 /* A helper for comdat_can_be_unshared_p. */ | |
123 | |
124 static bool | |
125 comdat_can_be_unshared_p_1 (symtab_node *node) | |
126 { | |
127 if (!node->externally_visible) | |
128 return true; | |
129 if (node->address_can_be_compared_p ()) | |
130 { | |
131 struct ipa_ref *ref; | |
132 | |
133 for (unsigned int i = 0; node->iterate_referring (i, ref); i++) | |
134 if (ref->address_matters_p ()) | |
135 return false; | |
136 } | |
137 | |
138 /* If the symbol is used in some weird way, better to not touch it. */ | |
139 if (node->force_output) | |
140 return false; | |
141 | |
142 /* Explicit instantiations needs to be output when possibly | |
143 used externally. */ | |
144 if (node->forced_by_abi | |
145 && TREE_PUBLIC (node->decl) | |
146 && (node->resolution != LDPR_PREVAILING_DEF_IRONLY | |
147 && !flag_whole_program)) | |
148 return false; | |
149 | |
150 /* Non-readonly and volatile variables can not be duplicated. */ | |
151 if (is_a <varpool_node *> (node) | |
152 && (!TREE_READONLY (node->decl) | |
153 || TREE_THIS_VOLATILE (node->decl))) | |
154 return false; | |
155 return true; | |
156 } | |
157 | |
158 /* COMDAT functions must be shared only if they have address taken, | |
159 otherwise we can produce our own private implementation with | |
160 -fwhole-program. | |
161 Return true when turning COMDAT function static can not lead to wrong | |
162 code when the resulting object links with a library defining same COMDAT. | |
163 | |
164 Virtual functions do have their addresses taken from the vtables, | |
165 but in C++ there is no way to compare their addresses for equality. */ | |
166 | |
167 static bool | |
168 comdat_can_be_unshared_p (symtab_node *node) | |
169 { | |
170 if (!comdat_can_be_unshared_p_1 (node)) | |
171 return false; | |
172 if (node->same_comdat_group) | |
173 { | |
174 symtab_node *next; | |
175 | |
176 /* If more than one function is in the same COMDAT group, it must | |
177 be shared even if just one function in the comdat group has | |
178 address taken. */ | |
179 for (next = node->same_comdat_group; | |
180 next != node; next = next->same_comdat_group) | |
181 if (!comdat_can_be_unshared_p_1 (next)) | |
182 return false; | |
183 } | |
184 return true; | |
185 } | |
186 | |
187 /* Return true when function NODE should be considered externally visible. */ | |
188 | |
189 static bool | |
190 cgraph_externally_visible_p (struct cgraph_node *node, | |
191 bool whole_program) | |
192 { | |
193 while (node->transparent_alias && node->definition) | |
194 node = node->get_alias_target (); | |
195 if (!node->definition) | |
196 return false; | |
197 if (!TREE_PUBLIC (node->decl) | |
198 || DECL_EXTERNAL (node->decl)) | |
199 return false; | |
200 | |
201 /* Do not try to localize built-in functions yet. One of problems is that we | |
202 end up mangling their asm for WHOPR that makes it impossible to call them | |
203 using the implicit built-in declarations anymore. Similarly this enables | |
204 us to remove them as unreachable before actual calls may appear during | |
205 expansion or folding. */ | |
206 if (DECL_BUILT_IN (node->decl)) | |
207 return true; | |
208 | |
209 /* If linker counts on us, we must preserve the function. */ | |
210 if (node->used_from_object_file_p ()) | |
211 return true; | |
212 if (DECL_PRESERVE_P (node->decl)) | |
213 return true; | |
214 if (lookup_attribute ("externally_visible", | |
215 DECL_ATTRIBUTES (node->decl))) | |
216 return true; | |
217 if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))) | |
218 return true; | |
219 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES | |
220 && lookup_attribute ("dllexport", | |
221 DECL_ATTRIBUTES (node->decl))) | |
222 return true; | |
223 if (node->resolution == LDPR_PREVAILING_DEF_IRONLY) | |
224 return false; | |
225 /* When doing LTO or whole program, we can bring COMDAT functoins static. | |
226 This improves code quality and we know we will duplicate them at most twice | |
227 (in the case that we are not using plugin and link with object file | |
228 implementing same COMDAT) */ | |
229 if (((in_lto_p || whole_program) && !flag_incremental_link) | |
230 && DECL_COMDAT (node->decl) | |
231 && comdat_can_be_unshared_p (node)) | |
232 return false; | |
233 | |
234 /* When doing link time optimizations, hidden symbols become local. */ | |
235 if ((in_lto_p && !flag_incremental_link) | |
236 && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN | |
237 || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL) | |
238 /* Be sure that node is defined in IR file, not in other object | |
239 file. In that case we don't set used_from_other_object_file. */ | |
240 && node->definition) | |
241 ; | |
242 else if (!whole_program) | |
243 return true; | |
244 | |
245 if (MAIN_NAME_P (DECL_NAME (node->decl))) | |
246 return true; | |
247 | |
248 if (node->instrumentation_clone | |
249 && MAIN_NAME_P (DECL_NAME (node->orig_decl))) | |
250 return true; | |
251 | |
252 return false; | |
253 } | |
254 | |
255 /* Return true when variable should be considered externally visible. */ | |
256 | |
257 bool | |
258 varpool_node::externally_visible_p (void) | |
259 { | |
260 while (transparent_alias && definition) | |
261 return get_alias_target ()->externally_visible_p (); | |
262 if (DECL_EXTERNAL (decl)) | |
263 return true; | |
264 | |
265 if (!TREE_PUBLIC (decl)) | |
266 return false; | |
267 | |
268 /* If linker counts on us, we must preserve the function. */ | |
269 if (used_from_object_file_p ()) | |
270 return true; | |
271 | |
272 /* Bringing TLS variables local may cause dynamic linker failures | |
273 on limits of static TLS vars. */ | |
274 if (DECL_THREAD_LOCAL_P (decl) | |
275 && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED | |
276 && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC)) | |
277 return true; | |
278 | |
279 if (DECL_HARD_REGISTER (decl)) | |
280 return true; | |
281 if (DECL_PRESERVE_P (decl)) | |
282 return true; | |
283 if (lookup_attribute ("externally_visible", | |
284 DECL_ATTRIBUTES (decl))) | |
285 return true; | |
286 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES | |
287 && lookup_attribute ("dllexport", | |
288 DECL_ATTRIBUTES (decl))) | |
289 return true; | |
290 | |
291 /* See if we have linker information about symbol not being used or | |
292 if we need to make guess based on the declaration. | |
293 | |
294 Even if the linker clams the symbol is unused, never bring internal | |
295 symbols that are declared by user as used or externally visible. | |
296 This is needed for i.e. references from asm statements. */ | |
297 if (used_from_object_file_p ()) | |
298 return true; | |
299 if (resolution == LDPR_PREVAILING_DEF_IRONLY) | |
300 return false; | |
301 | |
302 /* As a special case, the COMDAT virtual tables can be unshared. | |
303 In LTO mode turn vtables into static variables. The variable is readonly, | |
304 so this does not enable more optimization, but referring static var | |
305 is faster for dynamic linking. Also this match logic hidding vtables | |
306 from LTO symbol tables. */ | |
307 if (((in_lto_p || flag_whole_program) && !flag_incremental_link) | |
308 && DECL_COMDAT (decl) | |
309 && comdat_can_be_unshared_p (this)) | |
310 return false; | |
311 | |
312 /* When doing link time optimizations, hidden symbols become local. */ | |
313 if (in_lto_p && !flag_incremental_link | |
314 && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN | |
315 || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL) | |
316 /* Be sure that node is defined in IR file, not in other object | |
317 file. In that case we don't set used_from_other_object_file. */ | |
318 && definition) | |
319 ; | |
320 else if (!flag_whole_program) | |
321 return true; | |
322 | |
323 /* Do not attempt to privatize COMDATS by default. | |
324 This would break linking with C++ libraries sharing | |
325 inline definitions. | |
326 | |
327 FIXME: We can do so for readonly vars with no address taken and | |
328 possibly also for vtables since no direct pointer comparsion is done. | |
329 It might be interesting to do so to reduce linking overhead. */ | |
330 if (DECL_COMDAT (decl) || DECL_WEAK (decl)) | |
331 return true; | |
332 return false; | |
333 } | |
334 | |
335 /* Return true if reference to NODE can be replaced by a local alias. | |
336 Local aliases save dynamic linking overhead and enable more optimizations. | |
337 */ | |
338 | |
339 static bool | |
340 can_replace_by_local_alias (symtab_node *node) | |
341 { | |
342 /* If aliases aren't supported, we can't do replacement. */ | |
343 if (!TARGET_SUPPORTS_ALIASES) | |
344 return false; | |
345 | |
346 /* Weakrefs have a reason to be non-local. Be sure we do not replace | |
347 them. */ | |
348 while (node->transparent_alias && node->definition && !node->weakref) | |
349 node = node->get_alias_target (); | |
350 if (node->weakref) | |
351 return false; | |
352 | |
353 return (node->get_availability () > AVAIL_INTERPOSABLE | |
354 && !decl_binds_to_current_def_p (node->decl) | |
355 && !node->can_be_discarded_p ()); | |
356 } | |
357 | |
358 /* Return true if we can replace reference to NODE by local alias | |
359 within a virtual table. Generally we can replace function pointers | |
360 and virtual table pointers. */ | |
361 | |
362 static bool | |
363 can_replace_by_local_alias_in_vtable (symtab_node *node) | |
364 { | |
365 if (is_a <varpool_node *> (node) | |
366 && !DECL_VIRTUAL_P (node->decl)) | |
367 return false; | |
368 return can_replace_by_local_alias (node); | |
369 } | |
370 | |
371 /* walk_tree callback that rewrites initializer references. */ | |
372 | |
373 static tree | |
374 update_vtable_references (tree *tp, int *walk_subtrees, | |
375 void *data ATTRIBUTE_UNUSED) | |
376 { | |
377 if (VAR_OR_FUNCTION_DECL_P (*tp)) | |
378 { | |
379 if (can_replace_by_local_alias_in_vtable (symtab_node::get (*tp))) | |
380 *tp = symtab_node::get (*tp)->noninterposable_alias ()->decl; | |
381 *walk_subtrees = 0; | |
382 } | |
383 else if (IS_TYPE_OR_DECL_P (*tp)) | |
384 *walk_subtrees = 0; | |
385 return NULL; | |
386 } | |
387 | |
388 /* In LTO we can remove COMDAT groups and weak symbols. | |
389 Either turn them into normal symbols or external symbol depending on | |
390 resolution info. */ | |
391 | |
392 static void | |
393 update_visibility_by_resolution_info (symtab_node * node) | |
394 { | |
395 bool define; | |
396 | |
397 if (!node->externally_visible | |
398 || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl)) | |
399 || node->resolution == LDPR_UNKNOWN) | |
400 return; | |
401 | |
402 define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY | |
403 || node->resolution == LDPR_PREVAILING_DEF | |
404 || node->resolution == LDPR_UNDEF | |
405 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); | |
406 | |
407 /* The linker decisions ought to agree in the whole group. */ | |
408 if (node->same_comdat_group) | |
409 for (symtab_node *next = node->same_comdat_group; | |
410 next != node; next = next->same_comdat_group) | |
411 { | |
412 if (!next->externally_visible || next->transparent_alias) | |
413 continue; | |
414 | |
415 bool same_def | |
416 = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY | |
417 || next->resolution == LDPR_PREVAILING_DEF | |
418 || next->resolution == LDPR_UNDEF | |
419 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); | |
420 gcc_assert (in_lto_p || same_def); | |
421 if (!same_def) | |
422 return; | |
423 } | |
424 | |
425 if (node->same_comdat_group) | |
426 for (symtab_node *next = node->same_comdat_group; | |
427 next != node; next = next->same_comdat_group) | |
428 { | |
429 /* During incremental linking we need to keep symbol weak for future | |
430 linking. We can still drop definition if we know non-LTO world | |
431 prevails. */ | |
432 if (!flag_incremental_link) | |
433 { | |
434 DECL_WEAK (next->decl) = false; | |
435 next->set_comdat_group (NULL); | |
436 } | |
437 if (!define) | |
438 { | |
439 if (next->externally_visible) | |
440 DECL_EXTERNAL (next->decl) = true; | |
441 next->set_comdat_group (NULL); | |
442 } | |
443 } | |
444 | |
445 /* During incremental linking we need to keep symbol weak for future | |
446 linking. We can still drop definition if we know non-LTO world prevails. */ | |
447 if (!flag_incremental_link) | |
448 { | |
449 DECL_WEAK (node->decl) = false; | |
450 node->set_comdat_group (NULL); | |
451 node->dissolve_same_comdat_group_list (); | |
452 } | |
453 if (!define) | |
454 { | |
455 DECL_EXTERNAL (node->decl) = true; | |
456 node->set_comdat_group (NULL); | |
457 node->dissolve_same_comdat_group_list (); | |
458 } | |
459 } | |
460 | |
461 /* Try to get rid of weakref. */ | |
462 | |
463 static void | |
464 optimize_weakref (symtab_node *node) | |
465 { | |
466 bool strip_weakref = false; | |
467 bool static_alias = false; | |
468 | |
469 gcc_assert (node->weakref); | |
470 | |
471 /* Weakrefs with no target defined can not be optimized. */ | |
472 if (!node->analyzed) | |
473 return; | |
474 symtab_node *target = node->get_alias_target (); | |
475 | |
476 /* Weakrefs to weakrefs can be optimized only if target can be. */ | |
477 if (target->weakref) | |
478 optimize_weakref (target); | |
479 if (target->weakref) | |
480 return; | |
481 | |
482 /* If we have definition of weakref's target and we know it binds locally, | |
483 we can turn weakref to static alias. */ | |
484 if (TARGET_SUPPORTS_ALIASES | |
485 && target->definition && decl_binds_to_current_def_p (target->decl)) | |
486 strip_weakref = static_alias = true; | |
487 /* Otherwise we can turn weakref into transparent alias. This transformation | |
488 may break asm statements which directly refers to symbol name and expect | |
489 GNU as to translate it via .weakref directive. So do not optimize when | |
490 DECL_PRESERVED is set and .weakref is supported. */ | |
491 else if ((!DECL_PRESERVE_P (target->decl) | |
492 || IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl))) | |
493 && !DECL_WEAK (target->decl) | |
494 && !DECL_EXTERNAL (target->decl) | |
495 && ((target->definition && !target->can_be_discarded_p ()) | |
496 || target->resolution != LDPR_UNDEF)) | |
497 strip_weakref = true; | |
498 if (!strip_weakref) | |
499 return; | |
500 node->weakref = false; | |
501 IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0; | |
502 TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE; | |
503 DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref", | |
504 DECL_ATTRIBUTES | |
505 (node->decl)); | |
506 | |
507 if (dump_file) | |
508 fprintf (dump_file, "Optimizing weakref %s %s\n", | |
509 node->name(), | |
510 static_alias ? "as static alias" : "as transparent alias"); | |
511 | |
512 if (static_alias) | |
513 { | |
514 /* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC. | |
515 be sure it really clears the WEAK flag. */ | |
516 TREE_PUBLIC (node->decl) = true; | |
517 node->make_decl_local (); | |
518 node->forced_by_abi = false; | |
519 node->resolution = LDPR_PREVAILING_DEF_IRONLY; | |
520 node->externally_visible = false; | |
521 gcc_assert (!DECL_WEAK (node->decl)); | |
522 node->transparent_alias = false; | |
523 } | |
524 else | |
525 { | |
526 symtab->change_decl_assembler_name | |
527 (node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl)); | |
528 node->transparent_alias = true; | |
529 node->copy_visibility_from (target); | |
530 } | |
531 gcc_assert (node->alias); | |
532 } | |
533 | |
534 /* NODE is an externally visible definition, which we've discovered is | |
535 not needed externally. Make it local to this compilation. */ | |
536 | |
537 static void | |
538 localize_node (bool whole_program, symtab_node *node) | |
539 { | |
540 gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl)); | |
541 | |
542 /* It is possible that one comdat group contains both hidden and non-hidden | |
543 symbols. In this case we can privatize all hidden symbol but we need | |
544 to keep non-hidden exported. */ | |
545 if (node->same_comdat_group | |
546 && node->resolution == LDPR_PREVAILING_DEF_IRONLY) | |
547 { | |
548 symtab_node *next; | |
549 for (next = node->same_comdat_group; | |
550 next != node; next = next->same_comdat_group) | |
551 if (next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP | |
552 || next->resolution == LDPR_PREVAILING_DEF) | |
553 break; | |
554 if (node != next) | |
555 { | |
556 if (!node->transparent_alias) | |
557 { | |
558 node->resolution = LDPR_PREVAILING_DEF_IRONLY; | |
559 node->make_decl_local (); | |
560 if (!flag_incremental_link) | |
561 node->unique_name |= true; | |
562 return; | |
563 } | |
564 } | |
565 } | |
566 /* For similar reason do not privatize whole comdat when seeing comdat | |
567 local. Wait for non-comdat symbol to be privatized first. */ | |
568 if (node->comdat_local_p ()) | |
569 return; | |
570 | |
571 if (node->same_comdat_group && TREE_PUBLIC (node->decl)) | |
572 { | |
573 for (symtab_node *next = node->same_comdat_group; | |
574 next != node; next = next->same_comdat_group) | |
575 { | |
576 next->set_comdat_group (NULL); | |
577 if (!next->alias) | |
578 next->set_section (NULL); | |
579 if (!next->transparent_alias) | |
580 next->make_decl_local (); | |
581 next->unique_name | |
582 |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY | |
583 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) | |
584 && TREE_PUBLIC (next->decl) | |
585 && !flag_incremental_link); | |
586 } | |
587 | |
588 /* Now everything's localized, the grouping has no meaning, and | |
589 will cause crashes if we keep it around. */ | |
590 node->dissolve_same_comdat_group_list (); | |
591 } | |
592 | |
593 node->unique_name | |
594 |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY | |
595 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) | |
596 && TREE_PUBLIC (node->decl) | |
597 && !flag_incremental_link); | |
598 | |
599 if (TREE_PUBLIC (node->decl)) | |
600 node->set_comdat_group (NULL); | |
601 if (DECL_COMDAT (node->decl) && !node->alias) | |
602 node->set_section (NULL); | |
603 if (!node->transparent_alias) | |
604 { | |
605 node->resolution = LDPR_PREVAILING_DEF_IRONLY; | |
606 node->make_decl_local (); | |
607 } | |
608 } | |
609 | |
610 /* Decide on visibility of all symbols. */ | |
611 | |
612 static unsigned int | |
613 function_and_variable_visibility (bool whole_program) | |
614 { | |
615 struct cgraph_node *node; | |
616 varpool_node *vnode; | |
617 | |
618 /* All aliases should be processed at this point. */ | |
619 gcc_checking_assert (!alias_pairs || !alias_pairs->length ()); | |
620 | |
621 #ifdef ASM_OUTPUT_DEF | |
622 FOR_EACH_DEFINED_FUNCTION (node) | |
623 { | |
624 if (node->get_availability () != AVAIL_INTERPOSABLE | |
625 || DECL_EXTERNAL (node->decl) | |
626 || node->has_aliases_p ()) | |
627 continue; | |
628 | |
629 cgraph_node *alias = 0; | |
630 for (cgraph_edge *e = node->callees; e; e = e->next_callee) | |
631 { | |
632 /* Recursive function calls usually can't be interposed. */ | |
633 | |
634 if (!e->recursive_p ()) | |
635 continue; | |
636 | |
637 if (!alias) | |
638 { | |
639 alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ()); | |
640 gcc_assert (alias && alias != node); | |
641 } | |
642 | |
643 e->redirect_callee (alias); | |
644 if (gimple_has_body_p (e->caller->decl)) | |
645 { | |
646 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); | |
647 e->redirect_call_stmt_to_callee (); | |
648 pop_cfun (); | |
649 } | |
650 } | |
651 } | |
652 #endif | |
653 | |
654 FOR_EACH_FUNCTION (node) | |
655 { | |
656 int flags = flags_from_decl_or_type (node->decl); | |
657 | |
658 /* Optimize away PURE and CONST constructors and destructors. */ | |
659 if (node->analyzed | |
660 && (DECL_STATIC_CONSTRUCTOR (node->decl) | |
661 || DECL_STATIC_DESTRUCTOR (node->decl)) | |
662 && (flags & (ECF_CONST | ECF_PURE)) | |
663 && !(flags & ECF_LOOPING_CONST_OR_PURE) | |
664 && opt_for_fn (node->decl, optimize)) | |
665 { | |
666 DECL_STATIC_CONSTRUCTOR (node->decl) = 0; | |
667 DECL_STATIC_DESTRUCTOR (node->decl) = 0; | |
668 } | |
669 | |
670 /* Frontends and alias code marks nodes as needed before parsing | |
671 is finished. We may end up marking as node external nodes | |
672 where this flag is meaningless strip it. */ | |
673 if (DECL_EXTERNAL (node->decl) || !node->definition) | |
674 { | |
675 node->force_output = 0; | |
676 node->forced_by_abi = 0; | |
677 } | |
678 | |
679 /* C++ FE on lack of COMDAT support create local COMDAT functions | |
680 (that ought to be shared but can not due to object format | |
681 limitations). It is necessary to keep the flag to make rest of C++ FE | |
682 happy. Clear the flag here to avoid confusion in middle-end. */ | |
683 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl)) | |
684 DECL_COMDAT (node->decl) = 0; | |
685 | |
686 /* For external decls stop tracking same_comdat_group. It doesn't matter | |
687 what comdat group they are in when they won't be emitted in this TU. | |
688 | |
689 An exception is LTO where we may end up with both external | |
690 and non-external declarations in the same comdat group in | |
691 the case declarations was not merged. */ | |
692 if (node->same_comdat_group && DECL_EXTERNAL (node->decl) && !in_lto_p) | |
693 { | |
694 if (flag_checking) | |
695 { | |
696 for (symtab_node *n = node->same_comdat_group; | |
697 n != node; | |
698 n = n->same_comdat_group) | |
699 /* If at least one of same comdat group functions is external, | |
700 all of them have to be, otherwise it is a front-end bug. */ | |
701 gcc_assert (DECL_EXTERNAL (n->decl)); | |
702 } | |
703 node->dissolve_same_comdat_group_list (); | |
704 } | |
705 gcc_assert ((!DECL_WEAK (node->decl) | |
706 && !DECL_COMDAT (node->decl)) | |
707 || TREE_PUBLIC (node->decl) | |
708 || node->weakref | |
709 || DECL_EXTERNAL (node->decl)); | |
710 if (cgraph_externally_visible_p (node, whole_program)) | |
711 { | |
712 gcc_assert (!node->global.inlined_to); | |
713 node->externally_visible = true; | |
714 } | |
715 else | |
716 { | |
717 node->externally_visible = false; | |
718 node->forced_by_abi = false; | |
719 } | |
720 if (!node->externally_visible | |
721 && node->definition && !node->weakref | |
722 && !DECL_EXTERNAL (node->decl)) | |
723 localize_node (whole_program, node); | |
724 | |
725 if (node->thunk.thunk_p | |
726 && !node->thunk.add_pointer_bounds_args | |
727 && TREE_PUBLIC (node->decl)) | |
728 { | |
729 struct cgraph_node *decl_node = node; | |
730 | |
731 decl_node = decl_node->callees->callee->function_symbol (); | |
732 | |
733 /* Thunks have the same visibility as function they are attached to. | |
734 Make sure the C++ front end set this up properly. */ | |
735 if (DECL_ONE_ONLY (decl_node->decl)) | |
736 { | |
737 gcc_checking_assert (DECL_COMDAT (node->decl) | |
738 == DECL_COMDAT (decl_node->decl)); | |
739 gcc_checking_assert (node->in_same_comdat_group_p (decl_node)); | |
740 gcc_checking_assert (node->same_comdat_group); | |
741 } | |
742 node->forced_by_abi = decl_node->forced_by_abi; | |
743 if (DECL_EXTERNAL (decl_node->decl)) | |
744 DECL_EXTERNAL (node->decl) = 1; | |
745 } | |
746 | |
747 update_visibility_by_resolution_info (node); | |
748 if (node->weakref) | |
749 optimize_weakref (node); | |
750 } | |
751 FOR_EACH_DEFINED_FUNCTION (node) | |
752 { | |
753 if (!node->local.local) | |
754 node->local.local |= node->local_p (); | |
755 | |
756 /* If we know that function can not be overwritten by a | |
757 different semantics and moreover its section can not be | |
758 discarded, replace all direct calls by calls to an | |
759 noninterposable alias. This make dynamic linking cheaper and | |
760 enable more optimization. | |
761 | |
762 TODO: We can also update virtual tables. */ | |
763 if (node->callers | |
764 && can_replace_by_local_alias (node)) | |
765 { | |
766 cgraph_node *alias = dyn_cast<cgraph_node *> | |
767 (node->noninterposable_alias ()); | |
768 | |
769 if (alias && alias != node) | |
770 { | |
771 while (node->callers) | |
772 { | |
773 struct cgraph_edge *e = node->callers; | |
774 | |
775 e->redirect_callee (alias); | |
776 if (gimple_has_body_p (e->caller->decl)) | |
777 { | |
778 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); | |
779 e->redirect_call_stmt_to_callee (); | |
780 pop_cfun (); | |
781 } | |
782 } | |
783 } | |
784 } | |
785 } | |
786 FOR_EACH_VARIABLE (vnode) | |
787 { | |
788 /* weak flag makes no sense on local variables. */ | |
789 gcc_assert (!DECL_WEAK (vnode->decl) | |
790 || vnode->weakref | |
791 || TREE_PUBLIC (vnode->decl) | |
792 || DECL_EXTERNAL (vnode->decl)); | |
793 /* In several cases declarations can not be common: | |
794 | |
795 - when declaration has initializer | |
796 - when it is in weak | |
797 - when it has specific section | |
798 - when it resides in non-generic address space. | |
799 - if declaration is local, it will get into .local common section | |
800 so common flag is not needed. Frontends still produce these in | |
801 certain cases, such as for: | |
802 | |
803 static int a __attribute__ ((common)) | |
804 | |
805 Canonicalize things here and clear the redundant flag. */ | |
806 if (DECL_COMMON (vnode->decl) | |
807 && (!(TREE_PUBLIC (vnode->decl) | |
808 || DECL_EXTERNAL (vnode->decl)) | |
809 || (DECL_INITIAL (vnode->decl) | |
810 && DECL_INITIAL (vnode->decl) != error_mark_node) | |
811 || DECL_WEAK (vnode->decl) | |
812 || DECL_SECTION_NAME (vnode->decl) != NULL | |
813 || ! (ADDR_SPACE_GENERIC_P | |
814 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl)))))) | |
815 DECL_COMMON (vnode->decl) = 0; | |
816 if (vnode->weakref) | |
817 optimize_weakref (vnode); | |
818 } | |
819 FOR_EACH_DEFINED_VARIABLE (vnode) | |
820 { | |
821 if (!vnode->definition) | |
822 continue; | |
823 if (vnode->externally_visible_p ()) | |
824 vnode->externally_visible = true; | |
825 else | |
826 { | |
827 vnode->externally_visible = false; | |
828 vnode->forced_by_abi = false; | |
829 } | |
830 if (lookup_attribute ("no_reorder", | |
831 DECL_ATTRIBUTES (vnode->decl))) | |
832 vnode->no_reorder = 1; | |
833 | |
834 if (!vnode->externally_visible | |
835 && !vnode->transparent_alias | |
836 && !DECL_EXTERNAL (vnode->decl)) | |
837 localize_node (whole_program, vnode); | |
838 | |
839 update_visibility_by_resolution_info (vnode); | |
840 | |
841 /* Update virtual tables to point to local aliases where possible. */ | |
842 if (DECL_VIRTUAL_P (vnode->decl) | |
843 && !DECL_EXTERNAL (vnode->decl)) | |
844 { | |
845 int i; | |
846 struct ipa_ref *ref; | |
847 bool found = false; | |
848 | |
849 /* See if there is something to update. */ | |
850 for (i = 0; vnode->iterate_reference (i, ref); i++) | |
851 if (ref->use == IPA_REF_ADDR | |
852 && can_replace_by_local_alias_in_vtable (ref->referred)) | |
853 { | |
854 found = true; | |
855 break; | |
856 } | |
857 if (found) | |
858 { | |
859 hash_set<tree> visited_nodes; | |
860 | |
861 vnode->get_constructor (); | |
862 walk_tree (&DECL_INITIAL (vnode->decl), | |
863 update_vtable_references, NULL, &visited_nodes); | |
864 vnode->remove_all_references (); | |
865 record_references_in_initializer (vnode->decl, false); | |
866 } | |
867 } | |
868 } | |
869 | |
870 if (dump_file) | |
871 { | |
872 fprintf (dump_file, "\nMarking local functions:"); | |
873 FOR_EACH_DEFINED_FUNCTION (node) | |
874 if (node->local.local) | |
875 fprintf (dump_file, " %s", node->name ()); | |
876 fprintf (dump_file, "\n\n"); | |
877 fprintf (dump_file, "\nMarking externally visible functions:"); | |
878 FOR_EACH_DEFINED_FUNCTION (node) | |
879 if (node->externally_visible) | |
880 fprintf (dump_file, " %s", node->name ()); | |
881 fprintf (dump_file, "\n\n"); | |
882 fprintf (dump_file, "\nMarking externally visible variables:"); | |
883 FOR_EACH_DEFINED_VARIABLE (vnode) | |
884 if (vnode->externally_visible) | |
885 fprintf (dump_file, " %s", vnode->name ()); | |
886 fprintf (dump_file, "\n\n"); | |
887 } | |
888 symtab->function_flags_ready = true; | |
889 return 0; | |
890 } | |
891 | |
892 /* Local function pass handling visibilities. This happens before LTO streaming | |
893 so in particular -fwhole-program should be ignored at this level. */ | |
894 | |
895 namespace { | |
896 | |
897 const pass_data pass_data_ipa_function_and_variable_visibility = | |
898 { | |
899 SIMPLE_IPA_PASS, /* type */ | |
900 "visibility", /* name */ | |
901 OPTGROUP_NONE, /* optinfo_flags */ | |
902 TV_CGRAPHOPT, /* tv_id */ | |
903 0, /* properties_required */ | |
904 0, /* properties_provided */ | |
905 0, /* properties_destroyed */ | |
906 0, /* todo_flags_start */ | |
907 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */ | |
908 }; | |
909 | |
910 /* Bring functions local at LTO time with -fwhole-program. */ | |
911 | |
912 static unsigned int | |
913 whole_program_function_and_variable_visibility (void) | |
914 { | |
915 function_and_variable_visibility (flag_whole_program); | |
916 if (optimize || in_lto_p) | |
917 ipa_discover_readonly_nonaddressable_vars (); | |
918 return 0; | |
919 } | |
920 | |
921 } // anon namespace | |
922 | |
923 namespace { | |
924 | |
925 const pass_data pass_data_ipa_whole_program_visibility = | |
926 { | |
927 IPA_PASS, /* type */ | |
928 "whole-program", /* name */ | |
929 OPTGROUP_NONE, /* optinfo_flags */ | |
930 TV_CGRAPHOPT, /* tv_id */ | |
931 0, /* properties_required */ | |
932 0, /* properties_provided */ | |
933 0, /* properties_destroyed */ | |
934 0, /* todo_flags_start */ | |
935 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */ | |
936 }; | |
937 | |
938 class pass_ipa_whole_program_visibility : public ipa_opt_pass_d | |
939 { | |
940 public: | |
941 pass_ipa_whole_program_visibility (gcc::context *ctxt) | |
942 : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt, | |
943 NULL, /* generate_summary */ | |
944 NULL, /* write_summary */ | |
945 NULL, /* read_summary */ | |
946 NULL, /* write_optimization_summary */ | |
947 NULL, /* read_optimization_summary */ | |
948 NULL, /* stmt_fixup */ | |
949 0, /* function_transform_todo_flags_start */ | |
950 NULL, /* function_transform */ | |
951 NULL) /* variable_transform */ | |
952 {} | |
953 | |
954 /* opt_pass methods: */ | |
955 | |
956 virtual bool gate (function *) | |
957 { | |
958 /* Do not re-run on ltrans stage. */ | |
959 return !flag_ltrans; | |
960 } | |
961 virtual unsigned int execute (function *) | |
962 { | |
963 return whole_program_function_and_variable_visibility (); | |
964 } | |
965 | |
966 }; // class pass_ipa_whole_program_visibility | |
967 | |
968 } // anon namespace | |
969 | |
970 ipa_opt_pass_d * | |
971 make_pass_ipa_whole_program_visibility (gcc::context *ctxt) | |
972 { | |
973 return new pass_ipa_whole_program_visibility (ctxt); | |
974 } | |
975 | |
976 class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass | |
977 { | |
978 public: | |
979 pass_ipa_function_and_variable_visibility (gcc::context *ctxt) | |
980 : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility, | |
981 ctxt) | |
982 {} | |
983 | |
984 /* opt_pass methods: */ | |
985 virtual unsigned int execute (function *) | |
986 { | |
987 return function_and_variable_visibility (flag_whole_program && !flag_lto); | |
988 } | |
989 | |
990 }; // class pass_ipa_function_and_variable_visibility | |
991 | |
992 simple_ipa_opt_pass * | |
993 make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt) | |
994 { | |
995 return new pass_ipa_function_and_variable_visibility (ctxt); | |
996 } |