]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraphunit.c
/cp
[thirdparty/gcc.git] / gcc / cgraphunit.c
CommitLineData
da5e1e7c 1/* Driver of optimization process
aed6e608 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
5c8ad8f5 3 2011, 2012 Free Software Foundation, Inc.
ae01b312 4 Contributed by Jan Hubicka
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
8c4c00c1 10Software Foundation; either version 3, or (at your option) any later
ae01b312 11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
8c4c00c1 19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
ae01b312 21
da5e1e7c 22/* This module implements main driver of compilation process.
b0cdf642 23
24 The main scope of this file is to act as an interface in between
da5e1e7c 25 tree based frontends and the backend.
b0cdf642 26
27 The front-end is supposed to use following functionality:
28
29 - cgraph_finalize_function
30
31 This function is called once front-end has parsed whole body of function
32 and it is certain that the function body nor the declaration will change.
33
b326746d 34 (There is one exception needed for implementing GCC extern inline
35 function.)
b0cdf642 36
1d416bd7 37 - varpool_finalize_variable
b0cdf642 38
7bd28bba 39 This function has same behavior as the above but is used for static
b0cdf642 40 variables.
41
cf951b1a 42 - add_asm_node
43
44 Insert new toplevel ASM statement
45
46 - finalize_compilation_unit
b0cdf642 47
b326746d 48 This function is called once (source level) compilation unit is finalized
49 and it will no longer change.
b0cdf642 50
da5e1e7c 51 The symbol table is constructed starting from the trivially needed
52 symbols finalized by the frontend. Functions are lowered into
53 GIMPLE representation and callgraph/reference lists are constructed.
54 Those are used to discover other neccesary functions and variables.
55
56 At the end the bodies of unreachable functions are removed.
b0cdf642 57
b326746d 58 The function can be called multiple times when multiple source level
da5e1e7c 59 compilation units are combined.
b0cdf642 60
cf951b1a 61 - compile
b0cdf642 62
da5e1e7c 63 This passes control to the back-end. Optimizations are performed and
64 final assembler is generated. This is done in the following way. Note
65 that with link time optimization the process is split into three
66 stages (compile time, linktime analysis and parallel linktime as
67 indicated bellow).
68
69 Compile time:
70
71 1) Inter-procedural optimization.
72 (ipa_passes)
73
74 This part is further split into:
75
76 a) early optimizations. These are local passes executed in
77 the topological order on the callgraph.
78
79 The purpose of early optimiations is to optimize away simple
80 things that may otherwise confuse IP analysis. Very simple
81 propagation across the callgraph is done i.e. to discover
82 functions without side effects and simple inlining is performed.
83
84 b) early small interprocedural passes.
85
86 Those are interprocedural passes executed only at compilation
87 time. These include, for exmaple, transational memory lowering,
88 unreachable code removal and other simple transformations.
89
90 c) IP analysis stage. All interprocedural passes do their
91 analysis.
92
93 Interprocedural passes differ from small interprocedural
94 passes by their ability to operate across whole program
95 at linktime. Their analysis stage is performed early to
96 both reduce linking times and linktime memory usage by
97 not having to represent whole program in memory.
98
99 d) LTO sreaming. When doing LTO, everything important gets
100 streamed into the object file.
101
102 Compile time and or linktime analysis stage (WPA):
103
104 At linktime units gets streamed back and symbol table is
105 merged. Function bodies are not streamed in and not
106 available.
107 e) IP propagation stage. All IP passes execute their
108 IP propagation. This is done based on the earlier analysis
109 without having function bodies at hand.
110 f) Ltrans streaming. When doing WHOPR LTO, the program
111 is partitioned and streamed into multple object files.
b0cdf642 112
da5e1e7c 113 Compile time and/or parallel linktime stage (ltrans)
b0cdf642 114
da5e1e7c 115 Each of the object files is streamed back and compiled
116 separately. Now the function bodies becomes available
117 again.
b0cdf642 118
da5e1e7c 119 2) Virtual clone materialization
120 (cgraph_materialize_clone)
b0cdf642 121
da5e1e7c 122 IP passes can produce copies of existing functoins (such
123 as versioned clones or inline clones) without actually
124 manipulating their bodies by creating virtual clones in
125 the callgraph. At this time the virtual clones are
126 turned into real functions
127 3) IP transformation
b0cdf642 128
da5e1e7c 129 All IP passes transform function bodies based on earlier
130 decision of the IP propagation.
b0cdf642 131
da5e1e7c 132 4) late small IP passes
b0cdf642 133
da5e1e7c 134 Simple IP passes working within single program partition.
b0cdf642 135
da5e1e7c 136 5) Expansion
cf951b1a 137 (expand_all_functions)
b0cdf642 138
da5e1e7c 139 At this stage functions that needs to be output into
140 assembler are identified and compiled in topological order
141 6) Output of variables and aliases
142 Now it is known what variable references was not optimized
143 out and thus all variables are output to the file.
b0cdf642 144
da5e1e7c 145 Note that with -fno-toplevel-reorder passes 5 and 6
146 are combined together in cgraph_output_in_order.
b0cdf642 147
da5e1e7c 148 Finally there are functions to manipulate the callgraph from
149 backend.
150 - cgraph_add_new_function is used to add backend produced
151 functions introduced after the unit is finalized.
152 The functions are enqueue for later processing and inserted
153 into callgraph with cgraph_process_new_functions.
121f3051 154
da5e1e7c 155 - cgraph_function_versioning
156
157 produces a copy of function into new one (a version)
158 and apply simple transformations
159*/
acc70efa 160
ae01b312 161#include "config.h"
162#include "system.h"
163#include "coretypes.h"
164#include "tm.h"
165#include "tree.h"
941366fd 166#include "output.h"
b5530559 167#include "rtl.h"
acc70efa 168#include "tree-flow.h"
ae01b312 169#include "tree-inline.h"
170#include "langhooks.h"
c6224531 171#include "pointer-set.h"
ae01b312 172#include "toplev.h"
173#include "flags.h"
174#include "ggc.h"
175#include "debug.h"
176#include "target.h"
177#include "cgraph.h"
80a85d8a 178#include "diagnostic.h"
f79b6507 179#include "timevar.h"
d7c6d889 180#include "params.h"
181#include "fibheap.h"
611e5405 182#include "intl.h"
b69eb0ff 183#include "function.h"
b5d36404 184#include "ipa-prop.h"
75a70cf9 185#include "gimple.h"
186#include "tree-iterator.h"
f1e2a033 187#include "tree-pass.h"
bfec3452 188#include "tree-dump.h"
da5e1e7c 189#include "gimple-pretty-print.h"
c1dcd13c 190#include "output.h"
9ed5b1f5 191#include "coverage.h"
c9036234 192#include "plugin.h"
a41f2a28 193#include "ipa-inline.h"
7771d558 194#include "ipa-utils.h"
a0605d65 195#include "lto-streamer.h"
3db65b62 196#include "except.h"
941366fd 197#include "regset.h" /* FIXME: For reg_obstack. */
d7c6d889 198
ff2a5ada 199/* Queue of cgraph nodes scheduled to be added into cgraph. This is a
200 secondary queue used during optimization to accommodate passes that
201 may generate new functions that need to be optimized and expanded. */
202cgraph_node_set cgraph_new_nodes;
203
cf951b1a 204static void expand_all_functions (void);
205static void mark_functions_to_output (void);
206static void expand_function (struct cgraph_node *);
da5e1e7c 207static void cgraph_analyze_function (struct cgraph_node *);
25bb88de 208
ecb08119 209FILE *cgraph_dump_file;
121f3051 210
cf951b1a 211/* Linked list of cgraph asm nodes. */
212struct asm_node *asm_nodes;
213
214/* Last node in cgraph_asm_nodes. */
215static GTY(()) struct asm_node *asm_last_node;
216
28454517 217/* Used for vtable lookup in thunk adjusting. */
218static GTY (()) tree vtable_entry_type;
219
8efa224a 220/* Determine if function DECL is trivially needed and should stay in the
221 compilation unit. This is used at the symbol table construction time
222 and differs from later logic removing unnecesary functions that can
223 take into account results of analysis, whole program info etc. */
2c0b522d 224
da5e1e7c 225static bool
7bfefa9d 226cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
2c0b522d 227{
3f82b628 228 /* If the user told us it is used, then it must be so. */
8efa224a 229 if (node->symbol.force_output)
05806473 230 return true;
231
8efa224a 232 /* Double check that no one output the function into assembly file
233 early. */
234 gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
235 || (node->thunk.thunk_p || node->same_body_alias)
236 || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
3f82b628 237
55680bef 238
8efa224a 239 /* Keep constructors, destructors and virtual functions. */
240 if (DECL_STATIC_CONSTRUCTOR (decl)
241 || DECL_STATIC_DESTRUCTOR (decl)
242 || (DECL_VIRTUAL_P (decl)
243 && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
244 return true;
2c0b522d 245
246 /* Externally visible functions must be output. The exception is
8efa224a 247 COMDAT functions that must be output only when they are needed. */
8baa9d15 248
8efa224a 249 if (TREE_PUBLIC (decl)
62eec3b4 250 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
2c0b522d 251 return true;
252
2c0b522d 253 return false;
254}
255
ff2a5ada 256/* Head of the queue of nodes to be processed while building callgraph */
257
258static symtab_node first = (symtab_node)(void *)1;
259
260/* Add NODE to queue starting at FIRST.
261 The queue is linked via AUX pointers and terminated by pointer to 1. */
262
263static void
264enqueue_node (symtab_node node)
265{
266 if (node->symbol.aux)
267 return;
268 gcc_checking_assert (first);
269 node->symbol.aux = first;
270 first = node;
271}
272
bdc40eb8 273/* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
523c1122 274 functions into callgraph in a way so they look like ordinary reachable
275 functions inserted into callgraph already at construction time. */
276
277bool
278cgraph_process_new_functions (void)
279{
280 bool output = false;
281 tree fndecl;
282 struct cgraph_node *node;
ff2a5ada 283 cgraph_node_set_iterator csi;
523c1122 284
ff2a5ada 285 if (!cgraph_new_nodes)
286 return false;
523c1122 287 /* Note that this queue may grow as its being processed, as the new
288 functions may generate new ones. */
ff2a5ada 289 for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi))
523c1122 290 {
ff2a5ada 291 node = csi_node (csi);
7d0d0ce1 292 fndecl = node->symbol.decl;
523c1122 293 switch (cgraph_state)
294 {
295 case CGRAPH_STATE_CONSTRUCTION:
296 /* At construction time we just need to finalize function and move
297 it into reachable functions list. */
298
523c1122 299 cgraph_finalize_function (fndecl, false);
523c1122 300 output = true;
4f7a1122 301 cgraph_call_function_insertion_hooks (node);
ff2a5ada 302 enqueue_node ((symtab_node) node);
523c1122 303 break;
304
305 case CGRAPH_STATE_IPA:
f517b36e 306 case CGRAPH_STATE_IPA_SSA:
523c1122 307 /* When IPA optimization already started, do all essential
308 transformations that has been already performed on the whole
309 cgraph but not on this function. */
310
75a70cf9 311 gimple_register_cfg_hooks ();
523c1122 312 if (!node->analyzed)
313 cgraph_analyze_function (node);
314 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
315 current_function_decl = fndecl;
f517b36e 316 if ((cgraph_state == CGRAPH_STATE_IPA_SSA
317 && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
318 /* When not optimizing, be sure we run early local passes anyway
319 to expand OMP. */
320 || !optimize)
20099e35 321 execute_pass_list (pass_early_local_passes.pass.sub);
649597af 322 else
a41f2a28 323 compute_inline_parameters (node, true);
523c1122 324 free_dominance_info (CDI_POST_DOMINATORS);
325 free_dominance_info (CDI_DOMINATORS);
326 pop_cfun ();
327 current_function_decl = NULL;
4f7a1122 328 cgraph_call_function_insertion_hooks (node);
523c1122 329 break;
330
331 case CGRAPH_STATE_EXPANSION:
332 /* Functions created during expansion shall be compiled
333 directly. */
09fc9532 334 node->process = 0;
4f7a1122 335 cgraph_call_function_insertion_hooks (node);
cf951b1a 336 expand_function (node);
523c1122 337 break;
338
339 default:
340 gcc_unreachable ();
341 break;
342 }
343 }
ff2a5ada 344 free_cgraph_node_set (cgraph_new_nodes);
345 cgraph_new_nodes = NULL;
523c1122 346 return output;
347}
348
9b8fb23a 349/* As an GCC extension we allow redefinition of the function. The
350 semantics when both copies of bodies differ is not well defined.
351 We replace the old body with new body so in unit at a time mode
352 we always use new body, while in normal mode we may end up with
353 old body inlined into some functions and new body expanded and
354 inlined in others.
355
356 ??? It may make more sense to use one body for inlining and other
357 body for expanding the function but this is difficult to do. */
358
359static void
360cgraph_reset_node (struct cgraph_node *node)
361{
09fc9532 362 /* If node->process is set, then we have already begun whole-unit analysis.
6329636b 363 This is *not* testing for whether we've already emitted the function.
364 That case can be sort-of legitimately seen with real function redefinition
365 errors. I would argue that the front end should never present us with
366 such a case, but don't enforce that for now. */
09fc9532 367 gcc_assert (!node->process);
9b8fb23a 368
369 /* Reset our data structures so we can analyze the function again. */
370 memset (&node->local, 0, sizeof (node->local));
371 memset (&node->global, 0, sizeof (node->global));
372 memset (&node->rtl, 0, sizeof (node->rtl));
373 node->analyzed = false;
9b8fb23a 374 node->local.finalized = false;
375
9b8fb23a 376 cgraph_node_remove_callees (node);
9b8fb23a 377}
c08871a9 378
9a2639fc 379/* Return true when there are references to NODE. */
380
381static bool
382referred_to_p (symtab_node node)
383{
9a2639fc 384 struct ipa_ref *ref;
385
cf951b1a 386 /* See if there are any refrences at all. */
387 if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
9a2639fc 388 return true;
cf951b1a 389 /* For functions check also calls. */
9a2639fc 390 if (symtab_function_p (node) && cgraph (node)->callers)
391 return true;
392 return false;
393}
394
28df663b 395/* DECL has been parsed. Take it, queue it, compile it at the whim of the
396 logic in effect. If NESTED is true, then our caller cannot stand to have
397 the garbage collector run at the moment. We would need to either create
398 a new GC context, or just not compile right now. */
ae01b312 399
400void
28df663b 401cgraph_finalize_function (tree decl, bool nested)
ae01b312 402{
5a90471f 403 struct cgraph_node *node = cgraph_get_create_node (decl);
ae01b312 404
c08871a9 405 if (node->local.finalized)
443089c1 406 {
407 cgraph_reset_node (node);
408 node->local.redefined_extern_inline = true;
409 }
28df663b 410
c08871a9 411 notice_global_symbol (decl);
79bb87b4 412 node->local.finalized = true;
e27482aa 413 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
ae01b312 414
8efa224a 415 /* With -fkeep-inline-functions we are keeping all inline functions except
416 for extern inline ones. */
417 if (flag_keep_inline_functions
418 && DECL_DECLARED_INLINE_P (decl)
419 && !DECL_EXTERNAL (decl)
420 && !DECL_DISREGARD_INLINE_LIMITS (decl))
421 node->symbol.force_output = 1;
2c0b522d 422
8efa224a 423 /* When not optimizing, also output the static functions. (see
424 PR24561), but don't do so for always_inline functions, functions
425 declared inline and nested functions. These were optimized out
426 in the original implementation and it is unclear whether we want
427 to change the behavior here. */
428 if ((!optimize
429 && !node->same_body_alias
430 && !DECL_DISREGARD_INLINE_LIMITS (decl)
431 && !DECL_DECLARED_INLINE_P (decl)
432 && !(DECL_CONTEXT (decl)
433 && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
434 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
435 node->symbol.force_output = 1;
436
2c0b522d 437 /* If we've not yet emitted decl, tell the debug info about it. */
28df663b 438 if (!TREE_ASM_WRITTEN (decl))
2c0b522d 439 (*debug_hooks->deferred_inline_function) (decl);
4e8871a0 440
b69eb0ff 441 /* Possibly warn about unused parameters. */
442 if (warn_unused_parameter)
443 do_warn_unused_parameter (decl);
6329636b 444
445 if (!nested)
446 ggc_collect ();
9a2639fc 447
448 if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
449 && (cgraph_decide_is_function_needed (node, decl)
450 || referred_to_p ((symtab_node)node)))
451 enqueue_node ((symtab_node)node);
ae01b312 452}
453
3db65b62 454/* Add the function FNDECL to the call graph.
455 Unlike cgraph_finalize_function, this function is intended to be used
456 by middle end and allows insertion of new function at arbitrary point
457 of compilation. The function can be either in high, low or SSA form
458 GIMPLE.
459
460 The function is assumed to be reachable and have address taken (so no
461 API breaking optimizations are performed on it).
462
463 Main work done by this function is to enqueue the function for later
464 processing to avoid need the passes to be re-entrant. */
465
466void
467cgraph_add_new_function (tree fndecl, bool lowered)
468{
469 struct cgraph_node *node;
470 switch (cgraph_state)
471 {
ff2a5ada 472 case CGRAPH_STATE_PARSING:
473 cgraph_finalize_function (fndecl, false);
474 break;
3db65b62 475 case CGRAPH_STATE_CONSTRUCTION:
476 /* Just enqueue function to be processed at nearest occurrence. */
477 node = cgraph_create_node (fndecl);
3db65b62 478 if (lowered)
479 node->lowered = true;
ff2a5ada 480 if (!cgraph_new_nodes)
481 cgraph_new_nodes = cgraph_node_set_new ();
482 cgraph_node_set_add (cgraph_new_nodes, node);
3db65b62 483 break;
484
485 case CGRAPH_STATE_IPA:
486 case CGRAPH_STATE_IPA_SSA:
487 case CGRAPH_STATE_EXPANSION:
488 /* Bring the function into finalized state and enqueue for later
489 analyzing and compilation. */
490 node = cgraph_get_create_node (fndecl);
491 node->local.local = false;
492 node->local.finalized = true;
da751785 493 node->symbol.force_output = true;
3db65b62 494 if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
495 {
496 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
497 current_function_decl = fndecl;
498 gimple_register_cfg_hooks ();
499 bitmap_obstack_initialize (NULL);
500 execute_pass_list (all_lowering_passes);
501 execute_pass_list (pass_early_local_passes.pass.sub);
502 bitmap_obstack_release (NULL);
503 pop_cfun ();
504 current_function_decl = NULL;
505
506 lowered = true;
507 }
508 if (lowered)
509 node->lowered = true;
ff2a5ada 510 if (!cgraph_new_nodes)
511 cgraph_new_nodes = cgraph_node_set_new ();
512 cgraph_node_set_add (cgraph_new_nodes, node);
3db65b62 513 break;
514
515 case CGRAPH_STATE_FINISHED:
516 /* At the very end of compilation we have to do all the work up
517 to expansion. */
518 node = cgraph_create_node (fndecl);
519 if (lowered)
520 node->lowered = true;
521 cgraph_analyze_function (node);
522 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
523 current_function_decl = fndecl;
524 gimple_register_cfg_hooks ();
525 bitmap_obstack_initialize (NULL);
526 if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
527 execute_pass_list (pass_early_local_passes.pass.sub);
528 bitmap_obstack_release (NULL);
3db65b62 529 pop_cfun ();
cf951b1a 530 expand_function (node);
3db65b62 531 current_function_decl = NULL;
532 break;
533
534 default:
535 gcc_unreachable ();
536 }
537
538 /* Set a personality if required and we already passed EH lowering. */
539 if (lowered
540 && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl))
541 == eh_personality_lang))
542 DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
543}
544
cf951b1a 545/* Add a top-level asm statement to the list. */
546
547struct asm_node *
548add_asm_node (tree asm_str)
549{
550 struct asm_node *node;
551
552 node = ggc_alloc_cleared_asm_node ();
553 node->asm_str = asm_str;
554 node->order = symtab_order++;
555 node->next = NULL;
556 if (asm_nodes == NULL)
557 asm_nodes = node;
558 else
559 asm_last_node->next = node;
560 asm_last_node = node;
561 return node;
562}
563
56af936e 564/* Output all asm statements we have stored up to be output. */
565
566static void
cf951b1a 567output_asm_statements (void)
56af936e 568{
cf951b1a 569 struct asm_node *can;
56af936e 570
852f689e 571 if (seen_error ())
56af936e 572 return;
573
cf951b1a 574 for (can = asm_nodes; can; can = can->next)
56af936e 575 assemble_asm (can->asm_str);
cf951b1a 576 asm_nodes = NULL;
577}
578
579/* C++ FE sometimes change linkage flags after producing same body aliases. */
580void
581fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias)
582{
583 DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (alias);
584 if (TREE_PUBLIC (node->symbol.decl))
585 {
586 DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (alias);
587 DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (alias);
588 DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (alias);
589 if (DECL_ONE_ONLY (alias)
590 && !node->symbol.same_comdat_group)
591 symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
592 }
56af936e 593}
594
0785e435 595/* Analyze the function scheduled to be output. */
da5e1e7c 596static void
0785e435 597cgraph_analyze_function (struct cgraph_node *node)
598{
bfec3452 599 tree save = current_function_decl;
7d0d0ce1 600 tree decl = node->symbol.decl;
da5e1e7c 601 location_t saved_loc = input_location;
602 input_location = DECL_SOURCE_LOCATION (decl);
0785e435 603
c70f46b0 604 if (node->alias && node->thunk.alias)
605 {
606 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
b0898cb7 607 struct cgraph_node *n;
608
609 for (n = tgt; n && n->alias;
610 n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL)
611 if (n == node)
612 {
7d0d0ce1 613 error ("function %q+D part of alias cycle", node->symbol.decl);
b0898cb7 614 node->alias = false;
da5e1e7c 615 input_location = saved_loc;
b0898cb7 616 return;
617 }
7d0d0ce1 618 if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
04ec15fa 619 ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
620 IPA_REF_ALIAS, NULL);
c70f46b0 621 if (node->same_body_alias)
622 {
7d0d0ce1 623 DECL_DECLARED_INLINE_P (node->symbol.decl)
c70f46b0 624 = DECL_DECLARED_INLINE_P (node->thunk.alias);
7d0d0ce1 625 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
c70f46b0 626 = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
cf951b1a 627 fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->thunk.alias);
c70f46b0 628 }
629
7d0d0ce1 630 if (node->symbol.address_taken)
c70f46b0 631 cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
c70f46b0 632 }
633 else if (node->thunk.thunk_p)
91bf9d9a 634 {
635 cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
636 NULL, 0, CGRAPH_FREQ_BASE);
637 }
638 else
639 {
640 current_function_decl = decl;
641 push_cfun (DECL_STRUCT_FUNCTION (decl));
bfec3452 642
7d0d0ce1 643 assign_assembler_name_if_neeeded (node->symbol.decl);
6816d0c4 644
91bf9d9a 645 /* Make sure to gimplify bodies only once. During analyzing a
646 function we lower it, which will require gimplified nested
647 functions, so we can end up here with an already gimplified
648 body. */
e3a19533 649 if (!gimple_has_body_p (decl))
91bf9d9a 650 gimplify_function_tree (decl);
651 dump_function (TDI_generic, decl);
bfec3452 652
47199071 653 /* Lower the function. */
654 if (!node->lowered)
655 {
656 if (node->nested)
7d0d0ce1 657 lower_nested_functions (node->symbol.decl);
47199071 658 gcc_assert (!node->nested);
659
660 gimple_register_cfg_hooks ();
661 bitmap_obstack_initialize (NULL);
662 execute_pass_list (all_lowering_passes);
663 free_dominance_info (CDI_POST_DOMINATORS);
664 free_dominance_info (CDI_DOMINATORS);
665 compact_blocks ();
666 bitmap_obstack_release (NULL);
667 node->lowered = true;
668 }
669
91bf9d9a 670 pop_cfun ();
671 }
6e8d6e86 672 node->analyzed = true;
0785e435 673
bfec3452 674 current_function_decl = save;
da5e1e7c 675 input_location = saved_loc;
0785e435 676}
677
c70f46b0 678/* C++ frontend produce same body aliases all over the place, even before PCH
679 gets streamed out. It relies on us linking the aliases with their function
680 in order to do the fixups, but ipa-ref is not PCH safe. Consequentely we
681 first produce aliases without links, but once C++ FE is sure he won't sream
682 PCH we build the links via this function. */
683
684void
685cgraph_process_same_body_aliases (void)
686{
687 struct cgraph_node *node;
7c455d87 688 FOR_EACH_FUNCTION (node)
c70f46b0 689 if (node->same_body_alias
7d0d0ce1 690 && !VEC_length (ipa_ref_t, node->symbol.ref_list.references))
c70f46b0 691 {
692 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
04ec15fa 693 ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
694 IPA_REF_ALIAS, NULL);
c70f46b0 695 }
696 same_body_aliases_done = true;
697}
698
d05db70d 699/* Process attributes common for vars and functions. */
700
701static void
702process_common_attributes (tree decl)
703{
704 tree weakref = lookup_attribute ("weakref", DECL_ATTRIBUTES (decl));
705
706 if (weakref && !lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
707 {
708 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
709 "%<weakref%> attribute should be accompanied with"
710 " an %<alias%> attribute");
711 DECL_WEAK (decl) = 0;
40b32d93 712 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
713 DECL_ATTRIBUTES (decl));
d05db70d 714 }
715}
716
05806473 717/* Look for externally_visible and used attributes and mark cgraph nodes
718 accordingly.
719
720 We cannot mark the nodes at the point the attributes are processed (in
721 handle_*_attribute) because the copy of the declarations available at that
722 point may not be canonical. For example, in:
723
724 void f();
725 void f() __attribute__((used));
726
727 the declaration we see in handle_used_attribute will be the second
728 declaration -- but the front end will subsequently merge that declaration
729 with the original declaration and discard the second declaration.
730
731 Furthermore, we can't mark these nodes in cgraph_finalize_function because:
732
733 void f() {}
734 void f() __attribute__((externally_visible));
735
736 is valid.
737
738 So, we walk the nodes at the end of the translation unit, applying the
739 attributes at that point. */
740
741static void
742process_function_and_variable_attributes (struct cgraph_node *first,
1d416bd7 743 struct varpool_node *first_var)
05806473 744{
745 struct cgraph_node *node;
1d416bd7 746 struct varpool_node *vnode;
05806473 747
0704fb2e 748 for (node = cgraph_first_function (); node != first;
749 node = cgraph_next_function (node))
05806473 750 {
7d0d0ce1 751 tree decl = node->symbol.decl;
83a23b05 752 if (DECL_PRESERVE_P (decl))
8efa224a 753 cgraph_mark_force_output_node (node);
62433d51 754 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
05806473 755 {
7d0d0ce1 756 if (! TREE_PUBLIC (node->symbol.decl))
757 warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
712d2297 758 "%<externally_visible%>"
759 " attribute have effect only on public objects");
05806473 760 }
40b32d93 761 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
c70f46b0 762 && (node->local.finalized && !node->alias))
40b32d93 763 {
7d0d0ce1 764 warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
40b32d93 765 "%<weakref%> attribute ignored"
766 " because function is defined");
767 DECL_WEAK (decl) = 0;
768 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
769 DECL_ATTRIBUTES (decl));
770 }
a522e9eb 771
772 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))
773 && !DECL_DECLARED_INLINE_P (decl)
774 /* redefining extern inline function makes it DECL_UNINLINABLE. */
775 && !DECL_UNINLINABLE (decl))
776 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
777 "always_inline function might not be inlinable");
778
d05db70d 779 process_common_attributes (decl);
05806473 780 }
0704fb2e 781 for (vnode = varpool_first_variable (); vnode != first_var;
782 vnode = varpool_next_variable (vnode))
05806473 783 {
7d0d0ce1 784 tree decl = vnode->symbol.decl;
83a23b05 785 if (DECL_PRESERVE_P (decl))
ff2a5ada 786 vnode->symbol.force_output = true;
62433d51 787 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
05806473 788 {
7d0d0ce1 789 if (! TREE_PUBLIC (vnode->symbol.decl))
790 warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
712d2297 791 "%<externally_visible%>"
792 " attribute have effect only on public objects");
05806473 793 }
40b32d93 794 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
795 && vnode->finalized
796 && DECL_INITIAL (decl))
797 {
7d0d0ce1 798 warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
40b32d93 799 "%<weakref%> attribute ignored"
800 " because variable is initialized");
801 DECL_WEAK (decl) = 0;
802 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
803 DECL_ATTRIBUTES (decl));
804 }
d05db70d 805 process_common_attributes (decl);
05806473 806 }
807}
808
ff2a5ada 809/* Mark DECL as finalized. By finalizing the declaration, frontend instruct the
810 middle end to output the variable to asm file, if needed or externally
811 visible. */
812
813void
814varpool_finalize_decl (tree decl)
815{
816 struct varpool_node *node = varpool_node (decl);
817
818 gcc_assert (TREE_STATIC (decl));
819
820 if (node->finalized)
821 return;
822 notice_global_symbol (decl);
823 node->finalized = true;
824 if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
825 /* Traditionally we do not eliminate static variables when not
826 optimizing and when not doing toplevel reoder. */
827 || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl)
828 && !DECL_ARTIFICIAL (node->symbol.decl)))
829 node->symbol.force_output = true;
830
831 if (cgraph_state == CGRAPH_STATE_CONSTRUCTION
832 && (decide_is_variable_needed (node, decl)
833 || referred_to_p ((symtab_node)node)))
834 enqueue_node ((symtab_node)node);
835 if (cgraph_state >= CGRAPH_STATE_IPA_SSA)
836 varpool_analyze_node (node);
3d1c0354 837 /* Some frontends produce various interface variables after compilation
838 finished. */
839 if (cgraph_state == CGRAPH_STATE_FINISHED)
840 varpool_assemble_decl (node);
ff2a5ada 841}
842
843/* Discover all functions and variables that are trivially needed, analyze
844 them as well as all functions and variables referred by them */
ae01b312 845
aeeb194b 846static void
847cgraph_analyze_functions (void)
ae01b312 848{
c1dcd13c 849 /* Keep track of already processed nodes when called multiple times for
06b27565 850 intermodule optimization. */
c1dcd13c 851 static struct cgraph_node *first_analyzed;
ff2a5ada 852 struct cgraph_node *first_handled = first_analyzed;
1d416bd7 853 static struct varpool_node *first_analyzed_var;
ff2a5ada 854 struct varpool_node *first_handled_var = first_analyzed_var;
855
856 symtab_node node, next;
857 int i;
858 struct ipa_ref *ref;
859 bool changed = true;
ae01b312 860
f1c35659 861 bitmap_obstack_initialize (NULL);
ff2a5ada 862 cgraph_state = CGRAPH_STATE_CONSTRUCTION;
ae01b312 863
ff2a5ada 864 /* Analysis adds static variables that in turn adds references to new functions.
865 So we need to iterate the process until it stabilize. */
866 while (changed)
ae01b312 867 {
ff2a5ada 868 changed = false;
869 process_function_and_variable_attributes (first_analyzed,
870 first_analyzed_var);
871
872 /* First identify the trivially needed symbols. */
873 for (node = symtab_nodes;
874 node != (symtab_node)first_analyzed
875 && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
9b8fb23a 876 {
ff2a5ada 877 if ((symtab_function_p (node)
878 && cgraph (node)->local.finalized
879 && cgraph_decide_is_function_needed (cgraph (node), node->symbol.decl))
880 || (symtab_variable_p (node)
881 && varpool (node)->finalized
882 && !DECL_EXTERNAL (node->symbol.decl)
883 && decide_is_variable_needed (varpool (node), node->symbol.decl)))
884 {
885 enqueue_node (node);
886 if (!changed && cgraph_dump_file)
887 fprintf (cgraph_dump_file, "Trivially needed symbols:");
888 changed = true;
889 if (cgraph_dump_file)
890 fprintf (cgraph_dump_file, " %s", symtab_node_asm_name (node));
891 }
892 if (node == (symtab_node)first_analyzed
893 || node == (symtab_node)first_analyzed_var)
894 break;
9b8fb23a 895 }
ff2a5ada 896 cgraph_process_new_functions ();
897 first_analyzed_var = varpool_first_variable ();
898 first_analyzed = cgraph_first_function ();
638531ad 899
ff2a5ada 900 if (changed && dump_file)
901 fprintf (cgraph_dump_file, "\n");
2c0b522d 902
ff2a5ada 903 /* Lower representation, build callgraph edges and references for all trivially
904 needed symbols and all symbols referred by them. */
905 while (first != (symtab_node)(void *)1)
61c2c7b1 906 {
ff2a5ada 907 changed = true;
908 node = first;
909 first = (symtab_node)first->symbol.aux;
910 if (symtab_function_p (node) && cgraph (node)->local.finalized)
911 {
912 struct cgraph_edge *edge;
913 struct cgraph_node *cnode;
914 tree decl;
915
916 cnode = cgraph (node);
917 decl = cnode->symbol.decl;
918
919 /* ??? It is possible to create extern inline function and later using
920 weak alias attribute to kill its body. See
921 gcc.c-torture/compile/20011119-1.c */
922 if (!DECL_STRUCT_FUNCTION (decl)
923 && (!cnode->alias || !cnode->thunk.alias)
924 && !cnode->thunk.thunk_p)
925 {
926 cgraph_reset_node (cnode);
927 cnode->local.redefined_extern_inline = true;
928 continue;
929 }
61c2c7b1 930
ff2a5ada 931 if (!cnode->analyzed)
932 cgraph_analyze_function (cnode);
d544ceff 933
ff2a5ada 934 for (edge = cnode->callees; edge; edge = edge->next_callee)
da751785 935 if (edge->callee->local.finalized)
936 enqueue_node ((symtab_node)edge->callee);
ff2a5ada 937
938 /* If decl is a clone of an abstract function, mark that abstract
939 function so that we don't release its body. The DECL_INITIAL() of that
940 abstract function declaration will be later needed to output debug
941 info. */
942 if (DECL_ABSTRACT_ORIGIN (decl))
943 {
944 struct cgraph_node *origin_node;
945 origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
946 origin_node->abstract_and_needed = true;
947 }
948
949 }
950 else if (symtab_variable_p (node)
951 && varpool (node)->finalized)
da751785 952 varpool_analyze_node (varpool (node));
ff2a5ada 953
954 if (node->symbol.same_comdat_group)
955 {
956 symtab_node next;
957 for (next = node->symbol.same_comdat_group;
958 next != node;
959 next = next->symbol.same_comdat_group)
960 enqueue_node (next);
961 }
962 for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
963 if ((symtab_function_p (ref->referred) && cgraph (ref->referred)->local.finalized)
964 || (symtab_variable_p (ref->referred) && varpool (ref->referred)->finalized))
965 enqueue_node (ref->referred);
966 cgraph_process_new_functions ();
967 }
ae01b312 968 }
2c0b522d 969
aa5e06c7 970 /* Collect entry points to the unit. */
f79b6507 971 if (cgraph_dump_file)
3d7bfc56 972 {
e4200070 973 fprintf (cgraph_dump_file, "\n\nInitial ");
18841b0c 974 dump_symtab (cgraph_dump_file);
3d7bfc56 975 }
e6d2b2d8 976
f79b6507 977 if (cgraph_dump_file)
ff2a5ada 978 fprintf (cgraph_dump_file, "\nRemoving unused symbols:");
ae01b312 979
ff2a5ada 980 for (node = symtab_nodes;
981 node != (symtab_node)first_handled
982 && node != (symtab_node)first_handled_var; node = next)
ae01b312 983 {
ff2a5ada 984 next = node->symbol.next;
985 if (!node->symbol.aux && !referred_to_p (node))
ae01b312 986 {
f79b6507 987 if (cgraph_dump_file)
ff2a5ada 988 fprintf (cgraph_dump_file, " %s", symtab_node_name (node));
989 symtab_remove_node (node);
9b8fb23a 990 continue;
ae01b312 991 }
ff2a5ada 992 if (symtab_function_p (node))
993 {
994 tree decl = node->symbol.decl;
995 struct cgraph_node *cnode = cgraph (node);
996
997 if (cnode->local.finalized && !gimple_has_body_p (decl)
998 && (!cnode->alias || !cnode->thunk.alias)
999 && !cnode->thunk.thunk_p)
1000 cgraph_reset_node (cnode);
1001
1002 gcc_assert (!cnode->local.finalized || cnode->thunk.thunk_p
1003 || cnode->alias
1004 || gimple_has_body_p (decl));
1005 gcc_assert (cnode->analyzed == cnode->local.finalized);
1006 }
1007 node->symbol.aux = NULL;
ae01b312 1008 }
ff2a5ada 1009 first_analyzed = cgraph_first_function ();
1010 first_analyzed_var = varpool_first_variable ();
f79b6507 1011 if (cgraph_dump_file)
e4200070 1012 {
1013 fprintf (cgraph_dump_file, "\n\nReclaimed ");
18841b0c 1014 dump_symtab (cgraph_dump_file);
e4200070 1015 }
f1c35659 1016 bitmap_obstack_release (NULL);
ae01b312 1017 ggc_collect ();
aeeb194b 1018}
1019
3a849bc1 1020/* Translate the ugly representation of aliases as alias pairs into nice
1021 representation in callgraph. We don't handle all cases yet,
1022 unforutnately. */
1023
1024static void
1025handle_alias_pairs (void)
1026{
1027 alias_pair *p;
1028 unsigned i;
1029 struct cgraph_node *target_node;
1030 struct cgraph_node *src_node;
e0eaac80 1031 struct varpool_node *target_vnode;
3a849bc1 1032
1033 for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
1034 {
1035 if (TREE_CODE (p->decl) == FUNCTION_DECL
3a849bc1 1036 && (target_node = cgraph_node_for_asm (p->target)) != NULL)
1037 {
1038 src_node = cgraph_get_node (p->decl);
1039 if (src_node && src_node->local.finalized)
1040 cgraph_reset_node (src_node);
1041 /* Normally EXTERNAL flag is used to mark external inlines,
1042 however for aliases it seems to be allowed to use it w/o
1043 any meaning. See gcc.dg/attr-alias-3.c
1044 However for weakref we insist on EXTERNAL flag being set.
1045 See gcc.dg/attr-alias-5.c */
1046 if (DECL_EXTERNAL (p->decl))
7d0d0ce1 1047 DECL_EXTERNAL (p->decl)
1048 = lookup_attribute ("weakref",
1049 DECL_ATTRIBUTES (p->decl)) != NULL;
1050 cgraph_create_function_alias (p->decl, target_node->symbol.decl);
3a849bc1 1051 VEC_unordered_remove (alias_pair, alias_pairs, i);
1052 }
e0eaac80 1053 else if (TREE_CODE (p->decl) == VAR_DECL
e0eaac80 1054 && (target_vnode = varpool_node_for_asm (p->target)) != NULL)
1055 {
1056 /* Normally EXTERNAL flag is used to mark external inlines,
1057 however for aliases it seems to be allowed to use it w/o
1058 any meaning. See gcc.dg/attr-alias-3.c
1059 However for weakref we insist on EXTERNAL flag being set.
1060 See gcc.dg/attr-alias-5.c */
1061 if (DECL_EXTERNAL (p->decl))
7d0d0ce1 1062 DECL_EXTERNAL (p->decl)
1063 = lookup_attribute ("weakref",
1064 DECL_ATTRIBUTES (p->decl)) != NULL;
1065 varpool_create_variable_alias (p->decl, target_vnode->symbol.decl);
e0eaac80 1066 VEC_unordered_remove (alias_pair, alias_pairs, i);
1067 }
badeded8 1068 /* Weakrefs with target not defined in current unit are easy to handle; they
1069 behave just as external variables except we need to note the alias flag
1070 to later output the weakref pseudo op into asm file. */
1071 else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
1072 && (TREE_CODE (p->decl) == FUNCTION_DECL
1073 ? (varpool_node_for_asm (p->target) == NULL)
1074 : (cgraph_node_for_asm (p->target) == NULL)))
1075 {
1076 if (TREE_CODE (p->decl) == FUNCTION_DECL)
1077 cgraph_get_create_node (p->decl)->alias = true;
1078 else
1079 varpool_get_node (p->decl)->alias = true;
1080 DECL_EXTERNAL (p->decl) = 1;
1081 VEC_unordered_remove (alias_pair, alias_pairs, i);
1082 }
3a849bc1 1083 else
1084 {
1085 if (dump_file)
1086 fprintf (dump_file, "Unhandled alias %s->%s\n",
1087 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
1088 IDENTIFIER_POINTER (p->target));
1089
1090 i++;
1091 }
1092 }
1093}
1094
8f69fd82 1095
ae01b312 1096/* Figure out what functions we want to assemble. */
1097
1098static void
cf951b1a 1099mark_functions_to_output (void)
ae01b312 1100{
1101 struct cgraph_node *node;
61c2c7b1 1102#ifdef ENABLE_CHECKING
1103 bool check_same_comdat_groups = false;
1104
7c455d87 1105 FOR_EACH_FUNCTION (node)
61c2c7b1 1106 gcc_assert (!node->process);
1107#endif
ae01b312 1108
7c455d87 1109 FOR_EACH_FUNCTION (node)
ae01b312 1110 {
7d0d0ce1 1111 tree decl = node->symbol.decl;
a0c938f0 1112
7d0d0ce1 1113 gcc_assert (!node->process || node->symbol.same_comdat_group);
61c2c7b1 1114 if (node->process)
1115 continue;
d7c6d889 1116
e6d2b2d8 1117 /* We need to output all local functions that are used and not
1118 always inlined, as well as those that are reachable from
1119 outside the current compilation unit. */
1a1a827a 1120 if (node->analyzed
91bf9d9a 1121 && !node->thunk.thunk_p
c70f46b0 1122 && !node->alias
b0cdf642 1123 && !node->global.inlined_to
4ee9c684 1124 && !TREE_ASM_WRITTEN (decl)
ae01b312 1125 && !DECL_EXTERNAL (decl))
61c2c7b1 1126 {
1127 node->process = 1;
7d0d0ce1 1128 if (node->symbol.same_comdat_group)
61c2c7b1 1129 {
1130 struct cgraph_node *next;
7d0d0ce1 1131 for (next = cgraph (node->symbol.same_comdat_group);
61c2c7b1 1132 next != node;
7d0d0ce1 1133 next = cgraph (next->symbol.same_comdat_group))
c70f46b0 1134 if (!next->thunk.thunk_p && !next->alias)
91bf9d9a 1135 next->process = 1;
61c2c7b1 1136 }
1137 }
7d0d0ce1 1138 else if (node->symbol.same_comdat_group)
61c2c7b1 1139 {
1140#ifdef ENABLE_CHECKING
1141 check_same_comdat_groups = true;
1142#endif
1143 }
cc636d56 1144 else
9cee7c3f 1145 {
1146 /* We should've reclaimed all functions that are not needed. */
1147#ifdef ENABLE_CHECKING
75a70cf9 1148 if (!node->global.inlined_to
1a1a827a 1149 && gimple_has_body_p (decl)
08843223 1150 /* FIXME: in ltrans unit when offline copy is outside partition but inline copies
1151 are inside partition, we can end up not removing the body since we no longer
1152 have analyzed node pointing to it. */
7d0d0ce1 1153 && !node->symbol.in_other_partition
c70f46b0 1154 && !node->alias
9cee7c3f 1155 && !DECL_EXTERNAL (decl))
1156 {
1157 dump_cgraph_node (stderr, node);
1158 internal_error ("failed to reclaim unneeded function");
1159 }
1160#endif
75a70cf9 1161 gcc_assert (node->global.inlined_to
1a1a827a 1162 || !gimple_has_body_p (decl)
7d0d0ce1 1163 || node->symbol.in_other_partition
9cee7c3f 1164 || DECL_EXTERNAL (decl));
1165
1166 }
a0c938f0 1167
961e3b13 1168 }
61c2c7b1 1169#ifdef ENABLE_CHECKING
1170 if (check_same_comdat_groups)
7c455d87 1171 FOR_EACH_FUNCTION (node)
7d0d0ce1 1172 if (node->symbol.same_comdat_group && !node->process)
61c2c7b1 1173 {
7d0d0ce1 1174 tree decl = node->symbol.decl;
61c2c7b1 1175 if (!node->global.inlined_to
1176 && gimple_has_body_p (decl)
6d36105a 1177 /* FIXME: in an ltrans unit when the offline copy is outside a
1178 partition but inline copies are inside a partition, we can
1179 end up not removing the body since we no longer have an
1180 analyzed node pointing to it. */
7d0d0ce1 1181 && !node->symbol.in_other_partition
61c2c7b1 1182 && !DECL_EXTERNAL (decl))
1183 {
1184 dump_cgraph_node (stderr, node);
6d36105a 1185 internal_error ("failed to reclaim unneeded function in same "
1186 "comdat group");
61c2c7b1 1187 }
1188 }
1189#endif
961e3b13 1190}
1191
28454517 1192/* DECL is FUNCTION_DECL. Initialize datastructures so DECL is a function
1193 in lowered gimple form.
1194
1195 Set current_function_decl and cfun to newly constructed empty function body.
1196 return basic block in the function body. */
1197
1198static basic_block
1199init_lowered_empty_function (tree decl)
1200{
1201 basic_block bb;
1202
1203 current_function_decl = decl;
1204 allocate_struct_function (decl, false);
1205 gimple_register_cfg_hooks ();
1206 init_empty_tree_cfg ();
1207 init_tree_ssa (cfun);
1208 init_ssa_operands ();
1209 cfun->gimple_df->in_ssa_p = true;
1210 DECL_INITIAL (decl) = make_node (BLOCK);
1211
1212 DECL_SAVED_TREE (decl) = error_mark_node;
1213 cfun->curr_properties |=
1214 (PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_referenced_vars |
657e3a56 1215 PROP_ssa | PROP_gimple_any);
28454517 1216
1217 /* Create BB for body of the function and connect it properly. */
1218 bb = create_basic_block (NULL, (void *) 0, ENTRY_BLOCK_PTR);
167ef6d9 1219 make_edge (ENTRY_BLOCK_PTR, bb, 0);
1220 make_edge (bb, EXIT_BLOCK_PTR, 0);
28454517 1221
1222 return bb;
1223}
1224
1225/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
1226 offset indicated by VIRTUAL_OFFSET, if that is
1227 non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
1228 zero for a result adjusting thunk. */
1229
1230static tree
1231thunk_adjust (gimple_stmt_iterator * bsi,
1232 tree ptr, bool this_adjusting,
1233 HOST_WIDE_INT fixed_offset, tree virtual_offset)
1234{
1235 gimple stmt;
1236 tree ret;
1237
55d6cb23 1238 if (this_adjusting
1239 && fixed_offset != 0)
28454517 1240 {
2cc66f2a 1241 stmt = gimple_build_assign
1242 (ptr, fold_build_pointer_plus_hwi_loc (input_location,
1243 ptr,
1244 fixed_offset));
28454517 1245 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1246 }
1247
1248 /* If there's a virtual offset, look up that value in the vtable and
1249 adjust the pointer again. */
1250 if (virtual_offset)
1251 {
1252 tree vtabletmp;
1253 tree vtabletmp2;
1254 tree vtabletmp3;
28454517 1255
1256 if (!vtable_entry_type)
1257 {
1258 tree vfunc_type = make_node (FUNCTION_TYPE);
1259 TREE_TYPE (vfunc_type) = integer_type_node;
1260 TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
1261 layout_type (vfunc_type);
1262
1263 vtable_entry_type = build_pointer_type (vfunc_type);
1264 }
1265
1266 vtabletmp =
37ffa8fe 1267 make_rename_temp (build_pointer_type
1268 (build_pointer_type (vtable_entry_type)), "vptr");
28454517 1269
1270 /* The vptr is always at offset zero in the object. */
1271 stmt = gimple_build_assign (vtabletmp,
1272 build1 (NOP_EXPR, TREE_TYPE (vtabletmp),
1273 ptr));
1274 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
28454517 1275
1276 /* Form the vtable address. */
37ffa8fe 1277 vtabletmp2 = make_rename_temp (TREE_TYPE (TREE_TYPE (vtabletmp)),
1278 "vtableaddr");
28454517 1279 stmt = gimple_build_assign (vtabletmp2,
182cf5a9 1280 build_simple_mem_ref (vtabletmp));
28454517 1281 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
28454517 1282
1283 /* Find the entry with the vcall offset. */
1284 stmt = gimple_build_assign (vtabletmp2,
2cc66f2a 1285 fold_build_pointer_plus_loc (input_location,
1286 vtabletmp2,
1287 virtual_offset));
28454517 1288 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1289
1290 /* Get the offset itself. */
37ffa8fe 1291 vtabletmp3 = make_rename_temp (TREE_TYPE (TREE_TYPE (vtabletmp2)),
1292 "vcalloffset");
28454517 1293 stmt = gimple_build_assign (vtabletmp3,
182cf5a9 1294 build_simple_mem_ref (vtabletmp2));
28454517 1295 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
28454517 1296
28454517 1297 /* Adjust the `this' pointer. */
a0553bff 1298 ptr = fold_build_pointer_plus_loc (input_location, ptr, vtabletmp3);
1299 ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false,
1300 GSI_CONTINUE_LINKING);
28454517 1301 }
1302
55d6cb23 1303 if (!this_adjusting
1304 && fixed_offset != 0)
28454517 1305 /* Adjust the pointer by the constant. */
1306 {
1307 tree ptrtmp;
1308
1309 if (TREE_CODE (ptr) == VAR_DECL)
1310 ptrtmp = ptr;
1311 else
1312 {
37ffa8fe 1313 ptrtmp = make_rename_temp (TREE_TYPE (ptr), "ptr");
28454517 1314 stmt = gimple_build_assign (ptrtmp, ptr);
1315 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
28454517 1316 }
2cc66f2a 1317 ptr = fold_build_pointer_plus_hwi_loc (input_location,
1318 ptrtmp, fixed_offset);
28454517 1319 }
1320
1321 /* Emit the statement and gimplify the adjustment expression. */
37ffa8fe 1322 ret = make_rename_temp (TREE_TYPE (ptr), "adjusted_this");
28454517 1323 stmt = gimple_build_assign (ret, ptr);
28454517 1324 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1325
1326 return ret;
1327}
1328
1329/* Produce assembler for thunk NODE. */
1330
1331static void
1332assemble_thunk (struct cgraph_node *node)
1333{
1334 bool this_adjusting = node->thunk.this_adjusting;
1335 HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
1336 HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
1337 tree virtual_offset = NULL;
1338 tree alias = node->thunk.alias;
7d0d0ce1 1339 tree thunk_fndecl = node->symbol.decl;
28454517 1340 tree a = DECL_ARGUMENTS (thunk_fndecl);
1341
1342 current_function_decl = thunk_fndecl;
1343
aed6e608 1344 /* Ensure thunks are emitted in their correct sections. */
1345 resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
1346
28454517 1347 if (this_adjusting
1348 && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
1349 virtual_value, alias))
1350 {
1351 const char *fnname;
1352 tree fn_block;
28b2c6a7 1353 tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
28454517 1354
1355 DECL_RESULT (thunk_fndecl)
1356 = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
28b2c6a7 1357 RESULT_DECL, 0, restype);
22ea3b47 1358 fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
28454517 1359
1360 /* The back end expects DECL_INITIAL to contain a BLOCK, so we
1361 create one. */
1362 fn_block = make_node (BLOCK);
1363 BLOCK_VARS (fn_block) = a;
1364 DECL_INITIAL (thunk_fndecl) = fn_block;
1365 init_function_start (thunk_fndecl);
1366 cfun->is_thunk = 1;
1367 assemble_start_function (thunk_fndecl, fnname);
1368
1369 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
1370 fixed_offset, virtual_value, alias);
1371
1372 assemble_end_function (thunk_fndecl, fnname);
1373 init_insn_lengths ();
1374 free_after_compilation (cfun);
1375 set_cfun (NULL);
1376 TREE_ASM_WRITTEN (thunk_fndecl) = 1;
91bf9d9a 1377 node->thunk.thunk_p = false;
1378 node->analyzed = false;
28454517 1379 }
1380 else
1381 {
1382 tree restype;
1383 basic_block bb, then_bb, else_bb, return_bb;
1384 gimple_stmt_iterator bsi;
1385 int nargs = 0;
1386 tree arg;
1387 int i;
1388 tree resdecl;
1389 tree restmp = NULL;
1390 VEC(tree, heap) *vargs;
1391
1392 gimple call;
1393 gimple ret;
1394
1395 DECL_IGNORED_P (thunk_fndecl) = 1;
1396 bitmap_obstack_initialize (NULL);
1397
1398 if (node->thunk.virtual_offset_p)
1399 virtual_offset = size_int (virtual_value);
1400
1401 /* Build the return declaration for the function. */
1402 restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
1403 if (DECL_RESULT (thunk_fndecl) == NULL_TREE)
1404 {
1405 resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
1406 DECL_ARTIFICIAL (resdecl) = 1;
1407 DECL_IGNORED_P (resdecl) = 1;
1408 DECL_RESULT (thunk_fndecl) = resdecl;
1409 }
1410 else
1411 resdecl = DECL_RESULT (thunk_fndecl);
1412
1413 bb = then_bb = else_bb = return_bb = init_lowered_empty_function (thunk_fndecl);
1414
1415 bsi = gsi_start_bb (bb);
1416
1417 /* Build call to the function being thunked. */
1418 if (!VOID_TYPE_P (restype))
1419 {
1420 if (!is_gimple_reg_type (restype))
1421 {
1422 restmp = resdecl;
2ab2ce89 1423 add_local_decl (cfun, restmp);
28454517 1424 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp;
1425 }
1426 else
37ffa8fe 1427 restmp = make_rename_temp (restype, "retval");
28454517 1428 }
1429
1767a056 1430 for (arg = a; arg; arg = DECL_CHAIN (arg))
28454517 1431 nargs++;
1432 vargs = VEC_alloc (tree, heap, nargs);
1433 if (this_adjusting)
1434 VEC_quick_push (tree, vargs,
1435 thunk_adjust (&bsi,
1436 a, 1, fixed_offset,
1437 virtual_offset));
1438 else
1439 VEC_quick_push (tree, vargs, a);
37ffa8fe 1440 add_referenced_var (a);
1441 if (is_gimple_reg (a))
1442 mark_sym_for_renaming (a);
1767a056 1443 for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
37ffa8fe 1444 {
1445 add_referenced_var (arg);
1446 if (is_gimple_reg (arg))
1447 mark_sym_for_renaming (arg);
1448 VEC_quick_push (tree, vargs, arg);
1449 }
28454517 1450 call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
1451 VEC_free (tree, heap, vargs);
28454517 1452 gimple_call_set_from_thunk (call, true);
1453 if (restmp)
1454 gimple_call_set_lhs (call, restmp);
1455 gsi_insert_after (&bsi, call, GSI_NEW_STMT);
28454517 1456
1457 if (restmp && !this_adjusting)
1458 {
57ab8ec3 1459 tree true_label = NULL_TREE;
28454517 1460
1461 if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
1462 {
1463 gimple stmt;
1464 /* If the return type is a pointer, we need to
1465 protect against NULL. We know there will be an
1466 adjustment, because that's why we're emitting a
1467 thunk. */
1468 then_bb = create_basic_block (NULL, (void *) 0, bb);
1469 return_bb = create_basic_block (NULL, (void *) 0, then_bb);
1470 else_bb = create_basic_block (NULL, (void *) 0, else_bb);
1471 remove_edge (single_succ_edge (bb));
1472 true_label = gimple_block_label (then_bb);
28454517 1473 stmt = gimple_build_cond (NE_EXPR, restmp,
385f3f36 1474 build_zero_cst (TREE_TYPE (restmp)),
28454517 1475 NULL_TREE, NULL_TREE);
1476 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1477 make_edge (bb, then_bb, EDGE_TRUE_VALUE);
1478 make_edge (bb, else_bb, EDGE_FALSE_VALUE);
1479 make_edge (return_bb, EXIT_BLOCK_PTR, 0);
1480 make_edge (then_bb, return_bb, EDGE_FALLTHRU);
1481 make_edge (else_bb, return_bb, EDGE_FALLTHRU);
1482 bsi = gsi_last_bb (then_bb);
1483 }
1484
1485 restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
1486 fixed_offset, virtual_offset);
1487 if (true_label)
1488 {
1489 gimple stmt;
1490 bsi = gsi_last_bb (else_bb);
385f3f36 1491 stmt = gimple_build_assign (restmp,
1492 build_zero_cst (TREE_TYPE (restmp)));
28454517 1493 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1494 bsi = gsi_last_bb (return_bb);
1495 }
1496 }
1497 else
1498 gimple_call_set_tail (call, true);
1499
1500 /* Build return value. */
1501 ret = gimple_build_return (restmp);
1502 gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
1503
1504 delete_unreachable_blocks ();
1505 update_ssa (TODO_update_ssa);
1506
28454517 1507 /* Since we want to emit the thunk, we explicitly mark its name as
1508 referenced. */
91bf9d9a 1509 node->thunk.thunk_p = false;
1510 cgraph_node_remove_callees (node);
28454517 1511 cgraph_add_new_function (thunk_fndecl, true);
1512 bitmap_obstack_release (NULL);
1513 }
1514 current_function_decl = NULL;
1515}
1516
91bf9d9a 1517
c70f46b0 1518
1519/* Assemble thunks and aliases asociated to NODE. */
91bf9d9a 1520
1521static void
c70f46b0 1522assemble_thunks_and_aliases (struct cgraph_node *node)
91bf9d9a 1523{
1524 struct cgraph_edge *e;
c70f46b0 1525 int i;
1526 struct ipa_ref *ref;
1527
91bf9d9a 1528 for (e = node->callers; e;)
1529 if (e->caller->thunk.thunk_p)
1530 {
1531 struct cgraph_node *thunk = e->caller;
1532
1533 e = e->next_caller;
c70f46b0 1534 assemble_thunks_and_aliases (thunk);
91bf9d9a 1535 assemble_thunk (thunk);
1536 }
1537 else
1538 e = e->next_caller;
04ec15fa 1539 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
7d0d0ce1 1540 i, ref); i++)
c70f46b0 1541 if (ref->use == IPA_REF_ALIAS)
1542 {
04ec15fa 1543 struct cgraph_node *alias = ipa_ref_referring_node (ref);
968b8c52 1544 bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias);
1545
1546 /* Force assemble_alias to really output the alias this time instead
1547 of buffering it in same alias pairs. */
1548 TREE_ASM_WRITTEN (alias->thunk.alias) = 1;
7d0d0ce1 1549 assemble_alias (alias->symbol.decl,
c70f46b0 1550 DECL_ASSEMBLER_NAME (alias->thunk.alias));
1551 assemble_thunks_and_aliases (alias);
968b8c52 1552 TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written;
c70f46b0 1553 }
91bf9d9a 1554}
1555
da5e1e7c 1556/* Expand function specified by NODE. */
941366fd 1557
3db65b62 1558static void
cf951b1a 1559expand_function (struct cgraph_node *node)
941366fd 1560{
da5e1e7c 1561 tree decl = node->symbol.decl;
941366fd 1562 location_t saved_loc;
1563
da5e1e7c 1564 /* We ought to not compile any inline clones. */
1565 gcc_assert (!node->global.inlined_to);
1566
1567 announce_function (decl);
1568 node->process = 0;
1569 gcc_assert (node->lowered);
1570
1571 /* Generate RTL for the body of DECL. */
1572
941366fd 1573 timevar_push (TV_REST_OF_COMPILATION);
1574
1575 gcc_assert (cgraph_global_info_ready);
1576
1577 /* Initialize the default bitmap obstack. */
1578 bitmap_obstack_initialize (NULL);
1579
1580 /* Initialize the RTL code for the function. */
da5e1e7c 1581 current_function_decl = decl;
941366fd 1582 saved_loc = input_location;
da5e1e7c 1583 input_location = DECL_SOURCE_LOCATION (decl);
1584 init_function_start (decl);
941366fd 1585
1586 gimple_register_cfg_hooks ();
1587
1588 bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
1589
1590 execute_all_ipa_transforms ();
1591
1592 /* Perform all tree transforms and optimizations. */
1593
1594 /* Signal the start of passes. */
1595 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
1596
1597 execute_pass_list (all_passes);
1598
1599 /* Signal the end of passes. */
1600 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
1601
1602 bitmap_obstack_release (&reg_obstack);
1603
1604 /* Release the default bitmap obstack. */
1605 bitmap_obstack_release (NULL);
1606
1607 set_cfun (NULL);
1608
1609 /* If requested, warn about function definitions where the function will
1610 return a value (usually of some struct or union type) which itself will
1611 take up a lot of stack space. */
da5e1e7c 1612 if (warn_larger_than && !DECL_EXTERNAL (decl) && TREE_TYPE (decl))
941366fd 1613 {
da5e1e7c 1614 tree ret_type = TREE_TYPE (TREE_TYPE (decl));
941366fd 1615
1616 if (ret_type && TYPE_SIZE_UNIT (ret_type)
1617 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
1618 && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
1619 larger_than_size))
1620 {
1621 unsigned int size_as_int
1622 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
1623
1624 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
1625 warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
da5e1e7c 1626 decl, size_as_int);
941366fd 1627 else
1628 warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
da5e1e7c 1629 decl, larger_than_size);
941366fd 1630 }
1631 }
1632
da5e1e7c 1633 gimple_set_body (decl, NULL);
1634 if (DECL_STRUCT_FUNCTION (decl) == 0
1635 && !cgraph_get_node (decl)->origin)
941366fd 1636 {
1637 /* Stop pointing to the local nodes about to be freed.
1638 But DECL_INITIAL must remain nonzero so we know this
1639 was an actual function definition.
1640 For a nested function, this is done in c_pop_function_context.
1641 If rest_of_compilation set this to 0, leave it 0. */
da5e1e7c 1642 if (DECL_INITIAL (decl) != 0)
1643 DECL_INITIAL (decl) = error_mark_node;
941366fd 1644 }
1645
1646 input_location = saved_loc;
1647
1648 ggc_collect ();
1649 timevar_pop (TV_REST_OF_COMPILATION);
f7777314 1650
1651 /* Make sure that BE didn't give up on compiling. */
1652 gcc_assert (TREE_ASM_WRITTEN (decl));
1653 current_function_decl = NULL;
f76f7453 1654
1655 /* It would make a lot more sense to output thunks before function body to get more
cf951b1a 1656 forward and lest backwarding jumps. This however would need solving problem
f76f7453 1657 with comdats. See PR48668. Also aliases must come after function itself to
cf951b1a 1658 make one pass assemblers, like one on AIX, happy. See PR 50689.
f76f7453 1659 FIXME: Perhaps thunks should be move before function IFF they are not in comdat
1660 groups. */
1661 assemble_thunks_and_aliases (node);
1a1a827a 1662 cgraph_release_function_body (node);
1663 /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
1664 points to the dead function body. */
1665 cgraph_node_remove_callees (node);
ae01b312 1666}
1667
acc70efa 1668
d9d9733a 1669/* Expand all functions that must be output.
1670
d7c6d889 1671 Attempt to topologically sort the nodes so function is output when
1672 all called functions are already assembled to allow data to be
91c82c20 1673 propagated across the callgraph. Use a stack to get smaller distance
3927afe0 1674 between a function and its callees (later we may choose to use a more
d7c6d889 1675 sophisticated algorithm for function reordering; we will likely want
1676 to use subsections to make the output functions appear in top-down
1677 order). */
1678
1679static void
cf951b1a 1680expand_all_functions (void)
d7c6d889 1681{
1682 struct cgraph_node *node;
4c36ffe6 1683 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
c04e3894 1684 int order_pos, new_order_pos = 0;
d7c6d889 1685 int i;
1686
7771d558 1687 order_pos = ipa_reverse_postorder (order);
cc636d56 1688 gcc_assert (order_pos == cgraph_n_nodes);
d7c6d889 1689
7bd28bba 1690 /* Garbage collector may remove inline clones we eliminate during
b0cdf642 1691 optimization. So we must be sure to not reference them. */
1692 for (i = 0; i < order_pos; i++)
09fc9532 1693 if (order[i]->process)
b0cdf642 1694 order[new_order_pos++] = order[i];
1695
1696 for (i = new_order_pos - 1; i >= 0; i--)
d7c6d889 1697 {
1698 node = order[i];
09fc9532 1699 if (node->process)
d7c6d889 1700 {
09fc9532 1701 node->process = 0;
cf951b1a 1702 expand_function (node);
d7c6d889 1703 }
1704 }
523c1122 1705 cgraph_process_new_functions ();
773c5ba7 1706
d7c6d889 1707 free (order);
773c5ba7 1708
d7c6d889 1709}
1710
56af936e 1711/* This is used to sort the node types by the cgraph order number. */
1712
0b09525f 1713enum cgraph_order_sort_kind
1714{
1715 ORDER_UNDEFINED = 0,
1716 ORDER_FUNCTION,
1717 ORDER_VAR,
1718 ORDER_ASM
1719};
1720
56af936e 1721struct cgraph_order_sort
1722{
0b09525f 1723 enum cgraph_order_sort_kind kind;
56af936e 1724 union
1725 {
1726 struct cgraph_node *f;
1d416bd7 1727 struct varpool_node *v;
cf951b1a 1728 struct asm_node *a;
56af936e 1729 } u;
1730};
1731
1732/* Output all functions, variables, and asm statements in the order
1733 according to their order fields, which is the order in which they
1734 appeared in the file. This implements -fno-toplevel-reorder. In
1735 this mode we may output functions and variables which don't really
1736 need to be output. */
1737
1738static void
cf951b1a 1739output_in_order (void)
56af936e 1740{
1741 int max;
56af936e 1742 struct cgraph_order_sort *nodes;
1743 int i;
1744 struct cgraph_node *pf;
1d416bd7 1745 struct varpool_node *pv;
cf951b1a 1746 struct asm_node *pa;
56af936e 1747
0704fb2e 1748 max = symtab_order;
3e1cde87 1749 nodes = XCNEWVEC (struct cgraph_order_sort, max);
56af936e 1750
7c455d87 1751 FOR_EACH_DEFINED_FUNCTION (pf)
56af936e 1752 {
c70f46b0 1753 if (pf->process && !pf->thunk.thunk_p && !pf->alias)
56af936e 1754 {
7d0d0ce1 1755 i = pf->symbol.order;
56af936e 1756 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1757 nodes[i].kind = ORDER_FUNCTION;
1758 nodes[i].u.f = pf;
1759 }
1760 }
1761
7c455d87 1762 FOR_EACH_DEFINED_VARIABLE (pv)
56af936e 1763 {
7d0d0ce1 1764 i = pv->symbol.order;
56af936e 1765 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1766 nodes[i].kind = ORDER_VAR;
1767 nodes[i].u.v = pv;
1768 }
1769
cf951b1a 1770 for (pa = asm_nodes; pa; pa = pa->next)
56af936e 1771 {
1772 i = pa->order;
1773 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
1774 nodes[i].kind = ORDER_ASM;
1775 nodes[i].u.a = pa;
1776 }
56af936e 1777
304e5318 1778 /* In toplevel reorder mode we output all statics; mark them as needed. */
304e5318 1779
91da0f1c 1780 for (i = 0; i < max; ++i)
1781 if (nodes[i].kind == ORDER_VAR)
1782 varpool_finalize_named_section_flags (nodes[i].u.v);
1783
56af936e 1784 for (i = 0; i < max; ++i)
1785 {
1786 switch (nodes[i].kind)
1787 {
1788 case ORDER_FUNCTION:
09fc9532 1789 nodes[i].u.f->process = 0;
cf951b1a 1790 expand_function (nodes[i].u.f);
56af936e 1791 break;
1792
1793 case ORDER_VAR:
1d416bd7 1794 varpool_assemble_decl (nodes[i].u.v);
56af936e 1795 break;
1796
1797 case ORDER_ASM:
1798 assemble_asm (nodes[i].u.a->asm_str);
1799 break;
1800
1801 case ORDER_UNDEFINED:
1802 break;
1803
1804 default:
1805 gcc_unreachable ();
1806 }
1807 }
4b4ea2db 1808
cf951b1a 1809 asm_nodes = NULL;
3e1cde87 1810 free (nodes);
56af936e 1811}
1812
77fce4cd 1813static void
1814ipa_passes (void)
1815{
87d4aa85 1816 set_cfun (NULL);
4b14adf9 1817 current_function_decl = NULL;
75a70cf9 1818 gimple_register_cfg_hooks ();
77fce4cd 1819 bitmap_obstack_initialize (NULL);
59dd4830 1820
c9036234 1821 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
1822
59dd4830 1823 if (!in_lto_p)
7b2e8956 1824 {
1825 execute_ipa_pass_list (all_small_ipa_passes);
1826 if (seen_error ())
1827 return;
1828 }
9ed5b1f5 1829
941125aa 1830 /* We never run removal of unreachable nodes after early passes. This is
1831 because TODO is run before the subpasses. It is important to remove
1832 the unreachable functions to save works at IPA level and to get LTO
1833 symbol tables right. */
91f0ab48 1834 symtab_remove_unreachable_nodes (true, cgraph_dump_file);
941125aa 1835
7bfefa9d 1836 /* If pass_all_early_optimizations was not scheduled, the state of
1837 the cgraph will not be properly updated. Update it now. */
1838 if (cgraph_state < CGRAPH_STATE_IPA_SSA)
1839 cgraph_state = CGRAPH_STATE_IPA_SSA;
9ed5b1f5 1840
7bfefa9d 1841 if (!in_lto_p)
1842 {
1843 /* Generate coverage variables and constructors. */
1844 coverage_finish ();
1845
1846 /* Process new functions added. */
1847 set_cfun (NULL);
1848 current_function_decl = NULL;
1849 cgraph_process_new_functions ();
7bfefa9d 1850
c9036234 1851 execute_ipa_summary_passes
1852 ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
8867b500 1853 }
23433d72 1854
1855 /* Some targets need to handle LTO assembler output specially. */
1856 if (flag_generate_lto)
1857 targetm.asm_out.lto_start ();
1858
7bfefa9d 1859 execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
1860
1861 if (!in_lto_p)
1862 ipa_write_summaries ();
1863
23433d72 1864 if (flag_generate_lto)
1865 targetm.asm_out.lto_end ();
1866
b33542ab 1867 if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
8867b500 1868 execute_ipa_pass_list (all_regular_ipa_passes);
c9036234 1869 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
9ed5b1f5 1870
77fce4cd 1871 bitmap_obstack_release (NULL);
1872}
1873
badeded8 1874
1875/* Return string alias is alias of. */
1876
1877static tree
1878get_alias_symbol (tree decl)
1879{
1880 tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
1881 return get_identifier (TREE_STRING_POINTER
1882 (TREE_VALUE (TREE_VALUE (alias))));
1883}
1884
1885
5e712541 1886/* Weakrefs may be associated to external decls and thus not output
1887 at expansion time. Emit all neccesary aliases. */
1888
5139ff04 1889static void
5e712541 1890output_weakrefs (void)
1891{
1892 struct cgraph_node *node;
1893 struct varpool_node *vnode;
7c455d87 1894 FOR_EACH_FUNCTION (node)
7d0d0ce1 1895 if (node->alias && DECL_EXTERNAL (node->symbol.decl)
1896 && !TREE_ASM_WRITTEN (node->symbol.decl)
1897 && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
1898 assemble_alias (node->symbol.decl,
badeded8 1899 node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
7d0d0ce1 1900 : get_alias_symbol (node->symbol.decl));
7c455d87 1901 FOR_EACH_VARIABLE (vnode)
7d0d0ce1 1902 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)
1903 && !TREE_ASM_WRITTEN (vnode->symbol.decl)
1904 && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
1905 assemble_alias (vnode->symbol.decl,
badeded8 1906 vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
7d0d0ce1 1907 : get_alias_symbol (vnode->symbol.decl));
5e712541 1908}
1909
da5e1e7c 1910/* Initialize callgraph dump file. */
34e5cced 1911
121f3051 1912void
1913init_cgraph (void)
1914{
01ec0a6c 1915 if (!cgraph_dump_file)
1916 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
121f3051 1917}
b5d36404 1918
d2bb3f9d 1919
1920/* Perform simple optimizations based on callgraph. */
1921
1922void
cf951b1a 1923compile (void)
d2bb3f9d 1924{
1925 if (seen_error ())
1926 return;
1927
1928#ifdef ENABLE_CHECKING
3e7775f6 1929 verify_symtab ();
d2bb3f9d 1930#endif
1931
d2bb3f9d 1932 timevar_push (TV_CGRAPHOPT);
1933 if (pre_ipa_mem_report)
1934 {
1935 fprintf (stderr, "Memory consumption before IPA\n");
1936 dump_memory_report (false);
1937 }
1938 if (!quiet_flag)
1939 fprintf (stderr, "Performing interprocedural optimizations\n");
1940 cgraph_state = CGRAPH_STATE_IPA;
1941
cf951b1a 1942 /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */
1943 if (flag_lto)
1944 lto_streamer_hooks_init ();
1945
d2bb3f9d 1946 /* Don't run the IPA passes if there was any error or sorry messages. */
1947 if (!seen_error ())
1948 ipa_passes ();
1949
1950 /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */
1951 if (seen_error ()
1952 || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
1953 {
1954 timevar_pop (TV_CGRAPHOPT);
1955 return;
1956 }
1957
1958 /* This pass remove bodies of extern inline functions we never inlined.
1959 Do this later so other IPA passes see what is really going on. */
91f0ab48 1960 symtab_remove_unreachable_nodes (false, dump_file);
d2bb3f9d 1961 cgraph_global_info_ready = true;
1962 if (cgraph_dump_file)
1963 {
1964 fprintf (cgraph_dump_file, "Optimized ");
18841b0c 1965 dump_symtab (cgraph_dump_file);
d2bb3f9d 1966 }
1967 if (post_ipa_mem_report)
1968 {
1969 fprintf (stderr, "Memory consumption after IPA\n");
1970 dump_memory_report (false);
1971 }
1972 timevar_pop (TV_CGRAPHOPT);
1973
1974 /* Output everything. */
1975 (*debug_hooks->assembly_start) ();
1976 if (!quiet_flag)
1977 fprintf (stderr, "Assembling functions:\n");
1978#ifdef ENABLE_CHECKING
3e7775f6 1979 verify_symtab ();
d2bb3f9d 1980#endif
1981
1982 cgraph_materialize_all_clones ();
1983 bitmap_obstack_initialize (NULL);
1984 execute_ipa_pass_list (all_late_ipa_passes);
91f0ab48 1985 symtab_remove_unreachable_nodes (true, dump_file);
d2bb3f9d 1986#ifdef ENABLE_CHECKING
3e7775f6 1987 verify_symtab ();
d2bb3f9d 1988#endif
1989 bitmap_obstack_release (NULL);
cf951b1a 1990 mark_functions_to_output ();
d2bb3f9d 1991 output_weakrefs ();
1992
1993 cgraph_state = CGRAPH_STATE_EXPANSION;
1994 if (!flag_toplevel_reorder)
cf951b1a 1995 output_in_order ();
d2bb3f9d 1996 else
1997 {
cf951b1a 1998 output_asm_statements ();
d2bb3f9d 1999
cf951b1a 2000 expand_all_functions ();
2001 varpool_output_variables ();
d2bb3f9d 2002 }
2003
2004 cgraph_process_new_functions ();
2005 cgraph_state = CGRAPH_STATE_FINISHED;
2006
2007 if (cgraph_dump_file)
2008 {
2009 fprintf (cgraph_dump_file, "\nFinal ");
18841b0c 2010 dump_symtab (cgraph_dump_file);
d2bb3f9d 2011 }
2012#ifdef ENABLE_CHECKING
3e7775f6 2013 verify_symtab ();
d2bb3f9d 2014 /* Double check that all inline clones are gone and that all
2015 function bodies have been released from memory. */
2016 if (!seen_error ())
2017 {
2018 struct cgraph_node *node;
2019 bool error_found = false;
2020
7c455d87 2021 FOR_EACH_DEFINED_FUNCTION (node)
2022 if (node->global.inlined_to
2023 || gimple_has_body_p (node->symbol.decl))
d2bb3f9d 2024 {
2025 error_found = true;
2026 dump_cgraph_node (stderr, node);
2027 }
2028 if (error_found)
2029 internal_error ("nodes with unreleased memory found");
2030 }
2031#endif
2032}
2033
2034
2035/* Analyze the whole compilation unit once it is parsed completely. */
2036
2037void
cf951b1a 2038finalize_compilation_unit (void)
d2bb3f9d 2039{
2040 timevar_push (TV_CGRAPH);
2041
d2bb3f9d 2042 /* If we're here there's no current function anymore. Some frontends
2043 are lazy in clearing these. */
2044 current_function_decl = NULL;
2045 set_cfun (NULL);
2046
2047 /* Do not skip analyzing the functions if there were errors, we
2048 miss diagnostics for following functions otherwise. */
2049
2050 /* Emit size functions we didn't inline. */
2051 finalize_size_functions ();
2052
2053 /* Mark alias targets necessary and emit diagnostics. */
2054 finish_aliases_1 ();
2055 handle_alias_pairs ();
2056
2057 if (!quiet_flag)
2058 {
2059 fprintf (stderr, "\nAnalyzing compilation unit\n");
2060 fflush (stderr);
2061 }
2062
2063 if (flag_dump_passes)
2064 dump_passes ();
2065
2066 /* Gimplify and lower all functions, compute reachability and
2067 remove unreachable nodes. */
2068 cgraph_analyze_functions ();
2069
2070 /* Mark alias targets necessary and emit diagnostics. */
2071 finish_aliases_1 ();
2072 handle_alias_pairs ();
2073
2074 /* Gimplify and lower thunks. */
2075 cgraph_analyze_functions ();
2076
2077 /* Finally drive the pass manager. */
cf951b1a 2078 compile ();
d2bb3f9d 2079
2080 timevar_pop (TV_CGRAPH);
2081}
2082
2083
a861fe52 2084#include "gt-cgraphunit.h"