]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraphunit.c
2012-04-16 Richard Guenther <rguenther@suse.de>
[thirdparty/gcc.git] / gcc / cgraphunit.c
CommitLineData
cd6bca02 1/* Callgraph based interprocedural optimizations.
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
b0cdf642 22/* This module implements main driver of compilation process as well as
cd6bca02 23 few basic interprocedural optimizers.
b0cdf642 24
25 The main scope of this file is to act as an interface in between
26 tree based frontends and the backend (and middle end)
27
28 The front-end is supposed to use following functionality:
29
30 - cgraph_finalize_function
31
32 This function is called once front-end has parsed whole body of function
33 and it is certain that the function body nor the declaration will change.
34
b326746d 35 (There is one exception needed for implementing GCC extern inline
36 function.)
b0cdf642 37
1d416bd7 38 - varpool_finalize_variable
b0cdf642 39
7bd28bba 40 This function has same behavior as the above but is used for static
b0cdf642 41 variables.
42
43 - cgraph_finalize_compilation_unit
44
b326746d 45 This function is called once (source level) compilation unit is finalized
46 and it will no longer change.
b0cdf642 47
851d9296 48 In the call-graph construction and local function analysis takes
49 place here. Bodies of unreachable functions are released to
50 conserve memory usage.
b0cdf642 51
b326746d 52 The function can be called multiple times when multiple source level
53 compilation units are combined (such as in C frontend)
b0cdf642 54
55 - cgraph_optimize
56
57 In this unit-at-a-time compilation the intra procedural analysis takes
58 place here. In particular the static functions whose address is never
59 taken are marked as local. Backend can then use this information to
60 modify calling conventions, do better inlining or similar optimizations.
61
b0cdf642 62 - cgraph_mark_needed_node
1d416bd7 63 - varpool_mark_needed_node
b0cdf642 64
b326746d 65 When function or variable is referenced by some hidden way the call-graph
66 data structure must be updated accordingly by this function.
67 There should be little need to call this function and all the references
68 should be made explicit to cgraph code. At present these functions are
ccd2f3d1 69 used by C++ frontend to explicitly mark the keyed methods.
b0cdf642 70
71 - analyze_expr callback
72
73 This function is responsible for lowering tree nodes not understood by
74 generic code into understandable ones or alternatively marking
75 callgraph and varpool nodes referenced by the as needed.
76
77 ??? On the tree-ssa genericizing should take place here and we will avoid
78 need for these hooks (replacing them by genericizing hook)
79
6329636b 80 Analyzing of all functions is deferred
b0cdf642 81 to cgraph_finalize_compilation_unit and expansion into cgraph_optimize.
82
83 In cgraph_finalize_compilation_unit the reachable functions are
84 analyzed. During analysis the call-graph edges from reachable
85 functions are constructed and their destinations are marked as
86 reachable. References to functions and variables are discovered too
87 and variables found to be needed output to the assembly file. Via
88 mark_referenced call in assemble_variable functions referenced by
89 static variables are noticed too.
90
ca67a72b 91 The intra-procedural information is produced and its existence
b0cdf642 92 indicated by global_info_ready. Once this flag is set it is impossible
93 to change function from !reachable to reachable and thus
94 assemble_variable no longer call mark_referenced.
95
96 Finally the call-graph is topologically sorted and all reachable functions
97 that has not been completely inlined or are not external are output.
98
99 ??? It is possible that reference to function or variable is optimized
100 out. We can not deal with this nicely because topological order is not
101 suitable for it. For tree-ssa we may consider another pass doing
102 optimization and re-discovering reachable functions.
103
104 ??? Reorganize code so variables are output very last and only if they
105 really has been referenced by produced code, so we catch more cases
6329636b 106 where reference has been optimized out. */
121f3051 107
acc70efa 108
ae01b312 109#include "config.h"
110#include "system.h"
111#include "coretypes.h"
112#include "tm.h"
113#include "tree.h"
941366fd 114#include "output.h"
b5530559 115#include "rtl.h"
acc70efa 116#include "tree-flow.h"
ae01b312 117#include "tree-inline.h"
118#include "langhooks.h"
c6224531 119#include "pointer-set.h"
ae01b312 120#include "toplev.h"
121#include "flags.h"
122#include "ggc.h"
123#include "debug.h"
124#include "target.h"
125#include "cgraph.h"
80a85d8a 126#include "diagnostic.h"
ce084dfc 127#include "tree-pretty-print.h"
128#include "gimple-pretty-print.h"
f79b6507 129#include "timevar.h"
d7c6d889 130#include "params.h"
131#include "fibheap.h"
611e5405 132#include "intl.h"
b69eb0ff 133#include "function.h"
b5d36404 134#include "ipa-prop.h"
75a70cf9 135#include "gimple.h"
136#include "tree-iterator.h"
f1e2a033 137#include "tree-pass.h"
bfec3452 138#include "tree-dump.h"
c1dcd13c 139#include "output.h"
9ed5b1f5 140#include "coverage.h"
c9036234 141#include "plugin.h"
a41f2a28 142#include "ipa-inline.h"
7771d558 143#include "ipa-utils.h"
a0605d65 144#include "lto-streamer.h"
3db65b62 145#include "except.h"
941366fd 146#include "regset.h" /* FIXME: For reg_obstack. */
d7c6d889 147
a6868229 148static void cgraph_expand_all_functions (void);
d9d9733a 149static void cgraph_mark_functions_to_output (void);
150static void cgraph_expand_function (struct cgraph_node *);
f788fff2 151static void cgraph_output_pending_asms (void);
3db65b62 152static void tree_rest_of_compilation (struct cgraph_node *);
25bb88de 153
ecb08119 154FILE *cgraph_dump_file;
121f3051 155
28454517 156/* Used for vtable lookup in thunk adjusting. */
157static GTY (()) tree vtable_entry_type;
158
2c0b522d 159/* Determine if function DECL is needed. That is, visible to something
160 either outside this translation unit, something magic in the system
6329636b 161 configury. */
2c0b522d 162
7bfefa9d 163bool
164cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
2c0b522d 165{
3f82b628 166 /* If the user told us it is used, then it must be so. */
7d0d0ce1 167 if (node->symbol.externally_visible)
05806473 168 return true;
169
3f82b628 170 /* ??? If the assembler name is set by hand, it is possible to assemble
171 the name later after finalizing the function and the fact is noticed
172 in assemble_name then. This is arguably a bug. */
173 if (DECL_ASSEMBLER_NAME_SET_P (decl)
c70f46b0 174 && (!node->thunk.thunk_p && !node->same_body_alias)
3f82b628 175 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
176 return true;
177
55680bef 178 /* With -fkeep-inline-functions we are keeping all inline functions except
179 for extern inline ones. */
180 if (flag_keep_inline_functions
181 && DECL_DECLARED_INLINE_P (decl)
316ef6d8 182 && !DECL_EXTERNAL (decl)
cbd7f5a0 183 && !DECL_DISREGARD_INLINE_LIMITS (decl))
55680bef 184 return true;
185
2c0b522d 186 /* If we decided it was needed before, but at the time we didn't have
187 the body of the function available, then it's still needed. We have
188 to go back and re-check its dependencies now. */
189 if (node->needed)
190 return true;
191
192 /* Externally visible functions must be output. The exception is
a0c938f0 193 COMDAT functions that must be output only when they are needed.
8baa9d15 194
195 When not optimizing, also output the static functions. (see
95da6220 196 PR24561), but don't do so for always_inline functions, functions
0f9238c0 197 declared inline and nested functions. These were optimized out
d3d410e1 198 in the original implementation and it is unclear whether we want
554f2707 199 to change the behavior here. */
bba7ddf8 200 if (((TREE_PUBLIC (decl)
0f9238c0 201 || (!optimize
07828d90 202 && !node->same_body_alias
cbd7f5a0 203 && !DECL_DISREGARD_INLINE_LIMITS (decl)
d3d410e1 204 && !DECL_DECLARED_INLINE_P (decl)
0f9238c0 205 && !(DECL_CONTEXT (decl)
206 && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
59dd4830 207 && !flag_whole_program
cbcf2791 208 && !flag_lto)
62eec3b4 209 && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
2c0b522d 210 return true;
211
2c0b522d 212 return false;
213}
214
bdc40eb8 215/* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
523c1122 216 functions into callgraph in a way so they look like ordinary reachable
217 functions inserted into callgraph already at construction time. */
218
219bool
220cgraph_process_new_functions (void)
221{
222 bool output = false;
223 tree fndecl;
224 struct cgraph_node *node;
225
0cddb138 226 varpool_analyze_pending_decls ();
523c1122 227 /* Note that this queue may grow as its being processed, as the new
228 functions may generate new ones. */
229 while (cgraph_new_nodes)
230 {
231 node = cgraph_new_nodes;
7d0d0ce1 232 fndecl = node->symbol.decl;
523c1122 233 cgraph_new_nodes = cgraph_new_nodes->next_needed;
234 switch (cgraph_state)
235 {
236 case CGRAPH_STATE_CONSTRUCTION:
237 /* At construction time we just need to finalize function and move
238 it into reachable functions list. */
239
240 node->next_needed = NULL;
241 cgraph_finalize_function (fndecl, false);
242 cgraph_mark_reachable_node (node);
243 output = true;
4f7a1122 244 cgraph_call_function_insertion_hooks (node);
523c1122 245 break;
246
247 case CGRAPH_STATE_IPA:
f517b36e 248 case CGRAPH_STATE_IPA_SSA:
523c1122 249 /* When IPA optimization already started, do all essential
250 transformations that has been already performed on the whole
251 cgraph but not on this function. */
252
75a70cf9 253 gimple_register_cfg_hooks ();
523c1122 254 if (!node->analyzed)
255 cgraph_analyze_function (node);
256 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
257 current_function_decl = fndecl;
f517b36e 258 if ((cgraph_state == CGRAPH_STATE_IPA_SSA
259 && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
260 /* When not optimizing, be sure we run early local passes anyway
261 to expand OMP. */
262 || !optimize)
20099e35 263 execute_pass_list (pass_early_local_passes.pass.sub);
649597af 264 else
a41f2a28 265 compute_inline_parameters (node, true);
523c1122 266 free_dominance_info (CDI_POST_DOMINATORS);
267 free_dominance_info (CDI_DOMINATORS);
268 pop_cfun ();
269 current_function_decl = NULL;
4f7a1122 270 cgraph_call_function_insertion_hooks (node);
523c1122 271 break;
272
273 case CGRAPH_STATE_EXPANSION:
274 /* Functions created during expansion shall be compiled
275 directly. */
09fc9532 276 node->process = 0;
4f7a1122 277 cgraph_call_function_insertion_hooks (node);
523c1122 278 cgraph_expand_function (node);
279 break;
280
281 default:
282 gcc_unreachable ();
283 break;
284 }
0cddb138 285 varpool_analyze_pending_decls ();
523c1122 286 }
287 return output;
288}
289
9b8fb23a 290/* As an GCC extension we allow redefinition of the function. The
291 semantics when both copies of bodies differ is not well defined.
292 We replace the old body with new body so in unit at a time mode
293 we always use new body, while in normal mode we may end up with
294 old body inlined into some functions and new body expanded and
295 inlined in others.
296
297 ??? It may make more sense to use one body for inlining and other
298 body for expanding the function but this is difficult to do. */
299
300static void
301cgraph_reset_node (struct cgraph_node *node)
302{
09fc9532 303 /* If node->process is set, then we have already begun whole-unit analysis.
6329636b 304 This is *not* testing for whether we've already emitted the function.
305 That case can be sort-of legitimately seen with real function redefinition
306 errors. I would argue that the front end should never present us with
307 such a case, but don't enforce that for now. */
09fc9532 308 gcc_assert (!node->process);
9b8fb23a 309
310 /* Reset our data structures so we can analyze the function again. */
311 memset (&node->local, 0, sizeof (node->local));
312 memset (&node->global, 0, sizeof (node->global));
313 memset (&node->rtl, 0, sizeof (node->rtl));
314 node->analyzed = false;
9b8fb23a 315 node->local.finalized = false;
316
9b8fb23a 317 cgraph_node_remove_callees (node);
9b8fb23a 318}
c08871a9 319
28df663b 320/* DECL has been parsed. Take it, queue it, compile it at the whim of the
321 logic in effect. If NESTED is true, then our caller cannot stand to have
322 the garbage collector run at the moment. We would need to either create
323 a new GC context, or just not compile right now. */
ae01b312 324
325void
28df663b 326cgraph_finalize_function (tree decl, bool nested)
ae01b312 327{
5a90471f 328 struct cgraph_node *node = cgraph_get_create_node (decl);
ae01b312 329
c08871a9 330 if (node->local.finalized)
443089c1 331 {
332 cgraph_reset_node (node);
333 node->local.redefined_extern_inline = true;
334 }
28df663b 335
c08871a9 336 notice_global_symbol (decl);
79bb87b4 337 node->local.finalized = true;
e27482aa 338 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
ae01b312 339
7bfefa9d 340 if (cgraph_decide_is_function_needed (node, decl))
2c0b522d 341 cgraph_mark_needed_node (node);
342
ecda6e51 343 /* Since we reclaim unreachable nodes at the end of every language
3f82b628 344 level unit, we need to be conservative about possible entry points
345 there. */
1e3aebec 346 if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
347 || DECL_STATIC_CONSTRUCTOR (decl)
d050bafd 348 || DECL_STATIC_DESTRUCTOR (decl)
349 /* COMDAT virtual functions may be referenced by vtable from
0a10fd82 350 other compilation unit. Still we want to devirtualize calls
d050bafd 351 to those so we need to analyze them.
352 FIXME: We should introduce may edges for this purpose and update
353 their handling in unreachable function removal and inliner too. */
91bf9d9a 354 || (DECL_VIRTUAL_P (decl)
355 && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
3f82b628 356 cgraph_mark_reachable_node (node);
357
2c0b522d 358 /* If we've not yet emitted decl, tell the debug info about it. */
28df663b 359 if (!TREE_ASM_WRITTEN (decl))
2c0b522d 360 (*debug_hooks->deferred_inline_function) (decl);
4e8871a0 361
b69eb0ff 362 /* Possibly warn about unused parameters. */
363 if (warn_unused_parameter)
364 do_warn_unused_parameter (decl);
6329636b 365
366 if (!nested)
367 ggc_collect ();
ae01b312 368}
369
3db65b62 370/* Add the function FNDECL to the call graph.
371 Unlike cgraph_finalize_function, this function is intended to be used
372 by middle end and allows insertion of new function at arbitrary point
373 of compilation. The function can be either in high, low or SSA form
374 GIMPLE.
375
376 The function is assumed to be reachable and have address taken (so no
377 API breaking optimizations are performed on it).
378
379 Main work done by this function is to enqueue the function for later
380 processing to avoid need the passes to be re-entrant. */
381
382void
383cgraph_add_new_function (tree fndecl, bool lowered)
384{
385 struct cgraph_node *node;
386 switch (cgraph_state)
387 {
388 case CGRAPH_STATE_CONSTRUCTION:
389 /* Just enqueue function to be processed at nearest occurrence. */
390 node = cgraph_create_node (fndecl);
391 node->next_needed = cgraph_new_nodes;
392 if (lowered)
393 node->lowered = true;
394 cgraph_new_nodes = node;
395 break;
396
397 case CGRAPH_STATE_IPA:
398 case CGRAPH_STATE_IPA_SSA:
399 case CGRAPH_STATE_EXPANSION:
400 /* Bring the function into finalized state and enqueue for later
401 analyzing and compilation. */
402 node = cgraph_get_create_node (fndecl);
403 node->local.local = false;
404 node->local.finalized = true;
405 node->reachable = node->needed = true;
406 if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
407 {
408 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
409 current_function_decl = fndecl;
410 gimple_register_cfg_hooks ();
411 bitmap_obstack_initialize (NULL);
412 execute_pass_list (all_lowering_passes);
413 execute_pass_list (pass_early_local_passes.pass.sub);
414 bitmap_obstack_release (NULL);
415 pop_cfun ();
416 current_function_decl = NULL;
417
418 lowered = true;
419 }
420 if (lowered)
421 node->lowered = true;
422 node->next_needed = cgraph_new_nodes;
423 cgraph_new_nodes = node;
424 break;
425
426 case CGRAPH_STATE_FINISHED:
427 /* At the very end of compilation we have to do all the work up
428 to expansion. */
429 node = cgraph_create_node (fndecl);
430 if (lowered)
431 node->lowered = true;
432 cgraph_analyze_function (node);
433 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
434 current_function_decl = fndecl;
435 gimple_register_cfg_hooks ();
436 bitmap_obstack_initialize (NULL);
437 if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
438 execute_pass_list (pass_early_local_passes.pass.sub);
439 bitmap_obstack_release (NULL);
440 tree_rest_of_compilation (node);
441 pop_cfun ();
442 current_function_decl = NULL;
443 break;
444
445 default:
446 gcc_unreachable ();
447 }
448
449 /* Set a personality if required and we already passed EH lowering. */
450 if (lowered
451 && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl))
452 == eh_personality_lang))
453 DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
454}
455
0da03d11 456/* C99 extern inline keywords allow changing of declaration after function
457 has been finalized. We need to re-decide if we want to mark the function as
458 needed then. */
459
460void
461cgraph_mark_if_needed (tree decl)
462{
fd6a3c41 463 struct cgraph_node *node = cgraph_get_node (decl);
7bfefa9d 464 if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
0da03d11 465 cgraph_mark_needed_node (node);
466}
467
ccf4ab6b 468/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
469static bool
470clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
471{
c70f46b0 472 node = cgraph_function_or_thunk_node (node, NULL);
473 node2 = cgraph_function_or_thunk_node (node2, NULL);
ccf4ab6b 474 while (node != node2 && node2)
475 node2 = node2->clone_of;
476 return node2 != NULL;
477}
478
1a036a3b 479/* Verify edge E count and frequency. */
480
481static bool
482verify_edge_count_and_frequency (struct cgraph_edge *e)
483{
484 bool error_found = false;
485 if (e->count < 0)
486 {
487 error ("caller edge count is negative");
488 error_found = true;
489 }
490 if (e->frequency < 0)
491 {
492 error ("caller edge frequency is negative");
493 error_found = true;
494 }
495 if (e->frequency > CGRAPH_FREQ_MAX)
496 {
497 error ("caller edge frequency is too large");
498 error_found = true;
499 }
7d0d0ce1 500 if (gimple_has_body_p (e->caller->symbol.decl)
1a036a3b 501 && !e->caller->global.inlined_to
8bae3ea4 502 /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
503 Remove this once edges are actualy removed from the function at that time. */
504 && (e->frequency
505 || (inline_edge_summary_vec
9ed50dd9 506 && ((VEC_length(inline_edge_summary_t, inline_edge_summary_vec)
507 <= (unsigned) e->uid)
508 || !inline_edge_summary (e)->predicate)))
1a036a3b 509 && (e->frequency
7d0d0ce1 510 != compute_call_stmt_bb_frequency (e->caller->symbol.decl,
1a036a3b 511 gimple_bb (e->call_stmt))))
512 {
0a10fd82 513 error ("caller edge frequency %i does not match BB frequency %i",
1a036a3b 514 e->frequency,
7d0d0ce1 515 compute_call_stmt_bb_frequency (e->caller->symbol.decl,
1a036a3b 516 gimple_bb (e->call_stmt)));
517 error_found = true;
518 }
519 return error_found;
520}
521
7b29dd2f 522/* Switch to THIS_CFUN if needed and print STMT to stderr. */
523static void
524cgraph_debug_gimple_stmt (struct function *this_cfun, gimple stmt)
525{
526 /* debug_gimple_stmt needs correct cfun */
527 if (cfun != this_cfun)
528 set_cfun (this_cfun);
529 debug_gimple_stmt (stmt);
530}
531
2f9d66d3 532/* Verify that call graph edge E corresponds to DECL from the associated
533 statement. Return true if the verification should fail. */
534
535static bool
536verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
537{
54e8af13 538 struct cgraph_node *node;
539
540 if (!decl || e->callee->global.inlined_to)
541 return false;
542 node = cgraph_get_node (decl);
543
544 /* We do not know if a node from a different partition is an alias or what it
545 aliases and therefore cannot do the former_clone_of check reliably. */
7d0d0ce1 546 if (!node || node->symbol.in_other_partition)
54e8af13 547 return false;
548 node = cgraph_function_or_thunk_node (node, NULL);
549
7d0d0ce1 550 if ((e->callee->former_clone_of != node->symbol.decl
cdf67cee 551 && (!node->same_body_alias
552 || e->callee->former_clone_of != node->thunk.alias))
2f9d66d3 553 /* IPA-CP sometimes redirect edge to clone and then back to the former
cdf67cee 554 function. This ping-pong has to go, eventually. */
54e8af13 555 && (node != cgraph_function_or_thunk_node (e->callee, NULL))
cdf67cee 556 && !clone_of_p (node, e->callee)
557 /* If decl is a same body alias of some other decl, allow e->callee to be
558 a clone of a clone of that other decl too. */
559 && (!node->same_body_alias
560 || !clone_of_p (cgraph_get_node (node->thunk.alias), e->callee)))
2f9d66d3 561 return true;
562 else
563 return false;
564}
565
b0cdf642 566/* Verify cgraph nodes of given cgraph node. */
4b987fac 567DEBUG_FUNCTION void
b0cdf642 568verify_cgraph_node (struct cgraph_node *node)
569{
570 struct cgraph_edge *e;
7d0d0ce1 571 struct function *this_cfun = DECL_STRUCT_FUNCTION (node->symbol.decl);
e27482aa 572 basic_block this_block;
75a70cf9 573 gimple_stmt_iterator gsi;
9bfec7c2 574 bool error_found = false;
b0cdf642 575
852f689e 576 if (seen_error ())
bd09cd3e 577 return;
578
b0cdf642 579 timevar_push (TV_CGRAPH_VERIFY);
b0cdf642 580 for (e = node->callees; e; e = e->next_callee)
581 if (e->aux)
582 {
0a81f5a0 583 error ("aux field set for edge %s->%s",
abd3e6b5 584 identifier_to_locale (cgraph_node_name (e->caller)),
585 identifier_to_locale (cgraph_node_name (e->callee)));
b0cdf642 586 error_found = true;
587 }
a2cb9b3b 588 if (node->count < 0)
589 {
bf776685 590 error ("execution count is negative");
a2cb9b3b 591 error_found = true;
592 }
7d0d0ce1 593 if (node->global.inlined_to && node->symbol.externally_visible)
59dd4830 594 {
bf776685 595 error ("externally visible inline clone");
59dd4830 596 error_found = true;
597 }
7d0d0ce1 598 if (node->global.inlined_to && node->symbol.address_taken)
59dd4830 599 {
bf776685 600 error ("inline clone with address taken");
59dd4830 601 error_found = true;
602 }
603 if (node->global.inlined_to && node->needed)
604 {
bf776685 605 error ("inline clone is needed");
59dd4830 606 error_found = true;
607 }
799c8711 608 for (e = node->indirect_calls; e; e = e->next_callee)
609 {
610 if (e->aux)
611 {
612 error ("aux field set for indirect edge from %s",
613 identifier_to_locale (cgraph_node_name (e->caller)));
614 error_found = true;
615 }
616 if (!e->indirect_unknown_callee
617 || !e->indirect_info)
618 {
619 error ("An indirect edge from %s is not marked as indirect or has "
620 "associated indirect_info, the corresponding statement is: ",
621 identifier_to_locale (cgraph_node_name (e->caller)));
7b29dd2f 622 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
799c8711 623 error_found = true;
624 }
625 }
b0cdf642 626 for (e = node->callers; e; e = e->next_caller)
627 {
1a036a3b 628 if (verify_edge_count_and_frequency (e))
629 error_found = true;
b0cdf642 630 if (!e->inline_failed)
631 {
632 if (node->global.inlined_to
633 != (e->caller->global.inlined_to
634 ? e->caller->global.inlined_to : e->caller))
635 {
0a81f5a0 636 error ("inlined_to pointer is wrong");
b0cdf642 637 error_found = true;
638 }
639 if (node->callers->next_caller)
640 {
0a81f5a0 641 error ("multiple inline callers");
b0cdf642 642 error_found = true;
643 }
644 }
645 else
646 if (node->global.inlined_to)
647 {
0a81f5a0 648 error ("inlined_to pointer set for noninline callers");
b0cdf642 649 error_found = true;
650 }
651 }
1a036a3b 652 for (e = node->indirect_calls; e; e = e->next_callee)
653 if (verify_edge_count_and_frequency (e))
654 error_found = true;
b0cdf642 655 if (!node->callers && node->global.inlined_to)
656 {
5cd75817 657 error ("inlined_to pointer is set but no predecessors found");
b0cdf642 658 error_found = true;
659 }
660 if (node->global.inlined_to == node)
661 {
0a81f5a0 662 error ("inlined_to pointer refers to itself");
b0cdf642 663 error_found = true;
664 }
665
7d0d0ce1 666 if (!cgraph_get_node (node->symbol.decl))
b0cdf642 667 {
0f6439b9 668 error ("node not found in cgraph_hash");
b0cdf642 669 error_found = true;
670 }
a0c938f0 671
ccf4ab6b 672 if (node->clone_of)
673 {
674 struct cgraph_node *n;
675 for (n = node->clone_of->clones; n; n = n->next_sibling_clone)
676 if (n == node)
677 break;
678 if (!n)
679 {
680 error ("node has wrong clone_of");
681 error_found = true;
682 }
683 }
684 if (node->clones)
685 {
686 struct cgraph_node *n;
687 for (n = node->clones; n; n = n->next_sibling_clone)
688 if (n->clone_of != node)
689 break;
690 if (n)
691 {
692 error ("node has wrong clone list");
693 error_found = true;
694 }
695 }
696 if ((node->prev_sibling_clone || node->next_sibling_clone) && !node->clone_of)
697 {
698 error ("node is in clone list but it is not clone");
699 error_found = true;
700 }
701 if (!node->prev_sibling_clone && node->clone_of && node->clone_of->clones != node)
702 {
703 error ("node has wrong prev_clone pointer");
704 error_found = true;
705 }
706 if (node->prev_sibling_clone && node->prev_sibling_clone->next_sibling_clone != node)
707 {
708 error ("double linked list of clones corrupted");
709 error_found = true;
710 }
7d0d0ce1 711 if (node->symbol.same_comdat_group)
c524ac5d 712 {
7d0d0ce1 713 symtab_node n = node->symbol.same_comdat_group;
c524ac5d 714
7d0d0ce1 715 if (!DECL_ONE_ONLY (n->symbol.decl))
c524ac5d 716 {
717 error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
718 error_found = true;
719 }
7d0d0ce1 720 if (n == (symtab_node)node)
c524ac5d 721 {
722 error ("node is alone in a comdat group");
723 error_found = true;
724 }
725 do
726 {
7d0d0ce1 727 if (!n->symbol.same_comdat_group)
c524ac5d 728 {
729 error ("same_comdat_group is not a circular list");
730 error_found = true;
731 break;
732 }
7d0d0ce1 733 n = n->symbol.same_comdat_group;
c524ac5d 734 }
7d0d0ce1 735 while (n != (symtab_node)node);
c524ac5d 736 }
ccf4ab6b 737
c70f46b0 738 if (node->analyzed && node->alias)
739 {
740 bool ref_found = false;
741 int i;
742 struct ipa_ref *ref;
743
744 if (node->callees)
745 {
746 error ("Alias has call edges");
747 error_found = true;
748 }
7d0d0ce1 749 for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
750 i, ref); i++)
c70f46b0 751 if (ref->use != IPA_REF_ALIAS)
752 {
70f89d12 753 error ("Alias has non-alias reference");
c70f46b0 754 error_found = true;
755 }
756 else if (ref_found)
757 {
758 error ("Alias has more than one alias reference");
759 error_found = true;
760 }
761 else
762 ref_found = true;
763 if (!ref_found)
764 {
765 error ("Analyzed alias has no reference");
766 error_found = true;
767 }
768 }
91bf9d9a 769 if (node->analyzed && node->thunk.thunk_p)
770 {
771 if (!node->callees)
772 {
773 error ("No edge out of thunk node");
774 error_found = true;
775 }
776 else if (node->callees->next_callee)
777 {
778 error ("More than one edge out of thunk node");
779 error_found = true;
780 }
7d0d0ce1 781 if (gimple_has_body_p (node->symbol.decl))
91bf9d9a 782 {
783 error ("Thunk is not supposed to have body");
784 error_found = true;
785 }
786 }
7d0d0ce1 787 else if (node->analyzed && gimple_has_body_p (node->symbol.decl)
788 && !TREE_ASM_WRITTEN (node->symbol.decl)
789 && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
91bf9d9a 790 && !flag_wpa)
b0cdf642 791 {
e27482aa 792 if (this_cfun->cfg)
793 {
794 /* The nodes we're interested in are never shared, so walk
795 the tree ignoring duplicates. */
e7c352d1 796 struct pointer_set_t *visited_nodes = pointer_set_create ();
e27482aa 797 /* Reach the trees by walking over the CFG, and note the
798 enclosing basic-blocks in the call edges. */
799 FOR_EACH_BB_FN (this_block, this_cfun)
75a70cf9 800 for (gsi = gsi_start_bb (this_block);
801 !gsi_end_p (gsi);
802 gsi_next (&gsi))
9bfec7c2 803 {
75a70cf9 804 gimple stmt = gsi_stmt (gsi);
799c8711 805 if (is_gimple_call (stmt))
9bfec7c2 806 {
807 struct cgraph_edge *e = cgraph_edge (node, stmt);
799c8711 808 tree decl = gimple_call_fndecl (stmt);
9bfec7c2 809 if (e)
810 {
811 if (e->aux)
812 {
0a81f5a0 813 error ("shared call_stmt:");
7b29dd2f 814 cgraph_debug_gimple_stmt (this_cfun, stmt);
9bfec7c2 815 error_found = true;
816 }
799c8711 817 if (!e->indirect_unknown_callee)
28454517 818 {
2f9d66d3 819 if (verify_edge_corresponds_to_fndecl (e, decl))
799c8711 820 {
821 error ("edge points to wrong declaration:");
7d0d0ce1 822 debug_tree (e->callee->symbol.decl);
799c8711 823 fprintf (stderr," Instead of:");
824 debug_tree (decl);
825 error_found = true;
826 }
28454517 827 }
799c8711 828 else if (decl)
9bfec7c2 829 {
799c8711 830 error ("an indirect edge with unknown callee "
831 "corresponding to a call_stmt with "
832 "a known declaration:");
ee3f5fc0 833 error_found = true;
7b29dd2f 834 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
9bfec7c2 835 }
836 e->aux = (void *)1;
837 }
799c8711 838 else if (decl)
9bfec7c2 839 {
0a81f5a0 840 error ("missing callgraph edge for call stmt:");
7b29dd2f 841 cgraph_debug_gimple_stmt (this_cfun, stmt);
9bfec7c2 842 error_found = true;
843 }
844 }
845 }
e27482aa 846 pointer_set_destroy (visited_nodes);
e27482aa 847 }
848 else
849 /* No CFG available?! */
850 gcc_unreachable ();
851
b0cdf642 852 for (e = node->callees; e; e = e->next_callee)
853 {
799c8711 854 if (!e->aux)
b0cdf642 855 {
0a81f5a0 856 error ("edge %s->%s has no corresponding call_stmt",
abd3e6b5 857 identifier_to_locale (cgraph_node_name (e->caller)),
858 identifier_to_locale (cgraph_node_name (e->callee)));
7b29dd2f 859 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
b0cdf642 860 error_found = true;
861 }
862 e->aux = 0;
863 }
799c8711 864 for (e = node->indirect_calls; e; e = e->next_callee)
865 {
866 if (!e->aux)
867 {
868 error ("an indirect edge from %s has no corresponding call_stmt",
869 identifier_to_locale (cgraph_node_name (e->caller)));
7b29dd2f 870 cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
799c8711 871 error_found = true;
872 }
873 e->aux = 0;
874 }
b0cdf642 875 }
876 if (error_found)
877 {
878 dump_cgraph_node (stderr, node);
0a81f5a0 879 internal_error ("verify_cgraph_node failed");
b0cdf642 880 }
881 timevar_pop (TV_CGRAPH_VERIFY);
882}
883
884/* Verify whole cgraph structure. */
4b987fac 885DEBUG_FUNCTION void
b0cdf642 886verify_cgraph (void)
887{
888 struct cgraph_node *node;
889
852f689e 890 if (seen_error ())
8ec2a798 891 return;
892
b0cdf642 893 for (node = cgraph_nodes; node; node = node->next)
894 verify_cgraph_node (node);
895}
896
56af936e 897/* Output all asm statements we have stored up to be output. */
898
899static void
900cgraph_output_pending_asms (void)
901{
902 struct cgraph_asm_node *can;
903
852f689e 904 if (seen_error ())
56af936e 905 return;
906
907 for (can = cgraph_asm_nodes; can; can = can->next)
908 assemble_asm (can->asm_str);
909 cgraph_asm_nodes = NULL;
910}
911
0785e435 912/* Analyze the function scheduled to be output. */
222bc9b9 913void
0785e435 914cgraph_analyze_function (struct cgraph_node *node)
915{
bfec3452 916 tree save = current_function_decl;
7d0d0ce1 917 tree decl = node->symbol.decl;
0785e435 918
c70f46b0 919 if (node->alias && node->thunk.alias)
920 {
921 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
b0898cb7 922 struct cgraph_node *n;
923
924 for (n = tgt; n && n->alias;
925 n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL)
926 if (n == node)
927 {
7d0d0ce1 928 error ("function %q+D part of alias cycle", node->symbol.decl);
b0898cb7 929 node->alias = false;
930 return;
931 }
7d0d0ce1 932 if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
c70f46b0 933 ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
934 if (node->same_body_alias)
935 {
7d0d0ce1 936 DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
937 DECL_DECLARED_INLINE_P (node->symbol.decl)
c70f46b0 938 = DECL_DECLARED_INLINE_P (node->thunk.alias);
7d0d0ce1 939 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
c70f46b0 940 = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
941 }
942
943 /* Fixup visibility nonsences C++ frontend produce on same body aliases. */
7d0d0ce1 944 if (TREE_PUBLIC (node->symbol.decl) && node->same_body_alias)
c70f46b0 945 {
7d0d0ce1 946 DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->thunk.alias);
89bf5ca9 947 if (DECL_ONE_ONLY (node->thunk.alias))
c70f46b0 948 {
7d0d0ce1 949 DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (node->thunk.alias);
950 DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (node->thunk.alias);
951 if (DECL_ONE_ONLY (node->thunk.alias) && !node->symbol.same_comdat_group)
c70f46b0 952 {
953 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
7d0d0ce1 954 node->symbol.same_comdat_group = (symtab_node)tgt;
955 if (!tgt->symbol.same_comdat_group)
956 tgt->symbol.same_comdat_group = (symtab_node)node;
c70f46b0 957 else
958 {
7d0d0ce1 959 symtab_node n;
960 for (n = tgt->symbol.same_comdat_group;
961 n->symbol.same_comdat_group != (symtab_node)tgt;
962 n = n->symbol.same_comdat_group)
c70f46b0 963 ;
7d0d0ce1 964 n->symbol.same_comdat_group = (symtab_node)node;
c70f46b0 965 }
966 }
967 }
968 }
969 cgraph_mark_reachable_node (cgraph_alias_aliased_node (node));
7d0d0ce1 970 if (node->symbol.address_taken)
c70f46b0 971 cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
7d0d0ce1 972 if (cgraph_decide_is_function_needed (node, node->symbol.decl))
c70f46b0 973 cgraph_mark_needed_node (node);
974 }
975 else if (node->thunk.thunk_p)
91bf9d9a 976 {
977 cgraph_create_edge (node, cgraph_get_node (node->thunk.alias),
978 NULL, 0, CGRAPH_FREQ_BASE);
979 }
980 else
981 {
982 current_function_decl = decl;
983 push_cfun (DECL_STRUCT_FUNCTION (decl));
bfec3452 984
7d0d0ce1 985 assign_assembler_name_if_neeeded (node->symbol.decl);
6816d0c4 986
91bf9d9a 987 /* Make sure to gimplify bodies only once. During analyzing a
988 function we lower it, which will require gimplified nested
989 functions, so we can end up here with an already gimplified
990 body. */
991 if (!gimple_body (decl))
992 gimplify_function_tree (decl);
993 dump_function (TDI_generic, decl);
bfec3452 994
47199071 995 /* Lower the function. */
996 if (!node->lowered)
997 {
998 if (node->nested)
7d0d0ce1 999 lower_nested_functions (node->symbol.decl);
47199071 1000 gcc_assert (!node->nested);
1001
1002 gimple_register_cfg_hooks ();
1003 bitmap_obstack_initialize (NULL);
1004 execute_pass_list (all_lowering_passes);
1005 free_dominance_info (CDI_POST_DOMINATORS);
1006 free_dominance_info (CDI_DOMINATORS);
1007 compact_blocks ();
1008 bitmap_obstack_release (NULL);
1009 node->lowered = true;
1010 }
1011
91bf9d9a 1012 pop_cfun ();
1013 }
6e8d6e86 1014 node->analyzed = true;
0785e435 1015
bfec3452 1016 current_function_decl = save;
0785e435 1017}
1018
c70f46b0 1019/* C++ frontend produce same body aliases all over the place, even before PCH
1020 gets streamed out. It relies on us linking the aliases with their function
1021 in order to do the fixups, but ipa-ref is not PCH safe. Consequentely we
1022 first produce aliases without links, but once C++ FE is sure he won't sream
1023 PCH we build the links via this function. */
1024
1025void
1026cgraph_process_same_body_aliases (void)
1027{
1028 struct cgraph_node *node;
1029 for (node = cgraph_nodes; node; node = node->next)
1030 if (node->same_body_alias
7d0d0ce1 1031 && !VEC_length (ipa_ref_t, node->symbol.ref_list.references))
c70f46b0 1032 {
1033 struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
1034 ipa_record_reference (node, NULL, tgt, NULL, IPA_REF_ALIAS, NULL);
1035 }
1036 same_body_aliases_done = true;
1037}
1038
d05db70d 1039/* Process attributes common for vars and functions. */
1040
1041static void
1042process_common_attributes (tree decl)
1043{
1044 tree weakref = lookup_attribute ("weakref", DECL_ATTRIBUTES (decl));
1045
1046 if (weakref && !lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
1047 {
1048 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
1049 "%<weakref%> attribute should be accompanied with"
1050 " an %<alias%> attribute");
1051 DECL_WEAK (decl) = 0;
40b32d93 1052 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
1053 DECL_ATTRIBUTES (decl));
d05db70d 1054 }
1055}
1056
05806473 1057/* Look for externally_visible and used attributes and mark cgraph nodes
1058 accordingly.
1059
1060 We cannot mark the nodes at the point the attributes are processed (in
1061 handle_*_attribute) because the copy of the declarations available at that
1062 point may not be canonical. For example, in:
1063
1064 void f();
1065 void f() __attribute__((used));
1066
1067 the declaration we see in handle_used_attribute will be the second
1068 declaration -- but the front end will subsequently merge that declaration
1069 with the original declaration and discard the second declaration.
1070
1071 Furthermore, we can't mark these nodes in cgraph_finalize_function because:
1072
1073 void f() {}
1074 void f() __attribute__((externally_visible));
1075
1076 is valid.
1077
1078 So, we walk the nodes at the end of the translation unit, applying the
1079 attributes at that point. */
1080
1081static void
1082process_function_and_variable_attributes (struct cgraph_node *first,
1d416bd7 1083 struct varpool_node *first_var)
05806473 1084{
1085 struct cgraph_node *node;
1d416bd7 1086 struct varpool_node *vnode;
05806473 1087
1088 for (node = cgraph_nodes; node != first; node = node->next)
1089 {
7d0d0ce1 1090 tree decl = node->symbol.decl;
83a23b05 1091 if (DECL_PRESERVE_P (decl))
0b49f8f8 1092 cgraph_mark_needed_node (node);
62433d51 1093 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
1094 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
7d0d0ce1 1095 && TREE_PUBLIC (node->symbol.decl))
62433d51 1096 {
1097 if (node->local.finalized)
1098 cgraph_mark_needed_node (node);
1099 }
1100 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
05806473 1101 {
7d0d0ce1 1102 if (! TREE_PUBLIC (node->symbol.decl))
1103 warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
712d2297 1104 "%<externally_visible%>"
1105 " attribute have effect only on public objects");
59dd4830 1106 else if (node->local.finalized)
1107 cgraph_mark_needed_node (node);
05806473 1108 }
40b32d93 1109 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
c70f46b0 1110 && (node->local.finalized && !node->alias))
40b32d93 1111 {
7d0d0ce1 1112 warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
40b32d93 1113 "%<weakref%> attribute ignored"
1114 " because function is defined");
1115 DECL_WEAK (decl) = 0;
1116 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
1117 DECL_ATTRIBUTES (decl));
1118 }
a522e9eb 1119
1120 if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))
1121 && !DECL_DECLARED_INLINE_P (decl)
1122 /* redefining extern inline function makes it DECL_UNINLINABLE. */
1123 && !DECL_UNINLINABLE (decl))
1124 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
1125 "always_inline function might not be inlinable");
1126
d05db70d 1127 process_common_attributes (decl);
05806473 1128 }
1d416bd7 1129 for (vnode = varpool_nodes; vnode != first_var; vnode = vnode->next)
05806473 1130 {
7d0d0ce1 1131 tree decl = vnode->symbol.decl;
83a23b05 1132 if (DECL_PRESERVE_P (decl))
05806473 1133 {
22671757 1134 vnode->force_output = true;
05806473 1135 if (vnode->finalized)
1d416bd7 1136 varpool_mark_needed_node (vnode);
05806473 1137 }
62433d51 1138 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
1139 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
7d0d0ce1 1140 && TREE_PUBLIC (vnode->symbol.decl))
62433d51 1141 {
1142 if (vnode->finalized)
1143 varpool_mark_needed_node (vnode);
1144 }
1145 else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
05806473 1146 {
7d0d0ce1 1147 if (! TREE_PUBLIC (vnode->symbol.decl))
1148 warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
712d2297 1149 "%<externally_visible%>"
1150 " attribute have effect only on public objects");
59dd4830 1151 else if (vnode->finalized)
1152 varpool_mark_needed_node (vnode);
05806473 1153 }
40b32d93 1154 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
1155 && vnode->finalized
1156 && DECL_INITIAL (decl))
1157 {
7d0d0ce1 1158 warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
40b32d93 1159 "%<weakref%> attribute ignored"
1160 " because variable is initialized");
1161 DECL_WEAK (decl) = 0;
1162 DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
1163 DECL_ATTRIBUTES (decl));
1164 }
d05db70d 1165 process_common_attributes (decl);
05806473 1166 }
1167}
1168
aeeb194b 1169/* Process CGRAPH_NODES_NEEDED queue, analyze each function (and transitively
1170 each reachable functions) and build cgraph.
1171 The function can be called multiple times after inserting new nodes
0d424440 1172 into beginning of queue. Just the new part of queue is re-scanned then. */
ae01b312 1173
aeeb194b 1174static void
1175cgraph_analyze_functions (void)
ae01b312 1176{
c1dcd13c 1177 /* Keep track of already processed nodes when called multiple times for
06b27565 1178 intermodule optimization. */
c1dcd13c 1179 static struct cgraph_node *first_analyzed;
c17d0de1 1180 struct cgraph_node *first_processed = first_analyzed;
1d416bd7 1181 static struct varpool_node *first_analyzed_var;
aeeb194b 1182 struct cgraph_node *node, *next;
ae01b312 1183
f1c35659 1184 bitmap_obstack_initialize (NULL);
c17d0de1 1185 process_function_and_variable_attributes (first_processed,
1186 first_analyzed_var);
1187 first_processed = cgraph_nodes;
1d416bd7 1188 first_analyzed_var = varpool_nodes;
1189 varpool_analyze_pending_decls ();
f79b6507 1190 if (cgraph_dump_file)
ae01b312 1191 {
e4200070 1192 fprintf (cgraph_dump_file, "Initial entry points:");
c1dcd13c 1193 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1a1a827a 1194 if (node->needed)
f79b6507 1195 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1196 fprintf (cgraph_dump_file, "\n");
ae01b312 1197 }
aeeb194b 1198 cgraph_process_new_functions ();
ae01b312 1199
e6d2b2d8 1200 /* Propagate reachability flag and lower representation of all reachable
1201 functions. In the future, lowering will introduce new functions and
1202 new entry points on the way (by template instantiation and virtual
1203 method table generation for instance). */
3d7bfc56 1204 while (cgraph_nodes_queue)
ae01b312 1205 {
0785e435 1206 struct cgraph_edge *edge;
7d0d0ce1 1207 tree decl = cgraph_nodes_queue->symbol.decl;
3d7bfc56 1208
1209 node = cgraph_nodes_queue;
7d0d0ce1 1210 x_cgraph_nodes_queue = (symtab_node)cgraph_nodes_queue->next_needed;
b0cdf642 1211 node->next_needed = NULL;
ae01b312 1212
638531ad 1213 /* ??? It is possible to create extern inline function and later using
bbd5cba2 1214 weak alias attribute to kill its body. See
638531ad 1215 gcc.c-torture/compile/20011119-1.c */
91bf9d9a 1216 if (!DECL_STRUCT_FUNCTION (decl)
c70f46b0 1217 && (!node->alias || !node->thunk.alias)
91bf9d9a 1218 && !node->thunk.thunk_p)
9b8fb23a 1219 {
1220 cgraph_reset_node (node);
443089c1 1221 node->local.redefined_extern_inline = true;
9b8fb23a 1222 continue;
1223 }
638531ad 1224
7bfefa9d 1225 if (!node->analyzed)
1226 cgraph_analyze_function (node);
2c0b522d 1227
ae01b312 1228 for (edge = node->callees; edge; edge = edge->next_callee)
0785e435 1229 if (!edge->callee->reachable)
2c0b522d 1230 cgraph_mark_reachable_node (edge->callee);
91bf9d9a 1231 for (edge = node->callers; edge; edge = edge->next_caller)
1232 if (!edge->caller->reachable && edge->caller->thunk.thunk_p)
1233 cgraph_mark_reachable_node (edge->caller);
2c0b522d 1234
7d0d0ce1 1235 if (node->symbol.same_comdat_group)
61c2c7b1 1236 {
7d0d0ce1 1237 for (next = cgraph (node->symbol.same_comdat_group);
61c2c7b1 1238 next != node;
7d0d0ce1 1239 next = cgraph (next->symbol.same_comdat_group))
61c2c7b1 1240 cgraph_mark_reachable_node (next);
1241 }
1242
d544ceff 1243 /* If decl is a clone of an abstract function, mark that abstract
1244 function so that we don't release its body. The DECL_INITIAL() of that
fd6a3c41 1245 abstract function declaration will be later needed to output debug
1246 info. */
d544ceff 1247 if (DECL_ABSTRACT_ORIGIN (decl))
1248 {
fd6a3c41 1249 struct cgraph_node *origin_node;
1250 origin_node = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl));
d544ceff 1251 origin_node->abstract_and_needed = true;
1252 }
1253
c17d0de1 1254 /* We finalize local static variables during constructing callgraph
1255 edges. Process their attributes too. */
1256 process_function_and_variable_attributes (first_processed,
1257 first_analyzed_var);
1258 first_processed = cgraph_nodes;
1d416bd7 1259 first_analyzed_var = varpool_nodes;
1260 varpool_analyze_pending_decls ();
aeeb194b 1261 cgraph_process_new_functions ();
ae01b312 1262 }
2c0b522d 1263
aa5e06c7 1264 /* Collect entry points to the unit. */
f79b6507 1265 if (cgraph_dump_file)
3d7bfc56 1266 {
e4200070 1267 fprintf (cgraph_dump_file, "Unit entry points:");
c1dcd13c 1268 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1a1a827a 1269 if (node->needed)
f79b6507 1270 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
e4200070 1271 fprintf (cgraph_dump_file, "\n\nInitial ");
0785e435 1272 dump_cgraph (cgraph_dump_file);
7410370b 1273 dump_varpool (cgraph_dump_file);
3d7bfc56 1274 }
e6d2b2d8 1275
f79b6507 1276 if (cgraph_dump_file)
1277 fprintf (cgraph_dump_file, "\nReclaiming functions:");
ae01b312 1278
f4ec5ce1 1279 for (node = cgraph_nodes; node != first_analyzed; node = next)
ae01b312 1280 {
7d0d0ce1 1281 tree decl = node->symbol.decl;
f4ec5ce1 1282 next = node->next;
ae01b312 1283
91bf9d9a 1284 if (node->local.finalized && !gimple_has_body_p (decl)
c70f46b0 1285 && (!node->alias || !node->thunk.alias)
91bf9d9a 1286 && !node->thunk.thunk_p)
a0c938f0 1287 cgraph_reset_node (node);
9b8fb23a 1288
91bf9d9a 1289 if (!node->reachable
c70f46b0 1290 && (gimple_has_body_p (decl) || node->thunk.thunk_p
1291 || (node->alias && node->thunk.alias)))
ae01b312 1292 {
f79b6507 1293 if (cgraph_dump_file)
1294 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
b0cdf642 1295 cgraph_remove_node (node);
9b8fb23a 1296 continue;
ae01b312 1297 }
bc5cab3b 1298 else
1299 node->next_needed = NULL;
91bf9d9a 1300 gcc_assert (!node->local.finalized || node->thunk.thunk_p
c70f46b0 1301 || node->alias
91bf9d9a 1302 || gimple_has_body_p (decl));
9b8fb23a 1303 gcc_assert (node->analyzed == node->local.finalized);
ae01b312 1304 }
f79b6507 1305 if (cgraph_dump_file)
e4200070 1306 {
1307 fprintf (cgraph_dump_file, "\n\nReclaimed ");
1308 dump_cgraph (cgraph_dump_file);
7410370b 1309 dump_varpool (cgraph_dump_file);
e4200070 1310 }
f1c35659 1311 bitmap_obstack_release (NULL);
c1dcd13c 1312 first_analyzed = cgraph_nodes;
ae01b312 1313 ggc_collect ();
aeeb194b 1314}
1315
3a849bc1 1316/* Translate the ugly representation of aliases as alias pairs into nice
1317 representation in callgraph. We don't handle all cases yet,
1318 unforutnately. */
1319
1320static void
1321handle_alias_pairs (void)
1322{
1323 alias_pair *p;
1324 unsigned i;
1325 struct cgraph_node *target_node;
1326 struct cgraph_node *src_node;
e0eaac80 1327 struct varpool_node *target_vnode;
3a849bc1 1328
1329 for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
1330 {
1331 if (TREE_CODE (p->decl) == FUNCTION_DECL
3a849bc1 1332 && (target_node = cgraph_node_for_asm (p->target)) != NULL)
1333 {
1334 src_node = cgraph_get_node (p->decl);
1335 if (src_node && src_node->local.finalized)
1336 cgraph_reset_node (src_node);
1337 /* Normally EXTERNAL flag is used to mark external inlines,
1338 however for aliases it seems to be allowed to use it w/o
1339 any meaning. See gcc.dg/attr-alias-3.c
1340 However for weakref we insist on EXTERNAL flag being set.
1341 See gcc.dg/attr-alias-5.c */
1342 if (DECL_EXTERNAL (p->decl))
7d0d0ce1 1343 DECL_EXTERNAL (p->decl)
1344 = lookup_attribute ("weakref",
1345 DECL_ATTRIBUTES (p->decl)) != NULL;
1346 cgraph_create_function_alias (p->decl, target_node->symbol.decl);
3a849bc1 1347 VEC_unordered_remove (alias_pair, alias_pairs, i);
1348 }
e0eaac80 1349 else if (TREE_CODE (p->decl) == VAR_DECL
e0eaac80 1350 && (target_vnode = varpool_node_for_asm (p->target)) != NULL)
1351 {
1352 /* Normally EXTERNAL flag is used to mark external inlines,
1353 however for aliases it seems to be allowed to use it w/o
1354 any meaning. See gcc.dg/attr-alias-3.c
1355 However for weakref we insist on EXTERNAL flag being set.
1356 See gcc.dg/attr-alias-5.c */
1357 if (DECL_EXTERNAL (p->decl))
7d0d0ce1 1358 DECL_EXTERNAL (p->decl)
1359 = lookup_attribute ("weakref",
1360 DECL_ATTRIBUTES (p->decl)) != NULL;
1361 varpool_create_variable_alias (p->decl, target_vnode->symbol.decl);
e0eaac80 1362 VEC_unordered_remove (alias_pair, alias_pairs, i);
1363 }
badeded8 1364 /* Weakrefs with target not defined in current unit are easy to handle; they
1365 behave just as external variables except we need to note the alias flag
1366 to later output the weakref pseudo op into asm file. */
1367 else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
1368 && (TREE_CODE (p->decl) == FUNCTION_DECL
1369 ? (varpool_node_for_asm (p->target) == NULL)
1370 : (cgraph_node_for_asm (p->target) == NULL)))
1371 {
1372 if (TREE_CODE (p->decl) == FUNCTION_DECL)
1373 cgraph_get_create_node (p->decl)->alias = true;
1374 else
1375 varpool_get_node (p->decl)->alias = true;
1376 DECL_EXTERNAL (p->decl) = 1;
1377 VEC_unordered_remove (alias_pair, alias_pairs, i);
1378 }
3a849bc1 1379 else
1380 {
1381 if (dump_file)
1382 fprintf (dump_file, "Unhandled alias %s->%s\n",
1383 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
1384 IDENTIFIER_POINTER (p->target));
1385
1386 i++;
1387 }
1388 }
1389}
1390
8f69fd82 1391
ae01b312 1392/* Figure out what functions we want to assemble. */
1393
1394static void
d9d9733a 1395cgraph_mark_functions_to_output (void)
ae01b312 1396{
1397 struct cgraph_node *node;
61c2c7b1 1398#ifdef ENABLE_CHECKING
1399 bool check_same_comdat_groups = false;
1400
1401 for (node = cgraph_nodes; node; node = node->next)
1402 gcc_assert (!node->process);
1403#endif
ae01b312 1404
ae01b312 1405 for (node = cgraph_nodes; node; node = node->next)
1406 {
7d0d0ce1 1407 tree decl = node->symbol.decl;
d7c6d889 1408 struct cgraph_edge *e;
a0c938f0 1409
7d0d0ce1 1410 gcc_assert (!node->process || node->symbol.same_comdat_group);
61c2c7b1 1411 if (node->process)
1412 continue;
d7c6d889 1413
1414 for (e = node->callers; e; e = e->next_caller)
611e5405 1415 if (e->inline_failed)
d7c6d889 1416 break;
ae01b312 1417
e6d2b2d8 1418 /* We need to output all local functions that are used and not
1419 always inlined, as well as those that are reachable from
1420 outside the current compilation unit. */
1a1a827a 1421 if (node->analyzed
91bf9d9a 1422 && !node->thunk.thunk_p
c70f46b0 1423 && !node->alias
b0cdf642 1424 && !node->global.inlined_to
1e3aebec 1425 && (!cgraph_only_called_directly_p (node)
7d0d0ce1 1426 || ((e || ipa_ref_has_aliases_p (&node->symbol.ref_list))
c70f46b0 1427 && node->reachable))
4ee9c684 1428 && !TREE_ASM_WRITTEN (decl)
ae01b312 1429 && !DECL_EXTERNAL (decl))
61c2c7b1 1430 {
1431 node->process = 1;
7d0d0ce1 1432 if (node->symbol.same_comdat_group)
61c2c7b1 1433 {
1434 struct cgraph_node *next;
7d0d0ce1 1435 for (next = cgraph (node->symbol.same_comdat_group);
61c2c7b1 1436 next != node;
7d0d0ce1 1437 next = cgraph (next->symbol.same_comdat_group))
c70f46b0 1438 if (!next->thunk.thunk_p && !next->alias)
91bf9d9a 1439 next->process = 1;
61c2c7b1 1440 }
1441 }
7d0d0ce1 1442 else if (node->symbol.same_comdat_group)
61c2c7b1 1443 {
1444#ifdef ENABLE_CHECKING
1445 check_same_comdat_groups = true;
1446#endif
1447 }
cc636d56 1448 else
9cee7c3f 1449 {
1450 /* We should've reclaimed all functions that are not needed. */
1451#ifdef ENABLE_CHECKING
75a70cf9 1452 if (!node->global.inlined_to
1a1a827a 1453 && gimple_has_body_p (decl)
08843223 1454 /* FIXME: in ltrans unit when offline copy is outside partition but inline copies
1455 are inside partition, we can end up not removing the body since we no longer
1456 have analyzed node pointing to it. */
7d0d0ce1 1457 && !node->symbol.in_other_partition
c70f46b0 1458 && !node->alias
9cee7c3f 1459 && !DECL_EXTERNAL (decl))
1460 {
1461 dump_cgraph_node (stderr, node);
1462 internal_error ("failed to reclaim unneeded function");
1463 }
1464#endif
75a70cf9 1465 gcc_assert (node->global.inlined_to
1a1a827a 1466 || !gimple_has_body_p (decl)
7d0d0ce1 1467 || node->symbol.in_other_partition
9cee7c3f 1468 || DECL_EXTERNAL (decl));
1469
1470 }
a0c938f0 1471
961e3b13 1472 }
61c2c7b1 1473#ifdef ENABLE_CHECKING
1474 if (check_same_comdat_groups)
1475 for (node = cgraph_nodes; node; node = node->next)
7d0d0ce1 1476 if (node->symbol.same_comdat_group && !node->process)
61c2c7b1 1477 {
7d0d0ce1 1478 tree decl = node->symbol.decl;
61c2c7b1 1479 if (!node->global.inlined_to
1480 && gimple_has_body_p (decl)
6d36105a 1481 /* FIXME: in an ltrans unit when the offline copy is outside a
1482 partition but inline copies are inside a partition, we can
1483 end up not removing the body since we no longer have an
1484 analyzed node pointing to it. */
7d0d0ce1 1485 && !node->symbol.in_other_partition
61c2c7b1 1486 && !DECL_EXTERNAL (decl))
1487 {
1488 dump_cgraph_node (stderr, node);
6d36105a 1489 internal_error ("failed to reclaim unneeded function in same "
1490 "comdat group");
61c2c7b1 1491 }
1492 }
1493#endif
961e3b13 1494}
1495
28454517 1496/* DECL is FUNCTION_DECL. Initialize datastructures so DECL is a function
1497 in lowered gimple form.
1498
1499 Set current_function_decl and cfun to newly constructed empty function body.
1500 return basic block in the function body. */
1501
1502static basic_block
1503init_lowered_empty_function (tree decl)
1504{
1505 basic_block bb;
1506
1507 current_function_decl = decl;
1508 allocate_struct_function (decl, false);
1509 gimple_register_cfg_hooks ();
1510 init_empty_tree_cfg ();
1511 init_tree_ssa (cfun);
1512 init_ssa_operands ();
1513 cfun->gimple_df->in_ssa_p = true;
1514 DECL_INITIAL (decl) = make_node (BLOCK);
1515
1516 DECL_SAVED_TREE (decl) = error_mark_node;
1517 cfun->curr_properties |=
1518 (PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg | PROP_referenced_vars |
657e3a56 1519 PROP_ssa | PROP_gimple_any);
28454517 1520
1521 /* Create BB for body of the function and connect it properly. */
1522 bb = create_basic_block (NULL, (void *) 0, ENTRY_BLOCK_PTR);
167ef6d9 1523 make_edge (ENTRY_BLOCK_PTR, bb, 0);
1524 make_edge (bb, EXIT_BLOCK_PTR, 0);
28454517 1525
1526 return bb;
1527}
1528
1529/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
1530 offset indicated by VIRTUAL_OFFSET, if that is
1531 non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
1532 zero for a result adjusting thunk. */
1533
1534static tree
1535thunk_adjust (gimple_stmt_iterator * bsi,
1536 tree ptr, bool this_adjusting,
1537 HOST_WIDE_INT fixed_offset, tree virtual_offset)
1538{
1539 gimple stmt;
1540 tree ret;
1541
55d6cb23 1542 if (this_adjusting
1543 && fixed_offset != 0)
28454517 1544 {
2cc66f2a 1545 stmt = gimple_build_assign
1546 (ptr, fold_build_pointer_plus_hwi_loc (input_location,
1547 ptr,
1548 fixed_offset));
28454517 1549 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1550 }
1551
1552 /* If there's a virtual offset, look up that value in the vtable and
1553 adjust the pointer again. */
1554 if (virtual_offset)
1555 {
1556 tree vtabletmp;
1557 tree vtabletmp2;
1558 tree vtabletmp3;
28454517 1559
1560 if (!vtable_entry_type)
1561 {
1562 tree vfunc_type = make_node (FUNCTION_TYPE);
1563 TREE_TYPE (vfunc_type) = integer_type_node;
1564 TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
1565 layout_type (vfunc_type);
1566
1567 vtable_entry_type = build_pointer_type (vfunc_type);
1568 }
1569
1570 vtabletmp =
1571 create_tmp_var (build_pointer_type
1572 (build_pointer_type (vtable_entry_type)), "vptr");
1573
1574 /* The vptr is always at offset zero in the object. */
1575 stmt = gimple_build_assign (vtabletmp,
1576 build1 (NOP_EXPR, TREE_TYPE (vtabletmp),
1577 ptr));
1578 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1579 mark_symbols_for_renaming (stmt);
1580 find_referenced_vars_in (stmt);
1581
1582 /* Form the vtable address. */
1583 vtabletmp2 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp)),
1584 "vtableaddr");
1585 stmt = gimple_build_assign (vtabletmp2,
182cf5a9 1586 build_simple_mem_ref (vtabletmp));
28454517 1587 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1588 mark_symbols_for_renaming (stmt);
1589 find_referenced_vars_in (stmt);
1590
1591 /* Find the entry with the vcall offset. */
1592 stmt = gimple_build_assign (vtabletmp2,
2cc66f2a 1593 fold_build_pointer_plus_loc (input_location,
1594 vtabletmp2,
1595 virtual_offset));
28454517 1596 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1597
1598 /* Get the offset itself. */
1599 vtabletmp3 = create_tmp_var (TREE_TYPE (TREE_TYPE (vtabletmp2)),
1600 "vcalloffset");
1601 stmt = gimple_build_assign (vtabletmp3,
182cf5a9 1602 build_simple_mem_ref (vtabletmp2));
28454517 1603 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1604 mark_symbols_for_renaming (stmt);
1605 find_referenced_vars_in (stmt);
1606
28454517 1607 /* Adjust the `this' pointer. */
a0553bff 1608 ptr = fold_build_pointer_plus_loc (input_location, ptr, vtabletmp3);
1609 ptr = force_gimple_operand_gsi (bsi, ptr, true, NULL_TREE, false,
1610 GSI_CONTINUE_LINKING);
28454517 1611 }
1612
55d6cb23 1613 if (!this_adjusting
1614 && fixed_offset != 0)
28454517 1615 /* Adjust the pointer by the constant. */
1616 {
1617 tree ptrtmp;
1618
1619 if (TREE_CODE (ptr) == VAR_DECL)
1620 ptrtmp = ptr;
1621 else
1622 {
1623 ptrtmp = create_tmp_var (TREE_TYPE (ptr), "ptr");
1624 stmt = gimple_build_assign (ptrtmp, ptr);
1625 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1626 mark_symbols_for_renaming (stmt);
1627 find_referenced_vars_in (stmt);
1628 }
2cc66f2a 1629 ptr = fold_build_pointer_plus_hwi_loc (input_location,
1630 ptrtmp, fixed_offset);
28454517 1631 }
1632
1633 /* Emit the statement and gimplify the adjustment expression. */
1634 ret = create_tmp_var (TREE_TYPE (ptr), "adjusted_this");
1635 stmt = gimple_build_assign (ret, ptr);
1636 mark_symbols_for_renaming (stmt);
1637 find_referenced_vars_in (stmt);
1638 gsi_insert_after (bsi, stmt, GSI_NEW_STMT);
1639
1640 return ret;
1641}
1642
1643/* Produce assembler for thunk NODE. */
1644
1645static void
1646assemble_thunk (struct cgraph_node *node)
1647{
1648 bool this_adjusting = node->thunk.this_adjusting;
1649 HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset;
1650 HOST_WIDE_INT virtual_value = node->thunk.virtual_value;
1651 tree virtual_offset = NULL;
1652 tree alias = node->thunk.alias;
7d0d0ce1 1653 tree thunk_fndecl = node->symbol.decl;
28454517 1654 tree a = DECL_ARGUMENTS (thunk_fndecl);
1655
1656 current_function_decl = thunk_fndecl;
1657
aed6e608 1658 /* Ensure thunks are emitted in their correct sections. */
1659 resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
1660
28454517 1661 if (this_adjusting
1662 && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
1663 virtual_value, alias))
1664 {
1665 const char *fnname;
1666 tree fn_block;
28b2c6a7 1667 tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
28454517 1668
1669 DECL_RESULT (thunk_fndecl)
1670 = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
28b2c6a7 1671 RESULT_DECL, 0, restype);
22ea3b47 1672 fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
28454517 1673
1674 /* The back end expects DECL_INITIAL to contain a BLOCK, so we
1675 create one. */
1676 fn_block = make_node (BLOCK);
1677 BLOCK_VARS (fn_block) = a;
1678 DECL_INITIAL (thunk_fndecl) = fn_block;
1679 init_function_start (thunk_fndecl);
1680 cfun->is_thunk = 1;
1681 assemble_start_function (thunk_fndecl, fnname);
1682
1683 targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
1684 fixed_offset, virtual_value, alias);
1685
1686 assemble_end_function (thunk_fndecl, fnname);
1687 init_insn_lengths ();
1688 free_after_compilation (cfun);
1689 set_cfun (NULL);
1690 TREE_ASM_WRITTEN (thunk_fndecl) = 1;
91bf9d9a 1691 node->thunk.thunk_p = false;
1692 node->analyzed = false;
28454517 1693 }
1694 else
1695 {
1696 tree restype;
1697 basic_block bb, then_bb, else_bb, return_bb;
1698 gimple_stmt_iterator bsi;
1699 int nargs = 0;
1700 tree arg;
1701 int i;
1702 tree resdecl;
1703 tree restmp = NULL;
1704 VEC(tree, heap) *vargs;
1705
1706 gimple call;
1707 gimple ret;
1708
1709 DECL_IGNORED_P (thunk_fndecl) = 1;
1710 bitmap_obstack_initialize (NULL);
1711
1712 if (node->thunk.virtual_offset_p)
1713 virtual_offset = size_int (virtual_value);
1714
1715 /* Build the return declaration for the function. */
1716 restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
1717 if (DECL_RESULT (thunk_fndecl) == NULL_TREE)
1718 {
1719 resdecl = build_decl (input_location, RESULT_DECL, 0, restype);
1720 DECL_ARTIFICIAL (resdecl) = 1;
1721 DECL_IGNORED_P (resdecl) = 1;
1722 DECL_RESULT (thunk_fndecl) = resdecl;
1723 }
1724 else
1725 resdecl = DECL_RESULT (thunk_fndecl);
1726
1727 bb = then_bb = else_bb = return_bb = init_lowered_empty_function (thunk_fndecl);
1728
1729 bsi = gsi_start_bb (bb);
1730
1731 /* Build call to the function being thunked. */
1732 if (!VOID_TYPE_P (restype))
1733 {
1734 if (!is_gimple_reg_type (restype))
1735 {
1736 restmp = resdecl;
2ab2ce89 1737 add_local_decl (cfun, restmp);
28454517 1738 BLOCK_VARS (DECL_INITIAL (current_function_decl)) = restmp;
1739 }
1740 else
1741 restmp = create_tmp_var_raw (restype, "retval");
1742 }
1743
1767a056 1744 for (arg = a; arg; arg = DECL_CHAIN (arg))
28454517 1745 nargs++;
1746 vargs = VEC_alloc (tree, heap, nargs);
1747 if (this_adjusting)
1748 VEC_quick_push (tree, vargs,
1749 thunk_adjust (&bsi,
1750 a, 1, fixed_offset,
1751 virtual_offset));
1752 else
1753 VEC_quick_push (tree, vargs, a);
1767a056 1754 for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg))
28454517 1755 VEC_quick_push (tree, vargs, arg);
1756 call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs);
1757 VEC_free (tree, heap, vargs);
28454517 1758 gimple_call_set_from_thunk (call, true);
1759 if (restmp)
1760 gimple_call_set_lhs (call, restmp);
1761 gsi_insert_after (&bsi, call, GSI_NEW_STMT);
1762 mark_symbols_for_renaming (call);
1763 find_referenced_vars_in (call);
1764 update_stmt (call);
1765
1766 if (restmp && !this_adjusting)
1767 {
57ab8ec3 1768 tree true_label = NULL_TREE;
28454517 1769
1770 if (TREE_CODE (TREE_TYPE (restmp)) == POINTER_TYPE)
1771 {
1772 gimple stmt;
1773 /* If the return type is a pointer, we need to
1774 protect against NULL. We know there will be an
1775 adjustment, because that's why we're emitting a
1776 thunk. */
1777 then_bb = create_basic_block (NULL, (void *) 0, bb);
1778 return_bb = create_basic_block (NULL, (void *) 0, then_bb);
1779 else_bb = create_basic_block (NULL, (void *) 0, else_bb);
1780 remove_edge (single_succ_edge (bb));
1781 true_label = gimple_block_label (then_bb);
28454517 1782 stmt = gimple_build_cond (NE_EXPR, restmp,
385f3f36 1783 build_zero_cst (TREE_TYPE (restmp)),
28454517 1784 NULL_TREE, NULL_TREE);
1785 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1786 make_edge (bb, then_bb, EDGE_TRUE_VALUE);
1787 make_edge (bb, else_bb, EDGE_FALSE_VALUE);
1788 make_edge (return_bb, EXIT_BLOCK_PTR, 0);
1789 make_edge (then_bb, return_bb, EDGE_FALLTHRU);
1790 make_edge (else_bb, return_bb, EDGE_FALLTHRU);
1791 bsi = gsi_last_bb (then_bb);
1792 }
1793
1794 restmp = thunk_adjust (&bsi, restmp, /*this_adjusting=*/0,
1795 fixed_offset, virtual_offset);
1796 if (true_label)
1797 {
1798 gimple stmt;
1799 bsi = gsi_last_bb (else_bb);
385f3f36 1800 stmt = gimple_build_assign (restmp,
1801 build_zero_cst (TREE_TYPE (restmp)));
28454517 1802 gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
1803 bsi = gsi_last_bb (return_bb);
1804 }
1805 }
1806 else
1807 gimple_call_set_tail (call, true);
1808
1809 /* Build return value. */
1810 ret = gimple_build_return (restmp);
1811 gsi_insert_after (&bsi, ret, GSI_NEW_STMT);
1812
1813 delete_unreachable_blocks ();
1814 update_ssa (TODO_update_ssa);
1815
28454517 1816 /* Since we want to emit the thunk, we explicitly mark its name as
1817 referenced. */
91bf9d9a 1818 node->thunk.thunk_p = false;
1819 cgraph_node_remove_callees (node);
28454517 1820 cgraph_add_new_function (thunk_fndecl, true);
1821 bitmap_obstack_release (NULL);
1822 }
1823 current_function_decl = NULL;
1824}
1825
91bf9d9a 1826
c70f46b0 1827
1828/* Assemble thunks and aliases asociated to NODE. */
91bf9d9a 1829
1830static void
c70f46b0 1831assemble_thunks_and_aliases (struct cgraph_node *node)
91bf9d9a 1832{
1833 struct cgraph_edge *e;
c70f46b0 1834 int i;
1835 struct ipa_ref *ref;
1836
91bf9d9a 1837 for (e = node->callers; e;)
1838 if (e->caller->thunk.thunk_p)
1839 {
1840 struct cgraph_node *thunk = e->caller;
1841
1842 e = e->next_caller;
c70f46b0 1843 assemble_thunks_and_aliases (thunk);
91bf9d9a 1844 assemble_thunk (thunk);
1845 }
1846 else
1847 e = e->next_caller;
7d0d0ce1 1848 for (i = 0; ipa_ref_list_refering_iterate (&node->symbol.ref_list,
1849 i, ref); i++)
c70f46b0 1850 if (ref->use == IPA_REF_ALIAS)
1851 {
1852 struct cgraph_node *alias = ipa_ref_refering_node (ref);
968b8c52 1853 bool saved_written = TREE_ASM_WRITTEN (alias->thunk.alias);
1854
1855 /* Force assemble_alias to really output the alias this time instead
1856 of buffering it in same alias pairs. */
1857 TREE_ASM_WRITTEN (alias->thunk.alias) = 1;
7d0d0ce1 1858 assemble_alias (alias->symbol.decl,
c70f46b0 1859 DECL_ASSEMBLER_NAME (alias->thunk.alias));
1860 assemble_thunks_and_aliases (alias);
968b8c52 1861 TREE_ASM_WRITTEN (alias->thunk.alias) = saved_written;
c70f46b0 1862 }
91bf9d9a 1863}
1864
3db65b62 1865/* Perform IPA transforms and all further optimizations and compilation
1866 for FNDECL. */
941366fd 1867
3db65b62 1868static void
941366fd 1869tree_rest_of_compilation (struct cgraph_node *node)
1870{
7d0d0ce1 1871 tree fndecl = node->symbol.decl;
941366fd 1872 location_t saved_loc;
1873
1874 timevar_push (TV_REST_OF_COMPILATION);
1875
1876 gcc_assert (cgraph_global_info_ready);
1877
1878 /* Initialize the default bitmap obstack. */
1879 bitmap_obstack_initialize (NULL);
1880
1881 /* Initialize the RTL code for the function. */
1882 current_function_decl = fndecl;
1883 saved_loc = input_location;
1884 input_location = DECL_SOURCE_LOCATION (fndecl);
1885 init_function_start (fndecl);
1886
1887 gimple_register_cfg_hooks ();
1888
1889 bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
1890
1891 execute_all_ipa_transforms ();
1892
1893 /* Perform all tree transforms and optimizations. */
1894
1895 /* Signal the start of passes. */
1896 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
1897
1898 execute_pass_list (all_passes);
1899
1900 /* Signal the end of passes. */
1901 invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
1902
1903 bitmap_obstack_release (&reg_obstack);
1904
1905 /* Release the default bitmap obstack. */
1906 bitmap_obstack_release (NULL);
1907
1908 set_cfun (NULL);
1909
1910 /* If requested, warn about function definitions where the function will
1911 return a value (usually of some struct or union type) which itself will
1912 take up a lot of stack space. */
1913 if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
1914 {
1915 tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
1916
1917 if (ret_type && TYPE_SIZE_UNIT (ret_type)
1918 && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
1919 && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
1920 larger_than_size))
1921 {
1922 unsigned int size_as_int
1923 = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
1924
1925 if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
1926 warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes",
1927 fndecl, size_as_int);
1928 else
1929 warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes",
1930 fndecl, larger_than_size);
1931 }
1932 }
1933
1934 gimple_set_body (fndecl, NULL);
1935 if (DECL_STRUCT_FUNCTION (fndecl) == 0
1936 && !cgraph_get_node (fndecl)->origin)
1937 {
1938 /* Stop pointing to the local nodes about to be freed.
1939 But DECL_INITIAL must remain nonzero so we know this
1940 was an actual function definition.
1941 For a nested function, this is done in c_pop_function_context.
1942 If rest_of_compilation set this to 0, leave it 0. */
1943 if (DECL_INITIAL (fndecl) != 0)
1944 DECL_INITIAL (fndecl) = error_mark_node;
1945 }
1946
1947 input_location = saved_loc;
1948
1949 ggc_collect ();
1950 timevar_pop (TV_REST_OF_COMPILATION);
1951}
1952
ae01b312 1953/* Expand function specified by NODE. */
e6d2b2d8 1954
ae01b312 1955static void
d9d9733a 1956cgraph_expand_function (struct cgraph_node *node)
ae01b312 1957{
7d0d0ce1 1958 tree decl = node->symbol.decl;
ae01b312 1959
b0cdf642 1960 /* We ought to not compile any inline clones. */
cc636d56 1961 gcc_assert (!node->global.inlined_to);
b0cdf642 1962
6329636b 1963 announce_function (decl);
09fc9532 1964 node->process = 0;
f7777314 1965 gcc_assert (node->lowered);
1966
1967 /* Generate RTL for the body of DECL. */
941366fd 1968 tree_rest_of_compilation (node);
f7777314 1969
1970 /* Make sure that BE didn't give up on compiling. */
1971 gcc_assert (TREE_ASM_WRITTEN (decl));
1972 current_function_decl = NULL;
cc91b414 1973 gcc_assert (!cgraph_preserve_function_body_p (node));
f76f7453 1974
1975 /* It would make a lot more sense to output thunks before function body to get more
1976 forward and lest backwarding jumps. This is however would need solving problem
1977 with comdats. See PR48668. Also aliases must come after function itself to
1978 make one pass assemblers, like one on AIX happy. See PR 50689.
1979 FIXME: Perhaps thunks should be move before function IFF they are not in comdat
1980 groups. */
1981 assemble_thunks_and_aliases (node);
1a1a827a 1982 cgraph_release_function_body (node);
1983 /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
1984 points to the dead function body. */
1985 cgraph_node_remove_callees (node);
ae01b312 1986}
1987
b0cdf642 1988/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
d7c6d889 1989
1990bool
326a9581 1991cgraph_inline_p (struct cgraph_edge *e, cgraph_inline_failed_t *reason)
d7c6d889 1992{
b0cdf642 1993 *reason = e->inline_failed;
1994 return !e->inline_failed;
d7c6d889 1995}
b0cdf642 1996
acc70efa 1997
acc70efa 1998
d9d9733a 1999/* Expand all functions that must be output.
2000
d7c6d889 2001 Attempt to topologically sort the nodes so function is output when
2002 all called functions are already assembled to allow data to be
91c82c20 2003 propagated across the callgraph. Use a stack to get smaller distance
3927afe0 2004 between a function and its callees (later we may choose to use a more
d7c6d889 2005 sophisticated algorithm for function reordering; we will likely want
2006 to use subsections to make the output functions appear in top-down
2007 order). */
2008
2009static void
a6868229 2010cgraph_expand_all_functions (void)
d7c6d889 2011{
2012 struct cgraph_node *node;
4c36ffe6 2013 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
c04e3894 2014 int order_pos, new_order_pos = 0;
d7c6d889 2015 int i;
2016
7771d558 2017 order_pos = ipa_reverse_postorder (order);
cc636d56 2018 gcc_assert (order_pos == cgraph_n_nodes);
d7c6d889 2019
7bd28bba 2020 /* Garbage collector may remove inline clones we eliminate during
b0cdf642 2021 optimization. So we must be sure to not reference them. */
2022 for (i = 0; i < order_pos; i++)
09fc9532 2023 if (order[i]->process)
b0cdf642 2024 order[new_order_pos++] = order[i];
2025
2026 for (i = new_order_pos - 1; i >= 0; i--)
d7c6d889 2027 {
2028 node = order[i];
09fc9532 2029 if (node->process)
d7c6d889 2030 {
cc636d56 2031 gcc_assert (node->reachable);
09fc9532 2032 node->process = 0;
d7c6d889 2033 cgraph_expand_function (node);
2034 }
2035 }
523c1122 2036 cgraph_process_new_functions ();
773c5ba7 2037
d7c6d889 2038 free (order);
773c5ba7 2039
d7c6d889 2040}
2041
56af936e 2042/* This is used to sort the node types by the cgraph order number. */
2043
0b09525f 2044enum cgraph_order_sort_kind
2045{
2046 ORDER_UNDEFINED = 0,
2047 ORDER_FUNCTION,
2048 ORDER_VAR,
2049 ORDER_ASM
2050};
2051
56af936e 2052struct cgraph_order_sort
2053{
0b09525f 2054 enum cgraph_order_sort_kind kind;
56af936e 2055 union
2056 {
2057 struct cgraph_node *f;
1d416bd7 2058 struct varpool_node *v;
56af936e 2059 struct cgraph_asm_node *a;
2060 } u;
2061};
2062
2063/* Output all functions, variables, and asm statements in the order
2064 according to their order fields, which is the order in which they
2065 appeared in the file. This implements -fno-toplevel-reorder. In
2066 this mode we may output functions and variables which don't really
2067 need to be output. */
2068
2069static void
2070cgraph_output_in_order (void)
2071{
2072 int max;
56af936e 2073 struct cgraph_order_sort *nodes;
2074 int i;
2075 struct cgraph_node *pf;
1d416bd7 2076 struct varpool_node *pv;
56af936e 2077 struct cgraph_asm_node *pa;
2078
2079 max = cgraph_order;
3e1cde87 2080 nodes = XCNEWVEC (struct cgraph_order_sort, max);
56af936e 2081
1d416bd7 2082 varpool_analyze_pending_decls ();
56af936e 2083
2084 for (pf = cgraph_nodes; pf; pf = pf->next)
2085 {
c70f46b0 2086 if (pf->process && !pf->thunk.thunk_p && !pf->alias)
56af936e 2087 {
7d0d0ce1 2088 i = pf->symbol.order;
56af936e 2089 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
2090 nodes[i].kind = ORDER_FUNCTION;
2091 nodes[i].u.f = pf;
2092 }
2093 }
2094
1d416bd7 2095 for (pv = varpool_nodes_queue; pv; pv = pv->next_needed)
56af936e 2096 {
7d0d0ce1 2097 i = pv->symbol.order;
56af936e 2098 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
2099 nodes[i].kind = ORDER_VAR;
2100 nodes[i].u.v = pv;
2101 }
2102
2103 for (pa = cgraph_asm_nodes; pa; pa = pa->next)
2104 {
2105 i = pa->order;
2106 gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
2107 nodes[i].kind = ORDER_ASM;
2108 nodes[i].u.a = pa;
2109 }
56af936e 2110
304e5318 2111 /* In toplevel reorder mode we output all statics; mark them as needed. */
2112 for (i = 0; i < max; ++i)
2113 {
2114 if (nodes[i].kind == ORDER_VAR)
2115 {
2116 varpool_mark_needed_node (nodes[i].u.v);
2117 }
2118 }
2119 varpool_empty_needed_queue ();
2120
91da0f1c 2121 for (i = 0; i < max; ++i)
2122 if (nodes[i].kind == ORDER_VAR)
2123 varpool_finalize_named_section_flags (nodes[i].u.v);
2124
56af936e 2125 for (i = 0; i < max; ++i)
2126 {
2127 switch (nodes[i].kind)
2128 {
2129 case ORDER_FUNCTION:
09fc9532 2130 nodes[i].u.f->process = 0;
56af936e 2131 cgraph_expand_function (nodes[i].u.f);
2132 break;
2133
2134 case ORDER_VAR:
1d416bd7 2135 varpool_assemble_decl (nodes[i].u.v);
56af936e 2136 break;
2137
2138 case ORDER_ASM:
2139 assemble_asm (nodes[i].u.a->asm_str);
2140 break;
2141
2142 case ORDER_UNDEFINED:
2143 break;
2144
2145 default:
2146 gcc_unreachable ();
2147 }
2148 }
4b4ea2db 2149
2150 cgraph_asm_nodes = NULL;
3e1cde87 2151 free (nodes);
56af936e 2152}
2153
b0cdf642 2154/* Return true when function body of DECL still needs to be kept around
2155 for later re-use. */
2156bool
cc91b414 2157cgraph_preserve_function_body_p (struct cgraph_node *node)
b0cdf642 2158{
8d8c4c8d 2159 gcc_assert (cgraph_global_info_ready);
c70f46b0 2160 gcc_assert (!node->alias && !node->thunk.thunk_p);
cc91b414 2161
b0cdf642 2162 /* Look if there is any clone around. */
ccf4ab6b 2163 if (node->clones)
2164 return true;
b0cdf642 2165 return false;
2166}
2167
77fce4cd 2168static void
2169ipa_passes (void)
2170{
87d4aa85 2171 set_cfun (NULL);
4b14adf9 2172 current_function_decl = NULL;
75a70cf9 2173 gimple_register_cfg_hooks ();
77fce4cd 2174 bitmap_obstack_initialize (NULL);
59dd4830 2175
c9036234 2176 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
2177
59dd4830 2178 if (!in_lto_p)
7b2e8956 2179 {
2180 execute_ipa_pass_list (all_small_ipa_passes);
2181 if (seen_error ())
2182 return;
2183 }
9ed5b1f5 2184
941125aa 2185 /* We never run removal of unreachable nodes after early passes. This is
2186 because TODO is run before the subpasses. It is important to remove
2187 the unreachable functions to save works at IPA level and to get LTO
2188 symbol tables right. */
2189 cgraph_remove_unreachable_nodes (true, cgraph_dump_file);
2190
7bfefa9d 2191 /* If pass_all_early_optimizations was not scheduled, the state of
2192 the cgraph will not be properly updated. Update it now. */
2193 if (cgraph_state < CGRAPH_STATE_IPA_SSA)
2194 cgraph_state = CGRAPH_STATE_IPA_SSA;
9ed5b1f5 2195
7bfefa9d 2196 if (!in_lto_p)
2197 {
2198 /* Generate coverage variables and constructors. */
2199 coverage_finish ();
2200
2201 /* Process new functions added. */
2202 set_cfun (NULL);
2203 current_function_decl = NULL;
2204 cgraph_process_new_functions ();
7bfefa9d 2205
c9036234 2206 execute_ipa_summary_passes
2207 ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
8867b500 2208 }
23433d72 2209
2210 /* Some targets need to handle LTO assembler output specially. */
2211 if (flag_generate_lto)
2212 targetm.asm_out.lto_start ();
2213
7bfefa9d 2214 execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
2215
2216 if (!in_lto_p)
2217 ipa_write_summaries ();
2218
23433d72 2219 if (flag_generate_lto)
2220 targetm.asm_out.lto_end ();
2221
b33542ab 2222 if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
8867b500 2223 execute_ipa_pass_list (all_regular_ipa_passes);
c9036234 2224 invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
9ed5b1f5 2225
77fce4cd 2226 bitmap_obstack_release (NULL);
2227}
2228
badeded8 2229
2230/* Return string alias is alias of. */
2231
2232static tree
2233get_alias_symbol (tree decl)
2234{
2235 tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
2236 return get_identifier (TREE_STRING_POINTER
2237 (TREE_VALUE (TREE_VALUE (alias))));
2238}
2239
2240
5e712541 2241/* Weakrefs may be associated to external decls and thus not output
2242 at expansion time. Emit all neccesary aliases. */
2243
5139ff04 2244static void
5e712541 2245output_weakrefs (void)
2246{
2247 struct cgraph_node *node;
2248 struct varpool_node *vnode;
2249 for (node = cgraph_nodes; node; node = node->next)
7d0d0ce1 2250 if (node->alias && DECL_EXTERNAL (node->symbol.decl)
2251 && !TREE_ASM_WRITTEN (node->symbol.decl)
2252 && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
2253 assemble_alias (node->symbol.decl,
badeded8 2254 node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
7d0d0ce1 2255 : get_alias_symbol (node->symbol.decl));
5e712541 2256 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
7d0d0ce1 2257 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)
2258 && !TREE_ASM_WRITTEN (vnode->symbol.decl)
2259 && lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
2260 assemble_alias (vnode->symbol.decl,
badeded8 2261 vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
7d0d0ce1 2262 : get_alias_symbol (vnode->symbol.decl));
5e712541 2263}
2264
34e5cced 2265
34e5cced 2266
121f3051 2267void
2268init_cgraph (void)
2269{
01ec0a6c 2270 if (!cgraph_dump_file)
2271 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
121f3051 2272}
b5d36404 2273
a0c938f0 2274/* The edges representing the callers of the NEW_VERSION node were
b5d36404 2275 fixed by cgraph_function_versioning (), now the call_expr in their
2276 respective tree code should be updated to call the NEW_VERSION. */
2277
2278static void
2279update_call_expr (struct cgraph_node *new_version)
2280{
2281 struct cgraph_edge *e;
2282
2283 gcc_assert (new_version);
75a70cf9 2284
2285 /* Update the call expr on the edges to call the new version. */
b5d36404 2286 for (e = new_version->callers; e; e = e->next_caller)
e03a95e7 2287 {
7d0d0ce1 2288 struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
2289 gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl);
e38def9c 2290 maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
e03a95e7 2291 }
b5d36404 2292}
2293
2294
2295/* Create a new cgraph node which is the new version of
2296 OLD_VERSION node. REDIRECT_CALLERS holds the callers
2297 edges which should be redirected to point to
2298 NEW_VERSION. ALL the callees edges of OLD_VERSION
2299 are cloned to the new version node. Return the new
b06ab5fa 2300 version node.
2301
2302 If non-NULL BLOCK_TO_COPY determine what basic blocks
2303 was copied to prevent duplications of calls that are dead
2304 in the clone. */
b5d36404 2305
4c0315d0 2306struct cgraph_node *
b5d36404 2307cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
4460a647 2308 tree new_decl,
b06ab5fa 2309 VEC(cgraph_edge_p,heap) *redirect_callers,
2310 bitmap bbs_to_copy)
2311 {
b5d36404 2312 struct cgraph_node *new_version;
32936803 2313 struct cgraph_edge *e;
b5d36404 2314 unsigned i;
2315
2316 gcc_assert (old_version);
a0c938f0 2317
5a90471f 2318 new_version = cgraph_create_node (new_decl);
b5d36404 2319
4c0315d0 2320 new_version->analyzed = old_version->analyzed;
b5d36404 2321 new_version->local = old_version->local;
7d0d0ce1 2322 new_version->symbol.externally_visible = false;
a70a5e2c 2323 new_version->local.local = true;
b5d36404 2324 new_version->global = old_version->global;
a93f1c3b 2325 new_version->rtl = old_version->rtl;
b5d36404 2326 new_version->reachable = true;
2327 new_version->count = old_version->count;
2328
a70a5e2c 2329 for (e = old_version->callees; e; e=e->next_callee)
b06ab5fa 2330 if (!bbs_to_copy
2331 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
2332 cgraph_clone_edge (e, new_version, e->call_stmt,
2333 e->lto_stmt_uid, REG_BR_PROB_BASE,
2334 CGRAPH_FREQ_BASE,
0835ad03 2335 true);
a70a5e2c 2336 for (e = old_version->indirect_calls; e; e=e->next_callee)
b06ab5fa 2337 if (!bbs_to_copy
2338 || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
2339 cgraph_clone_edge (e, new_version, e->call_stmt,
2340 e->lto_stmt_uid, REG_BR_PROB_BASE,
2341 CGRAPH_FREQ_BASE,
0835ad03 2342 true);
48148244 2343 FOR_EACH_VEC_ELT (cgraph_edge_p, redirect_callers, i, e)
4460a647 2344 {
2345 /* Redirect calls to the old version node to point to its new
2346 version. */
2347 cgraph_redirect_edge_callee (e, new_version);
2348 }
b5d36404 2349
ad687a96 2350 cgraph_call_node_duplication_hooks (old_version, new_version);
2351
b5d36404 2352 return new_version;
2353 }
2354
2355 /* Perform function versioning.
a0c938f0 2356 Function versioning includes copying of the tree and
b5d36404 2357 a callgraph update (creating a new cgraph node and updating
2358 its callees and callers).
2359
2360 REDIRECT_CALLERS varray includes the edges to be redirected
2361 to the new version.
2362
2363 TREE_MAP is a mapping of tree nodes we want to replace with
2364 new ones (according to results of prior analysis).
2365 OLD_VERSION_NODE is the node that is versioned.
7a3ec978 2366
b06ab5fa 2367 If non-NULL ARGS_TO_SKIP determine function parameters to remove
2368 from new version.
7a3ec978 2369 If SKIP_RETURN is true, the new version will return void.
b06ab5fa 2370 If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
7a3ec978 2371 If non_NULL NEW_ENTRY determine new entry BB of the clone.
2372
2373 Return the new version's cgraph node. */
b5d36404 2374
2375struct cgraph_node *
2376cgraph_function_versioning (struct cgraph_node *old_version_node,
4460a647 2377 VEC(cgraph_edge_p,heap) *redirect_callers,
ccf4ab6b 2378 VEC (ipa_replace_map_p,gc)* tree_map,
a70a5e2c 2379 bitmap args_to_skip,
7a3ec978 2380 bool skip_return,
b06ab5fa 2381 bitmap bbs_to_copy,
2382 basic_block new_entry_block,
a70a5e2c 2383 const char *clone_name)
b5d36404 2384{
7d0d0ce1 2385 tree old_decl = old_version_node->symbol.decl;
b5d36404 2386 struct cgraph_node *new_version_node = NULL;
2387 tree new_decl;
2388
2389 if (!tree_versionable_function_p (old_decl))
2390 return NULL;
2391
3c97c75d 2392 gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
2393
7a3ec978 2394 /* Make a new FUNCTION_DECL tree node for the new version. */
2395 if (!args_to_skip && !skip_return)
5afe38fe 2396 new_decl = copy_node (old_decl);
2397 else
7a3ec978 2398 new_decl
2399 = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
b5d36404 2400
df0b8dfb 2401 /* Generate a new name for the new version. */
2402 DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
2403 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
2404 SET_DECL_RTL (new_decl, NULL);
2405
e54aa8a4 2406 /* When the old decl was a con-/destructor make sure the clone isn't. */
2407 DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
2408 DECL_STATIC_DESTRUCTOR(new_decl) = 0;
2409
b5d36404 2410 /* Create the new version's call-graph node.
2411 and update the edges of the new node. */
2412 new_version_node =
2413 cgraph_copy_node_for_versioning (old_version_node, new_decl,
b06ab5fa 2414 redirect_callers, bbs_to_copy);
b5d36404 2415
2416 /* Copy the OLD_VERSION_NODE function tree to the new version. */
b06ab5fa 2417 tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
7a3ec978 2418 skip_return, bbs_to_copy, new_entry_block);
b5d36404 2419
a0c938f0 2420 /* Update the new version's properties.
e03a95e7 2421 Make The new version visible only within this translation unit. Make sure
2422 that is not weak also.
a0c938f0 2423 ??? We cannot use COMDAT linkage because there is no
b5d36404 2424 ABI support for this. */
7d0d0ce1 2425 cgraph_make_decl_local (new_version_node->symbol.decl);
2426 DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
2427 new_version_node->symbol.externally_visible = 0;
b5d36404 2428 new_version_node->local.local = 1;
2429 new_version_node->lowered = true;
f014e39d 2430
e03a95e7 2431 /* Update the call_expr on the edges to call the new version node. */
2432 update_call_expr (new_version_node);
48e1416a 2433
50828ed8 2434 cgraph_call_function_insertion_hooks (new_version_node);
b5d36404 2435 return new_version_node;
2436}
469679ab 2437
ccf4ab6b 2438/* Given virtual clone, turn it into actual clone. */
2439static void
2440cgraph_materialize_clone (struct cgraph_node *node)
2441{
2442 bitmap_obstack_initialize (NULL);
7d0d0ce1 2443 node->former_clone_of = node->clone_of->symbol.decl;
e748b31d 2444 if (node->clone_of->former_clone_of)
2445 node->former_clone_of = node->clone_of->former_clone_of;
ccf4ab6b 2446 /* Copy the OLD_VERSION_NODE function tree to the new version. */
7d0d0ce1 2447 tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl,
ccf4ab6b 2448 node->clone.tree_map, true,
7a3ec978 2449 node->clone.args_to_skip, false,
2450 NULL, NULL);
e20422ea 2451 if (cgraph_dump_file)
2452 {
7d0d0ce1 2453 dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags);
2454 dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags);
e20422ea 2455 }
ccf4ab6b 2456
2457 /* Function is no longer clone. */
2458 if (node->next_sibling_clone)
2459 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
2460 if (node->prev_sibling_clone)
2461 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
2462 else
2463 node->clone_of->clones = node->next_sibling_clone;
2464 node->next_sibling_clone = NULL;
2465 node->prev_sibling_clone = NULL;
6d1cc52c 2466 if (!node->clone_of->analyzed && !node->clone_of->clones)
7d6a1ec8 2467 {
2468 cgraph_release_function_body (node->clone_of);
2469 cgraph_node_remove_callees (node->clone_of);
7d0d0ce1 2470 ipa_remove_all_references (&node->clone_of->symbol.ref_list);
7d6a1ec8 2471 }
ccf4ab6b 2472 node->clone_of = NULL;
2473 bitmap_obstack_release (NULL);
2474}
2475
c596d830 2476/* If necessary, change the function declaration in the call statement
2477 associated with E so that it corresponds to the edge callee. */
2478
2479gimple
2480cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
2481{
2482 tree decl = gimple_call_fndecl (e->call_stmt);
2483 gimple new_stmt;
3fd0ca33 2484 gimple_stmt_iterator gsi;
1f449108 2485#ifdef ENABLE_CHECKING
2486 struct cgraph_node *node;
2487#endif
c596d830 2488
1caef38b 2489 if (e->indirect_unknown_callee
7d0d0ce1 2490 || decl == e->callee->symbol.decl)
c596d830 2491 return e->call_stmt;
2492
1f449108 2493#ifdef ENABLE_CHECKING
1caef38b 2494 if (decl)
2495 {
2496 node = cgraph_get_node (decl);
2497 gcc_assert (!node || !node->clone.combined_args_to_skip);
2498 }
1f449108 2499#endif
e748b31d 2500
c596d830 2501 if (cgraph_dump_file)
2502 {
2503 fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
2504 cgraph_node_name (e->caller), e->caller->uid,
2505 cgraph_node_name (e->callee), e->callee->uid);
2506 print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
e748b31d 2507 if (e->callee->clone.combined_args_to_skip)
91aba934 2508 {
2509 fprintf (cgraph_dump_file, " combined args to skip: ");
2510 dump_bitmap (cgraph_dump_file,
2511 e->callee->clone.combined_args_to_skip);
e748b31d 2512 }
c596d830 2513 }
2514
2515 if (e->callee->clone.combined_args_to_skip)
91aba934 2516 {
092cd838 2517 int lp_nr;
91aba934 2518
2519 new_stmt
2520 = gimple_call_copy_skip_args (e->call_stmt,
2521 e->callee->clone.combined_args_to_skip);
7d0d0ce1 2522 gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
91aba934 2523
2524 if (gimple_vdef (new_stmt)
2525 && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
2526 SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
2527
d4e80e2b 2528 gsi = gsi_for_stmt (e->call_stmt);
9126b675 2529 gsi_replace (&gsi, new_stmt, false);
092cd838 2530 /* We need to defer cleaning EH info on the new statement to
2531 fixup-cfg. We may not have dominator information at this point
2532 and thus would end up with unreachable blocks and have no way
2533 to communicate that we need to run CFG cleanup then. */
2534 lp_nr = lookup_stmt_eh_lp (e->call_stmt);
2535 if (lp_nr != 0)
2536 {
2537 remove_stmt_from_eh_lp (e->call_stmt);
2538 add_stmt_to_eh_lp (new_stmt, lp_nr);
2539 }
91aba934 2540 }
c596d830 2541 else
75c7f5a5 2542 {
2543 new_stmt = e->call_stmt;
7d0d0ce1 2544 gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
75c7f5a5 2545 update_stmt (new_stmt);
2546 }
c596d830 2547
c596d830 2548 cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt);
2549
2550 if (cgraph_dump_file)
2551 {
2552 fprintf (cgraph_dump_file, " updated to:");
2553 print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
2554 }
2555 return new_stmt;
2556}
2557
ccf4ab6b 2558/* Once all functions from compilation unit are in memory, produce all clones
c596d830 2559 and update all calls. We might also do this on demand if we don't want to
2560 bring all functions to memory prior compilation, but current WHOPR
2561 implementation does that and it is is bit easier to keep everything right in
2562 this order. */
d2bb3f9d 2563static void
ccf4ab6b 2564cgraph_materialize_all_clones (void)
2565{
2566 struct cgraph_node *node;
2567 bool stabilized = false;
2568
2569 if (cgraph_dump_file)
2570 fprintf (cgraph_dump_file, "Materializing clones\n");
2571#ifdef ENABLE_CHECKING
2572 verify_cgraph ();
2573#endif
2574
2575 /* We can also do topological order, but number of iterations should be
2576 bounded by number of IPA passes since single IPA pass is probably not
2577 going to create clones of clones it created itself. */
2578 while (!stabilized)
2579 {
2580 stabilized = true;
2581 for (node = cgraph_nodes; node; node = node->next)
2582 {
7d0d0ce1 2583 if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
2584 && !gimple_has_body_p (node->symbol.decl))
ccf4ab6b 2585 {
7d0d0ce1 2586 if (gimple_has_body_p (node->clone_of->symbol.decl))
ccf4ab6b 2587 {
2588 if (cgraph_dump_file)
e20422ea 2589 {
0a10fd82 2590 fprintf (cgraph_dump_file, "cloning %s to %s\n",
e20422ea 2591 cgraph_node_name (node->clone_of),
2592 cgraph_node_name (node));
2593 if (node->clone.tree_map)
2594 {
2595 unsigned int i;
2596 fprintf (cgraph_dump_file, " replace map: ");
2597 for (i = 0; i < VEC_length (ipa_replace_map_p,
2598 node->clone.tree_map);
2599 i++)
2600 {
2601 struct ipa_replace_map *replace_info;
2602 replace_info = VEC_index (ipa_replace_map_p,
2603 node->clone.tree_map,
2604 i);
2605 print_generic_expr (cgraph_dump_file, replace_info->old_tree, 0);
2606 fprintf (cgraph_dump_file, " -> ");
2607 print_generic_expr (cgraph_dump_file, replace_info->new_tree, 0);
2608 fprintf (cgraph_dump_file, "%s%s;",
2609 replace_info->replace_p ? "(replace)":"",
2610 replace_info->ref_p ? "(ref)":"");
2611 }
2612 fprintf (cgraph_dump_file, "\n");
2613 }
2614 if (node->clone.args_to_skip)
2615 {
2616 fprintf (cgraph_dump_file, " args_to_skip: ");
2617 dump_bitmap (cgraph_dump_file, node->clone.args_to_skip);
2618 }
2619 if (node->clone.args_to_skip)
2620 {
2621 fprintf (cgraph_dump_file, " combined_args_to_skip:");
2622 dump_bitmap (cgraph_dump_file, node->clone.combined_args_to_skip);
2623 }
2624 }
ccf4ab6b 2625 cgraph_materialize_clone (node);
a510bd8d 2626 stabilized = false;
ccf4ab6b 2627 }
ccf4ab6b 2628 }
2629 }
2630 }
ee3f5fc0 2631 for (node = cgraph_nodes; node; node = node->next)
2632 if (!node->analyzed && node->callees)
2633 cgraph_node_remove_callees (node);
c596d830 2634 if (cgraph_dump_file)
2635 fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
947781ac 2636#ifdef ENABLE_CHECKING
2637 verify_cgraph ();
2638#endif
ccf4ab6b 2639 cgraph_remove_unreachable_nodes (false, cgraph_dump_file);
2640}
2641
d2bb3f9d 2642
2643/* Perform simple optimizations based on callgraph. */
2644
2645void
2646cgraph_optimize (void)
2647{
2648 if (seen_error ())
2649 return;
2650
2651#ifdef ENABLE_CHECKING
2652 verify_cgraph ();
2653#endif
2654
2655 /* Frontend may output common variables after the unit has been finalized.
2656 It is safe to deal with them here as they are always zero initialized. */
2657 varpool_analyze_pending_decls ();
2658
2659 timevar_push (TV_CGRAPHOPT);
2660 if (pre_ipa_mem_report)
2661 {
2662 fprintf (stderr, "Memory consumption before IPA\n");
2663 dump_memory_report (false);
2664 }
2665 if (!quiet_flag)
2666 fprintf (stderr, "Performing interprocedural optimizations\n");
2667 cgraph_state = CGRAPH_STATE_IPA;
2668
2669 /* Don't run the IPA passes if there was any error or sorry messages. */
2670 if (!seen_error ())
2671 ipa_passes ();
2672
2673 /* Do nothing else if any IPA pass found errors or if we are just streaming LTO. */
2674 if (seen_error ()
2675 || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
2676 {
2677 timevar_pop (TV_CGRAPHOPT);
2678 return;
2679 }
2680
2681 /* This pass remove bodies of extern inline functions we never inlined.
2682 Do this later so other IPA passes see what is really going on. */
2683 cgraph_remove_unreachable_nodes (false, dump_file);
2684 cgraph_global_info_ready = true;
2685 if (cgraph_dump_file)
2686 {
2687 fprintf (cgraph_dump_file, "Optimized ");
2688 dump_cgraph (cgraph_dump_file);
2689 dump_varpool (cgraph_dump_file);
2690 }
2691 if (post_ipa_mem_report)
2692 {
2693 fprintf (stderr, "Memory consumption after IPA\n");
2694 dump_memory_report (false);
2695 }
2696 timevar_pop (TV_CGRAPHOPT);
2697
2698 /* Output everything. */
2699 (*debug_hooks->assembly_start) ();
2700 if (!quiet_flag)
2701 fprintf (stderr, "Assembling functions:\n");
2702#ifdef ENABLE_CHECKING
2703 verify_cgraph ();
2704#endif
2705
2706 cgraph_materialize_all_clones ();
2707 bitmap_obstack_initialize (NULL);
2708 execute_ipa_pass_list (all_late_ipa_passes);
2709 cgraph_remove_unreachable_nodes (true, dump_file);
2710#ifdef ENABLE_CHECKING
2711 verify_cgraph ();
2712#endif
2713 bitmap_obstack_release (NULL);
2714 cgraph_mark_functions_to_output ();
2715 output_weakrefs ();
2716
2717 cgraph_state = CGRAPH_STATE_EXPANSION;
2718 if (!flag_toplevel_reorder)
2719 cgraph_output_in_order ();
2720 else
2721 {
2722 cgraph_output_pending_asms ();
2723
2724 cgraph_expand_all_functions ();
2725 varpool_remove_unreferenced_decls ();
2726
2727 varpool_assemble_pending_decls ();
2728 }
2729
2730 cgraph_process_new_functions ();
2731 cgraph_state = CGRAPH_STATE_FINISHED;
2732
2733 if (cgraph_dump_file)
2734 {
2735 fprintf (cgraph_dump_file, "\nFinal ");
2736 dump_cgraph (cgraph_dump_file);
2737 dump_varpool (cgraph_dump_file);
2738 }
2739#ifdef ENABLE_CHECKING
2740 verify_cgraph ();
2741 /* Double check that all inline clones are gone and that all
2742 function bodies have been released from memory. */
2743 if (!seen_error ())
2744 {
2745 struct cgraph_node *node;
2746 bool error_found = false;
2747
2748 for (node = cgraph_nodes; node; node = node->next)
2749 if (node->analyzed
2750 && (node->global.inlined_to
7d0d0ce1 2751 || gimple_has_body_p (node->symbol.decl)))
d2bb3f9d 2752 {
2753 error_found = true;
2754 dump_cgraph_node (stderr, node);
2755 }
2756 if (error_found)
2757 internal_error ("nodes with unreleased memory found");
2758 }
2759#endif
2760}
2761
2762
2763/* Analyze the whole compilation unit once it is parsed completely. */
2764
2765void
2766cgraph_finalize_compilation_unit (void)
2767{
2768 timevar_push (TV_CGRAPH);
2769
2770 /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */
2771 if (flag_lto)
2772 lto_streamer_hooks_init ();
2773
2774 /* If we're here there's no current function anymore. Some frontends
2775 are lazy in clearing these. */
2776 current_function_decl = NULL;
2777 set_cfun (NULL);
2778
2779 /* Do not skip analyzing the functions if there were errors, we
2780 miss diagnostics for following functions otherwise. */
2781
2782 /* Emit size functions we didn't inline. */
2783 finalize_size_functions ();
2784
2785 /* Mark alias targets necessary and emit diagnostics. */
2786 finish_aliases_1 ();
2787 handle_alias_pairs ();
2788
2789 if (!quiet_flag)
2790 {
2791 fprintf (stderr, "\nAnalyzing compilation unit\n");
2792 fflush (stderr);
2793 }
2794
2795 if (flag_dump_passes)
2796 dump_passes ();
2797
2798 /* Gimplify and lower all functions, compute reachability and
2799 remove unreachable nodes. */
2800 cgraph_analyze_functions ();
2801
2802 /* Mark alias targets necessary and emit diagnostics. */
2803 finish_aliases_1 ();
2804 handle_alias_pairs ();
2805
2806 /* Gimplify and lower thunks. */
2807 cgraph_analyze_functions ();
2808
2809 /* Finally drive the pass manager. */
2810 cgraph_optimize ();
2811
2812 timevar_pop (TV_CGRAPH);
2813}
2814
2815
a861fe52 2816#include "gt-cgraphunit.h"