]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraphunit.c
re PR target/21888 (bootstrap failure with linker relaxation enabled)
[thirdparty/gcc.git] / gcc / cgraphunit.c
CommitLineData
b58b1157 1/* Callgraph based intraprocedural optimizations.
a4de48bc 2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
1c4a429a
JH
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
21
18c6ada9
JH
22/* This module implements main driver of compilation process as well as
23 few basic intraprocedural optimizers.
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
35 (There is one exception needed for implementing GCC extern inline function.)
36
37 - cgraph_varpool_finalize_variable
38
1ae58c30 39 This function has same behavior as the above but is used for static
18c6ada9
JH
40 variables.
41
42 - cgraph_finalize_compilation_unit
43
44 This function is called once compilation unit is finalized and it will
45 no longer change.
46
47 In the unit-at-a-time the call-graph construction and local function
48 analysis takes place here. Bodies of unreachable functions are released
49 to conserve memory usage.
50
51 ??? The compilation unit in this point of view should be compilation
52 unit as defined by the language - for instance C frontend allows multiple
53 compilation units to be parsed at once and it should call function each
54 time parsing is done so we save memory.
55
56 - cgraph_optimize
57
58 In this unit-at-a-time compilation the intra procedural analysis takes
59 place here. In particular the static functions whose address is never
60 taken are marked as local. Backend can then use this information to
61 modify calling conventions, do better inlining or similar optimizations.
62
63 - cgraph_assemble_pending_functions
64 - cgraph_varpool_assemble_pending_variables
65
66 In non-unit-at-a-time mode these functions can be used to force compilation
67 of functions or variables that are known to be needed at given stage
68 of compilation
69
70 - cgraph_mark_needed_node
71 - cgraph_varpool_mark_needed_node
72
73 When function or variable is referenced by some hidden way (for instance
74 via assembly code and marked by attribute "used"), the call-graph data structure
75 must be updated accordingly by this function.
76
77 - analyze_expr callback
78
79 This function is responsible for lowering tree nodes not understood by
80 generic code into understandable ones or alternatively marking
81 callgraph and varpool nodes referenced by the as needed.
82
83 ??? On the tree-ssa genericizing should take place here and we will avoid
84 need for these hooks (replacing them by genericizing hook)
85
86 - expand_function callback
87
88 This function is used to expand function and pass it into RTL back-end.
89 Front-end should not make any assumptions about when this function can be
90 called. In particular cgraph_assemble_pending_functions,
91 cgraph_varpool_assemble_pending_variables, cgraph_finalize_function,
92 cgraph_varpool_finalize_function, cgraph_optimize can cause arbitrarily
93 previously finalized functions to be expanded.
94
95 We implement two compilation modes.
96
97 - unit-at-a-time: In this mode analyzing of all functions is deferred
98 to cgraph_finalize_compilation_unit and expansion into cgraph_optimize.
99
100 In cgraph_finalize_compilation_unit the reachable functions are
101 analyzed. During analysis the call-graph edges from reachable
102 functions are constructed and their destinations are marked as
103 reachable. References to functions and variables are discovered too
104 and variables found to be needed output to the assembly file. Via
105 mark_referenced call in assemble_variable functions referenced by
106 static variables are noticed too.
107
e1990f69 108 The intra-procedural information is produced and its existence
18c6ada9
JH
109 indicated by global_info_ready. Once this flag is set it is impossible
110 to change function from !reachable to reachable and thus
111 assemble_variable no longer call mark_referenced.
112
113 Finally the call-graph is topologically sorted and all reachable functions
114 that has not been completely inlined or are not external are output.
115
116 ??? It is possible that reference to function or variable is optimized
117 out. We can not deal with this nicely because topological order is not
118 suitable for it. For tree-ssa we may consider another pass doing
119 optimization and re-discovering reachable functions.
120
121 ??? Reorganize code so variables are output very last and only if they
122 really has been referenced by produced code, so we catch more cases
123 where reference has been optimized out.
124
125 - non-unit-at-a-time
126
127 All functions are variables are output as early as possible to conserve
128 memory consumption. This may or may not result in less memory used but
129 it is still needed for some legacy code that rely on particular ordering
130 of things output from the compiler.
131
132 Varpool data structures are not used and variables are output directly.
133
134 Functions are output early using call of
135 cgraph_assemble_pending_function from cgraph_finalize_function. The
136 decision on whether function is needed is made more conservative so
137 uninlininable static functions are needed too. During the call-graph
138 construction the edge destinations are not marked as reachable and it
e42922b1 139 is completely relied upn assemble_variable to mark them. */
9b3e897d 140
6674a6ce 141
1c4a429a
JH
142#include "config.h"
143#include "system.h"
144#include "coretypes.h"
145#include "tm.h"
146#include "tree.h"
c9b9aa64 147#include "rtl.h"
6674a6ce 148#include "tree-flow.h"
1c4a429a
JH
149#include "tree-inline.h"
150#include "langhooks.h"
0c58f841 151#include "pointer-set.h"
1c4a429a
JH
152#include "toplev.h"
153#include "flags.h"
154#include "ggc.h"
155#include "debug.h"
156#include "target.h"
157#include "cgraph.h"
dafc5b82 158#include "diagnostic.h"
a194aa56 159#include "timevar.h"
b58b1157
JH
160#include "params.h"
161#include "fibheap.h"
162#include "c-common.h"
dc0bfe6a 163#include "intl.h"
902edd36 164#include "function.h"
6674a6ce 165#include "tree-gimple.h"
b4861090 166#include "tree-pass.h"
cd9c7bd2 167#include "output.h"
b58b1157 168
a20af5b8 169static void cgraph_expand_all_functions (void);
db0e878d
AJ
170static void cgraph_mark_functions_to_output (void);
171static void cgraph_expand_function (struct cgraph_node *);
e0704a46 172static tree record_reference (tree *, int *, void *);
4a46cbfb 173static void cgraph_analyze_function (struct cgraph_node *node);
b58b1157 174
e0704a46 175/* Records tree nodes seen in record_reference. Simply using
7dff32e6
JS
176 walk_tree_without_duplicates doesn't guarantee each node is visited
177 once because it gets a new htab upon each recursive call from
e0704a46 178 record_reference itself. */
0c58f841 179static struct pointer_set_t *visited_nodes;
7dff32e6 180
9b3e897d
PB
181static FILE *cgraph_dump_file;
182
8dafba3c
RH
183/* Determine if function DECL is needed. That is, visible to something
184 either outside this translation unit, something magic in the system
185 configury, or (if not doing unit-at-a-time) to something we havn't
186 seen yet. */
187
188static bool
189decide_is_function_needed (struct cgraph_node *node, tree decl)
190{
8f235343 191 tree origin;
6de9cd9a 192
e7d6beb0
JH
193 /* If the user told us it is used, then it must be so. */
194 if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
195 return true;
196
197 /* ??? If the assembler name is set by hand, it is possible to assemble
198 the name later after finalizing the function and the fact is noticed
199 in assemble_name then. This is arguably a bug. */
200 if (DECL_ASSEMBLER_NAME_SET_P (decl)
201 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
202 return true;
203
8dafba3c
RH
204 /* If we decided it was needed before, but at the time we didn't have
205 the body of the function available, then it's still needed. We have
206 to go back and re-check its dependencies now. */
207 if (node->needed)
208 return true;
209
210 /* Externally visible functions must be output. The exception is
211 COMDAT functions that must be output only when they are needed. */
212 if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
213 return true;
214
215 /* Constructors and destructors are reachable from the runtime by
216 some mechanism. */
217 if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
218 return true;
219
8dafba3c
RH
220 if (flag_unit_at_a_time)
221 return false;
222
223 /* If not doing unit at a time, then we'll only defer this function
224 if its marked for inlining. Otherwise we want to emit it now. */
225
226 /* "extern inline" functions are never output locally. */
227 if (DECL_EXTERNAL (decl))
228 return false;
6de9cd9a
DN
229 /* Nested functions of extern inline function shall not be emit unless
230 we inlined the origin. */
8f235343
JH
231 for (origin = decl_function_context (decl); origin;
232 origin = decl_function_context (origin))
233 if (DECL_EXTERNAL (origin))
6de9cd9a 234 return false;
2067c116 235 /* We want to emit COMDAT functions only when absolutely necessary. */
d853a20e 236 if (DECL_COMDAT (decl))
8dafba3c
RH
237 return false;
238 if (!DECL_INLINE (decl)
239 || (!node->local.disregard_inline_limits
240 /* When declared inline, defer even the uninlinable functions.
7d82fe7c 241 This allows them to be eliminated when unused. */
8dafba3c 242 && !DECL_DECLARED_INLINE_P (decl)
d4d1ebc1 243 && (!node->local.inlinable || !cgraph_default_inline_p (node))))
8dafba3c
RH
244 return true;
245
246 return false;
247}
248
aabcd309
KH
249/* Walk the decls we marked as necessary and see if they reference new
250 variables or functions and add them into the worklists. */
cd9c7bd2
JH
251static bool
252cgraph_varpool_analyze_pending_decls (void)
253{
254 bool changed = false;
255 timevar_push (TV_CGRAPH);
256
257 while (cgraph_varpool_first_unanalyzed_node)
258 {
259 tree decl = cgraph_varpool_first_unanalyzed_node->decl;
260
261 cgraph_varpool_first_unanalyzed_node->analyzed = true;
262
263 cgraph_varpool_first_unanalyzed_node = cgraph_varpool_first_unanalyzed_node->next_needed;
264
265 if (DECL_INITIAL (decl))
e0704a46
JH
266 {
267 visited_nodes = pointer_set_create ();
268 walk_tree (&DECL_INITIAL (decl), record_reference, NULL, visited_nodes);
269 pointer_set_destroy (visited_nodes);
270 visited_nodes = NULL;
271 }
cd9c7bd2
JH
272 changed = true;
273 }
274 timevar_pop (TV_CGRAPH);
275 return changed;
276}
277
278/* Optimization of function bodies might've rendered some variables as
aabcd309 279 unnecessary so we want to avoid these from being compiled.
cd9c7bd2 280
0fa2e4df 281 This is done by pruning the queue and keeping only the variables that
aabcd309 282 really appear needed (ie they are either externally visible or referenced
cd9c7bd2
JH
283 by compiled function). Re-doing the reachability analysis on variables
284 brings back the remaining variables referenced by these. */
285static void
286cgraph_varpool_remove_unreferenced_decls (void)
287{
288 struct cgraph_varpool_node *next, *node = cgraph_varpool_nodes_queue;
289
290 cgraph_varpool_reset_queue ();
291
292 if (errorcount || sorrycount)
293 return;
294
295 while (node)
296 {
297 tree decl = node->decl;
298 next = node->next_needed;
299 node->needed = 0;
300
301 if (node->finalized
302 && ((DECL_ASSEMBLER_NAME_SET_P (decl)
303 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
304 || node->force_output
305 || decide_is_variable_needed (node, decl)))
306 cgraph_varpool_mark_needed_node (node);
307
308 node = next;
309 }
310 cgraph_varpool_analyze_pending_decls ();
311}
6674a6ce 312
6674a6ce 313
d853a20e
JH
314/* When not doing unit-at-a-time, output all functions enqueued.
315 Return true when such a functions were found. */
f6d1b84a
RH
316
317bool
d853a20e
JH
318cgraph_assemble_pending_functions (void)
319{
320 bool output = false;
321
322 if (flag_unit_at_a_time)
323 return false;
324
325 while (cgraph_nodes_queue)
326 {
327 struct cgraph_node *n = cgraph_nodes_queue;
328
329 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
18c6ada9 330 n->next_needed = NULL;
12527dce
RH
331 if (!n->global.inlined_to
332 && !n->alias
333 && !DECL_EXTERNAL (n->decl))
f6d1b84a
RH
334 {
335 cgraph_expand_function (n);
336 output = true;
337 }
d853a20e 338 }
f6d1b84a 339
d853a20e
JH
340 return output;
341}
342
6b00c969
RH
343/* DECL has been parsed. Take it, queue it, compile it at the whim of the
344 logic in effect. If NESTED is true, then our caller cannot stand to have
345 the garbage collector run at the moment. We would need to either create
346 a new GC context, or just not compile right now. */
1c4a429a
JH
347
348void
6b00c969 349cgraph_finalize_function (tree decl, bool nested)
1c4a429a
JH
350{
351 struct cgraph_node *node = cgraph_node (decl);
352
d853a20e
JH
353 if (node->local.finalized)
354 {
355 /* As an GCC extension we allow redefinition of the function. The
6b00c969
RH
356 semantics when both copies of bodies differ is not well defined.
357 We replace the old body with new body so in unit at a time mode
358 we always use new body, while in normal mode we may end up with
359 old body inlined into some functions and new body expanded and
360 inlined in others.
d853a20e 361
6b00c969 362 ??? It may make more sense to use one body for inlining and other
2067c116 363 body for expanding the function but this is difficult to do. */
6b00c969 364
f6d1b84a
RH
365 /* If node->output is set, then this is a unit-at-a-time compilation
366 and we have already begun whole-unit analysis. This is *not*
367 testing for whether we've already emitted the function. That
368 case can be sort-of legitimately seen with real function
369 redefinition errors. I would argue that the front end should
370 never present us with such a case, but don't enforce that for now. */
341c100f 371 gcc_assert (!node->output);
6b00c969 372
1ae58c30 373 /* Reset our data structures so we can analyze the function again. */
cd4dea62
JH
374 memset (&node->local, 0, sizeof (node->local));
375 memset (&node->global, 0, sizeof (node->global));
376 memset (&node->rtl, 0, sizeof (node->rtl));
25c84396 377 node->analyzed = false;
95c755e9 378 node->local.redefined_extern_inline = true;
58203599
JJ
379
380 if (!flag_unit_at_a_time)
381 {
382 struct cgraph_node *n;
383
384 for (n = cgraph_nodes; n; n = n->next)
385 if (n->global.inlined_to == node)
386 cgraph_remove_node (n);
387 }
388
2563c224 389 cgraph_node_remove_callees (node);
6b00c969 390
cd4dea62
JH
391 /* We may need to re-queue the node for assembling in case
392 we already proceeded it and ignored as not needed. */
393 if (node->reachable && !flag_unit_at_a_time)
d853a20e 394 {
cd4dea62
JH
395 struct cgraph_node *n;
396
397 for (n = cgraph_nodes_queue; n; n = n->next_needed)
398 if (n == node)
399 break;
400 if (!n)
401 node->reachable = 0;
d853a20e 402 }
d853a20e 403 }
6b00c969 404
d853a20e 405 notice_global_symbol (decl);
1c4a429a 406 node->decl = decl;
f6981e16 407 node->local.finalized = true;
e21aff8a 408 node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
8f235343
JH
409 if (node->nested)
410 lower_nested_functions (decl);
411 gcc_assert (!node->nested);
1c4a429a 412
8dafba3c
RH
413 /* If not unit at a time, then we need to create the call graph
414 now, so that called functions can be queued and emitted now. */
4a46cbfb 415 if (!flag_unit_at_a_time)
d4d1ebc1
JH
416 {
417 cgraph_analyze_function (node);
418 cgraph_decide_inlining_incrementally (node);
419 }
4a46cbfb 420
8dafba3c
RH
421 if (decide_is_function_needed (node, decl))
422 cgraph_mark_needed_node (node);
423
ff5c4582 424 /* Since we reclaim unreachable nodes at the end of every language
e7d6beb0
JH
425 level unit, we need to be conservative about possible entry points
426 there. */
427 if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
428 cgraph_mark_reachable_node (node);
429
6b00c969
RH
430 /* If not unit at a time, go ahead and emit everything we've found
431 to be reachable at this time. */
432 if (!nested)
d34cb6a1
JH
433 {
434 if (!cgraph_assemble_pending_functions ())
435 ggc_collect ();
436 }
1668aabc 437
8dafba3c 438 /* If we've not yet emitted decl, tell the debug info about it. */
6b00c969 439 if (!TREE_ASM_WRITTEN (decl))
8dafba3c 440 (*debug_hooks->deferred_inline_function) (decl);
d173e685 441
902edd36
JH
442 /* Possibly warn about unused parameters. */
443 if (warn_unused_parameter)
444 do_warn_unused_parameter (decl);
1c4a429a
JH
445}
446
e21aff8a
SB
447void
448cgraph_lower_function (struct cgraph_node *node)
449{
450 if (node->lowered)
451 return;
452 tree_lowering_passes (node->decl);
453 node->lowered = true;
454}
455
1c4a429a
JH
456/* Walk tree and record all calls. Called via walk_tree. */
457static tree
e0704a46 458record_reference (tree *tp, int *walk_subtrees, void *data)
1c4a429a 459{
25c84396
RH
460 tree t = *tp;
461
462 switch (TREE_CODE (t))
1c4a429a 463 {
25c84396
RH
464 case VAR_DECL:
465 /* ??? Really, we should mark this decl as *potentially* referenced
466 by this function and re-examine whether the decl is actually used
467 after rtl has been generated. */
cd9c7bd2 468 if (TREE_STATIC (t) || DECL_EXTERNAL (t))
4684cd27
MM
469 {
470 cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
471 if (lang_hooks.callgraph.analyze_expr)
472 return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees,
473 data);
474 }
25c84396
RH
475 break;
476
c7bcbc2c 477 case FDESC_EXPR:
25c84396
RH
478 case ADDR_EXPR:
479 if (flag_unit_at_a_time)
480 {
481 /* Record dereferences to the functions. This makes the
482 functions reachable unconditionally. */
483 tree decl = TREE_OPERAND (*tp, 0);
484 if (TREE_CODE (decl) == FUNCTION_DECL)
485 cgraph_mark_needed_node (cgraph_node (decl));
486 }
487 break;
488
25c84396
RH
489 default:
490 /* Save some cycles by not walking types and declaration as we
491 won't find anything useful there anyway. */
6615c446 492 if (IS_TYPE_OR_DECL_P (*tp))
1c4a429a 493 {
1c4a429a 494 *walk_subtrees = 0;
25c84396 495 break;
1c4a429a 496 }
25c84396
RH
497
498 if ((unsigned int) TREE_CODE (t) >= LAST_AND_UNUSED_TREE_CODE)
ae2bcd98 499 return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees, data);
25c84396 500 break;
1c4a429a 501 }
25c84396 502
1c4a429a
JH
503 return NULL;
504}
505
18c6ada9 506/* Create cgraph edges for function calls inside BODY from NODE. */
1c4a429a 507
e42922b1 508static void
18c6ada9 509cgraph_create_edges (struct cgraph_node *node, tree body)
1c4a429a 510{
e0704a46
JH
511 basic_block bb;
512
513 struct function *this_cfun = DECL_STRUCT_FUNCTION (body);
514 block_stmt_iterator bsi;
515 tree step;
0c58f841 516 visited_nodes = pointer_set_create ();
e21aff8a 517
e0704a46
JH
518 /* Reach the trees by walking over the CFG, and note the
519 enclosing basic-blocks in the call edges. */
520 FOR_EACH_BB_FN (bb, this_cfun)
521 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
522 {
523 tree stmt = bsi_stmt (bsi);
524 tree call = get_call_expr_in (stmt);
525 tree decl;
526
527 if (call && (decl = get_callee_fndecl (call)))
e21aff8a 528 {
e0704a46
JH
529 cgraph_create_edge (node, cgraph_node (decl), stmt,
530 bb->count,
531 bb->loop_depth);
532 walk_tree (&TREE_OPERAND (call, 1),
533 record_reference, node, visited_nodes);
534 if (TREE_CODE (stmt) == MODIFY_EXPR)
535 walk_tree (&TREE_OPERAND (stmt, 0),
536 record_reference, node, visited_nodes);
e21aff8a 537 }
e0704a46
JH
538 else
539 walk_tree (bsi_stmt_ptr (bsi), record_reference, node, visited_nodes);
540 }
541
542 /* Walk over any private statics that may take addresses of functions. */
543 if (TREE_CODE (DECL_INITIAL (body)) == BLOCK)
544 {
545 for (step = BLOCK_VARS (DECL_INITIAL (body));
546 step;
547 step = TREE_CHAIN (step))
548 if (DECL_INITIAL (step))
549 walk_tree (&DECL_INITIAL (step), record_reference, node, visited_nodes);
e21aff8a 550 }
e0704a46
JH
551
552 /* Also look here for private statics. */
553 if (DECL_STRUCT_FUNCTION (body))
554 for (step = DECL_STRUCT_FUNCTION (body)->unexpanded_var_list;
555 step;
556 step = TREE_CHAIN (step))
557 {
558 tree decl = TREE_VALUE (step);
559 if (DECL_INITIAL (decl) && TREE_STATIC (decl))
560 walk_tree (&DECL_INITIAL (decl), record_reference, node, visited_nodes);
561 }
e21aff8a 562
0c58f841 563 pointer_set_destroy (visited_nodes);
7dff32e6 564 visited_nodes = NULL;
1c4a429a
JH
565}
566
18c6ada9
JH
567
568/* Verify cgraph nodes of given cgraph node. */
569void
570verify_cgraph_node (struct cgraph_node *node)
571{
572 struct cgraph_edge *e;
573 struct cgraph_node *main_clone;
e21aff8a
SB
574 struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
575 basic_block this_block;
576 block_stmt_iterator bsi;
e0704a46 577 bool error_found = false;
18c6ada9
JH
578
579 timevar_push (TV_CGRAPH_VERIFY);
18c6ada9
JH
580 for (e = node->callees; e; e = e->next_callee)
581 if (e->aux)
582 {
583 error ("Aux field set for edge %s->%s",
584 cgraph_node_name (e->caller), cgraph_node_name (e->callee));
585 error_found = true;
586 }
587 for (e = node->callers; e; e = e->next_caller)
588 {
589 if (!e->inline_failed)
590 {
591 if (node->global.inlined_to
592 != (e->caller->global.inlined_to
593 ? e->caller->global.inlined_to : e->caller))
594 {
595 error ("Inlined_to pointer is wrong");
596 error_found = true;
597 }
598 if (node->callers->next_caller)
599 {
600 error ("Multiple inline callers");
601 error_found = true;
602 }
603 }
604 else
605 if (node->global.inlined_to)
606 {
607 error ("Inlined_to pointer set for noninline callers");
608 error_found = true;
609 }
610 }
611 if (!node->callers && node->global.inlined_to)
612 {
613 error ("Inlined_to pointer is set but no predecesors found");
614 error_found = true;
615 }
616 if (node->global.inlined_to == node)
617 {
cc9795d4 618 error ("Inlined_to pointer refers to itself");
18c6ada9
JH
619 error_found = true;
620 }
621
622 for (main_clone = cgraph_node (node->decl); main_clone;
623 main_clone = main_clone->next_clone)
624 if (main_clone == node)
625 break;
626 if (!node)
627 {
628 error ("Node not found in DECL_ASSEMBLER_NAME hash");
629 error_found = true;
630 }
631
632 if (node->analyzed
633 && DECL_SAVED_TREE (node->decl) && !TREE_ASM_WRITTEN (node->decl)
634 && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to))
635 {
e21aff8a
SB
636 if (this_cfun->cfg)
637 {
638 /* The nodes we're interested in are never shared, so walk
639 the tree ignoring duplicates. */
640 visited_nodes = pointer_set_create ();
641 /* Reach the trees by walking over the CFG, and note the
642 enclosing basic-blocks in the call edges. */
643 FOR_EACH_BB_FN (this_block, this_cfun)
644 for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
e0704a46
JH
645 {
646 tree stmt = bsi_stmt (bsi);
647 tree call = get_call_expr_in (stmt);
648 tree decl;
649 if (call && (decl = get_callee_fndecl (call)))
650 {
651 struct cgraph_edge *e = cgraph_edge (node, stmt);
652 if (e)
653 {
654 if (e->aux)
655 {
656 error ("Shared call_stmt:");
657 debug_generic_stmt (stmt);
658 error_found = true;
659 }
660 if (e->callee->decl != cgraph_node (decl)->decl)
661 {
662 error ("Edge points to wrong declaration:");
663 debug_tree (e->callee->decl);
664 fprintf (stderr," Instead of:");
665 debug_tree (decl);
666 }
667 e->aux = (void *)1;
668 }
669 else
670 {
671 error ("Missing callgraph edge for call stmt:");
672 debug_generic_stmt (stmt);
673 error_found = true;
674 }
675 }
676 }
e21aff8a
SB
677 pointer_set_destroy (visited_nodes);
678 visited_nodes = NULL;
679 }
680 else
681 /* No CFG available?! */
682 gcc_unreachable ();
683
18c6ada9
JH
684 for (e = node->callees; e; e = e->next_callee)
685 {
686 if (!e->aux)
687 {
e0704a46 688 error ("Edge %s->%s has no corresponding call_stmt",
18c6ada9
JH
689 cgraph_node_name (e->caller),
690 cgraph_node_name (e->callee));
e0704a46 691 debug_generic_stmt (e->call_stmt);
18c6ada9
JH
692 error_found = true;
693 }
694 e->aux = 0;
695 }
696 }
697 if (error_found)
698 {
699 dump_cgraph_node (stderr, node);
700 internal_error ("verify_cgraph_node failed.");
701 }
702 timevar_pop (TV_CGRAPH_VERIFY);
703}
704
705/* Verify whole cgraph structure. */
706void
707verify_cgraph (void)
708{
709 struct cgraph_node *node;
710
89480522
JH
711 if (sorrycount || errorcount)
712 return;
713
18c6ada9
JH
714 for (node = cgraph_nodes; node; node = node->next)
715 verify_cgraph_node (node);
716}
717
cd9c7bd2
JH
718
719/* Output all variables enqueued to be assembled. */
720bool
721cgraph_varpool_assemble_pending_decls (void)
722{
723 bool changed = false;
724
725 if (errorcount || sorrycount)
726 return false;
727
728 /* EH might mark decls as needed during expansion. This should be safe since
729 we don't create references to new function, but it should not be used
730 elsewhere. */
731 cgraph_varpool_analyze_pending_decls ();
732
733 while (cgraph_varpool_nodes_queue)
734 {
735 tree decl = cgraph_varpool_nodes_queue->decl;
736 struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
737
738 cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
739 if (!TREE_ASM_WRITTEN (decl) && !node->alias && !DECL_EXTERNAL (decl))
740 {
741 assemble_variable (decl, 0, 1, 0);
742 changed = true;
743 }
744 node->next_needed = NULL;
745 }
746 return changed;
747}
748
e767b5be
JH
749/* Analyze the function scheduled to be output. */
750static void
751cgraph_analyze_function (struct cgraph_node *node)
752{
753 tree decl = node->decl;
dc0bfe6a 754 struct cgraph_edge *e;
e767b5be 755
25c84396 756 current_function_decl = decl;
e21aff8a
SB
757 push_cfun (DECL_STRUCT_FUNCTION (decl));
758 cgraph_lower_function (node);
e767b5be
JH
759
760 /* First kill forward declaration so reverse inlining works properly. */
e21aff8a 761 cgraph_create_edges (node, decl);
e767b5be
JH
762
763 node->local.inlinable = tree_inlinable_function_p (decl);
e21aff8a 764 node->local.self_insns = estimate_num_insns (decl);
e767b5be
JH
765 if (node->local.inlinable)
766 node->local.disregard_inline_limits
ae2bcd98 767 = lang_hooks.tree_inlining.disregard_inline_limits (decl);
dc0bfe6a 768 for (e = node->callers; e; e = e->next_caller)
18c6ada9
JH
769 {
770 if (node->local.redefined_extern_inline)
771 e->inline_failed = N_("redefined extern inline functions are not "
772 "considered for inlining");
773 else if (!node->local.inlinable)
774 e->inline_failed = N_("function not inlinable");
775 else
776 e->inline_failed = N_("function not considered for inlining");
777 }
b684a3df
JH
778 if (flag_really_no_inline && !node->local.disregard_inline_limits)
779 node->local.inlinable = 0;
e767b5be
JH
780 /* Inlining characteristics are maintained by the cgraph_mark_inline. */
781 node->global.insns = node->local.self_insns;
e767b5be 782
25c84396 783 node->analyzed = true;
e21aff8a 784 pop_cfun ();
d853a20e 785 current_function_decl = NULL;
e767b5be
JH
786}
787
1c4a429a
JH
788/* Analyze the whole compilation unit once it is parsed completely. */
789
790void
db0e878d 791cgraph_finalize_compilation_unit (void)
1c4a429a
JH
792{
793 struct cgraph_node *node;
cd9c7bd2 794 /* Keep track of already processed nodes when called multiple times for
aabcd309 795 intermodule optimization. */
cd9c7bd2 796 static struct cgraph_node *first_analyzed;
1c4a429a 797
e4d5432a
RH
798 finish_aliases_1 ();
799
4a46cbfb 800 if (!flag_unit_at_a_time)
d853a20e
JH
801 {
802 cgraph_assemble_pending_functions ();
803 return;
804 }
4a46cbfb 805
b58b1157 806 if (!quiet_flag)
cd9c7bd2
JH
807 {
808 fprintf (stderr, "\nAnalyzing compilation unit");
809 fflush (stderr);
810 }
e69529cd 811
a194aa56 812 timevar_push (TV_CGRAPH);
cd9c7bd2 813 cgraph_varpool_analyze_pending_decls ();
a194aa56 814 if (cgraph_dump_file)
1c4a429a 815 {
7d82fe7c 816 fprintf (cgraph_dump_file, "Initial entry points:");
cd9c7bd2 817 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1668aabc 818 if (node->needed && DECL_SAVED_TREE (node->decl))
a194aa56
JH
819 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
820 fprintf (cgraph_dump_file, "\n");
1c4a429a
JH
821 }
822
7660e67e
SB
823 /* Propagate reachability flag and lower representation of all reachable
824 functions. In the future, lowering will introduce new functions and
825 new entry points on the way (by template instantiation and virtual
826 method table generation for instance). */
1668aabc 827 while (cgraph_nodes_queue)
1c4a429a 828 {
e767b5be 829 struct cgraph_edge *edge;
1668aabc
JH
830 tree decl = cgraph_nodes_queue->decl;
831
832 node = cgraph_nodes_queue;
8bd87c4e 833 cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
18c6ada9 834 node->next_needed = NULL;
1c4a429a 835
cd4dea62 836 /* ??? It is possible to create extern inline function and later using
9d203871 837 weak alias attribute to kill its body. See
cd4dea62
JH
838 gcc.c-torture/compile/20011119-1.c */
839 if (!DECL_SAVED_TREE (decl))
840 continue;
841
341c100f
NS
842 gcc_assert (!node->analyzed && node->reachable);
843 gcc_assert (DECL_SAVED_TREE (decl));
1c4a429a 844
e767b5be 845 cgraph_analyze_function (node);
8dafba3c 846
1c4a429a 847 for (edge = node->callees; edge; edge = edge->next_callee)
e767b5be 848 if (!edge->callee->reachable)
8dafba3c
RH
849 cgraph_mark_reachable_node (edge->callee);
850
cd9c7bd2 851 cgraph_varpool_analyze_pending_decls ();
1c4a429a 852 }
8dafba3c 853
1668aabc
JH
854 /* Collect entry points to the unit. */
855
a194aa56 856 if (cgraph_dump_file)
1668aabc 857 {
7d82fe7c 858 fprintf (cgraph_dump_file, "Unit entry points:");
cd9c7bd2 859 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1668aabc 860 if (node->needed && DECL_SAVED_TREE (node->decl))
a194aa56 861 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
7d82fe7c 862 fprintf (cgraph_dump_file, "\n\nInitial ");
e767b5be 863 dump_cgraph (cgraph_dump_file);
1668aabc 864 }
7660e67e 865
a194aa56
JH
866 if (cgraph_dump_file)
867 fprintf (cgraph_dump_file, "\nReclaiming functions:");
1c4a429a 868
cd9c7bd2 869 for (node = cgraph_nodes; node != first_analyzed; node = node->next)
1c4a429a
JH
870 {
871 tree decl = node->decl;
872
873 if (!node->reachable && DECL_SAVED_TREE (decl))
874 {
a194aa56
JH
875 if (cgraph_dump_file)
876 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
18c6ada9 877 cgraph_remove_node (node);
1c4a429a 878 }
9b0436b7
JH
879 else
880 node->next_needed = NULL;
1c4a429a 881 }
a194aa56 882 if (cgraph_dump_file)
7d82fe7c
KC
883 {
884 fprintf (cgraph_dump_file, "\n\nReclaimed ");
885 dump_cgraph (cgraph_dump_file);
886 }
cd9c7bd2 887 first_analyzed = cgraph_nodes;
1c4a429a 888 ggc_collect ();
a194aa56 889 timevar_pop (TV_CGRAPH);
1c4a429a 890}
1c4a429a
JH
891/* Figure out what functions we want to assemble. */
892
893static void
db0e878d 894cgraph_mark_functions_to_output (void)
1c4a429a
JH
895{
896 struct cgraph_node *node;
897
1c4a429a
JH
898 for (node = cgraph_nodes; node; node = node->next)
899 {
900 tree decl = node->decl;
b58b1157 901 struct cgraph_edge *e;
341c100f
NS
902
903 gcc_assert (!node->output);
b58b1157
JH
904
905 for (e = node->callers; e; e = e->next_caller)
dc0bfe6a 906 if (e->inline_failed)
b58b1157 907 break;
1c4a429a 908
7660e67e
SB
909 /* We need to output all local functions that are used and not
910 always inlined, as well as those that are reachable from
911 outside the current compilation unit. */
1c4a429a 912 if (DECL_SAVED_TREE (decl)
18c6ada9 913 && !node->global.inlined_to
1c4a429a 914 && (node->needed
b58b1157 915 || (e && node->reachable))
6de9cd9a 916 && !TREE_ASM_WRITTEN (decl)
1c4a429a
JH
917 && !DECL_EXTERNAL (decl))
918 node->output = 1;
341c100f 919 else
1a2caa7a
NS
920 {
921 /* We should've reclaimed all functions that are not needed. */
922#ifdef ENABLE_CHECKING
923 if (!node->global.inlined_to && DECL_SAVED_TREE (decl)
924 && !DECL_EXTERNAL (decl))
925 {
926 dump_cgraph_node (stderr, node);
927 internal_error ("failed to reclaim unneeded function");
928 }
929#endif
930 gcc_assert (node->global.inlined_to || !DECL_SAVED_TREE (decl)
931 || DECL_EXTERNAL (decl));
932
933 }
934
18d13f34
JH
935 }
936}
937
1c4a429a 938/* Expand function specified by NODE. */
7660e67e 939
1c4a429a 940static void
db0e878d 941cgraph_expand_function (struct cgraph_node *node)
1c4a429a
JH
942{
943 tree decl = node->decl;
944
18c6ada9 945 /* We ought to not compile any inline clones. */
341c100f 946 gcc_assert (!node->global.inlined_to);
18c6ada9 947
6b00c969
RH
948 if (flag_unit_at_a_time)
949 announce_function (decl);
18d13f34 950
776b966e
JH
951 cgraph_lower_function (node);
952
a3546141 953 /* Generate RTL for the body of DECL. */
ae2bcd98 954 lang_hooks.callgraph.expand_function (decl);
18d13f34 955
6de9cd9a
DN
956 /* Make sure that BE didn't give up on compiling. */
957 /* ??? Can happen with nested function of extern inline. */
341c100f 958 gcc_assert (TREE_ASM_WRITTEN (node->decl));
18c6ada9 959
1c4a429a 960 current_function_decl = NULL;
89480522 961 if (!cgraph_preserve_function_body_p (node->decl))
6de9cd9a
DN
962 {
963 DECL_SAVED_TREE (node->decl) = NULL;
964 DECL_STRUCT_FUNCTION (node->decl) = NULL;
6de9cd9a 965 DECL_INITIAL (node->decl) = error_mark_node;
229031d0 966 /* Eliminate all call edges. This is important so the call_expr no longer
89480522 967 points to the dead function body. */
2563c224 968 cgraph_node_remove_callees (node);
6de9cd9a 969 }
6b02a499
JH
970
971 cgraph_function_flags_ready = true;
1c4a429a
JH
972}
973
18c6ada9 974/* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */
b58b1157
JH
975
976bool
18c6ada9 977cgraph_inline_p (struct cgraph_edge *e, const char **reason)
b58b1157 978{
18c6ada9
JH
979 *reason = e->inline_failed;
980 return !e->inline_failed;
b58b1157 981}
18c6ada9 982
6674a6ce 983
6674a6ce 984
db0e878d
AJ
985/* Expand all functions that must be output.
986
b58b1157
JH
987 Attempt to topologically sort the nodes so function is output when
988 all called functions are already assembled to allow data to be
a98ebe2e 989 propagated across the callgraph. Use a stack to get smaller distance
d1a6adeb 990 between a function and its callees (later we may choose to use a more
b58b1157
JH
991 sophisticated algorithm for function reordering; we will likely want
992 to use subsections to make the output functions appear in top-down
993 order). */
994
995static void
a20af5b8 996cgraph_expand_all_functions (void)
b58b1157
JH
997{
998 struct cgraph_node *node;
999 struct cgraph_node **order =
b3c3af2f 1000 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
18c6ada9 1001 int order_pos = 0, new_order_pos = 0;
b58b1157
JH
1002 int i;
1003
b58b1157 1004 order_pos = cgraph_postorder (order);
341c100f 1005 gcc_assert (order_pos == cgraph_n_nodes);
b58b1157 1006
1ae58c30 1007 /* Garbage collector may remove inline clones we eliminate during
18c6ada9
JH
1008 optimization. So we must be sure to not reference them. */
1009 for (i = 0; i < order_pos; i++)
1010 if (order[i]->output)
1011 order[new_order_pos++] = order[i];
1012
1013 for (i = new_order_pos - 1; i >= 0; i--)
b58b1157
JH
1014 {
1015 node = order[i];
1016 if (node->output)
1017 {
341c100f 1018 gcc_assert (node->reachable);
b58b1157
JH
1019 node->output = 0;
1020 cgraph_expand_function (node);
1021 }
1022 }
1023 free (order);
1024}
1025
e7d6beb0 1026/* Mark visibility of all functions.
6674a6ce
KZ
1027
1028 A local function is one whose calls can occur only in the current
1029 compilation unit and all its calls are explicit, so we can change
1030 its calling convention. We simply mark all static functions whose
e7d6beb0
JH
1031 address is not taken as local.
1032
1033 We also change the TREE_PUBLIC flag of all declarations that are public
1034 in language point of view but we want to overwrite this default
1035 via visibilities for the backend point of view. */
b58b1157
JH
1036
1037static void
e7d6beb0 1038cgraph_function_and_variable_visibility (void)
b58b1157
JH
1039{
1040 struct cgraph_node *node;
e7d6beb0 1041 struct cgraph_varpool_node *vnode;
b58b1157 1042
b58b1157
JH
1043 for (node = cgraph_nodes; node; node = node->next)
1044 {
e7d6beb0
JH
1045 if (node->reachable
1046 && (DECL_COMDAT (node->decl)
1047 || (TREE_PUBLIC (node->decl) && !DECL_EXTERNAL (node->decl))))
1048 node->local.externally_visible = 1;
b58b1157 1049 node->local.local = (!node->needed
e7d6beb0 1050 && node->analyzed
e2089d72 1051 && !DECL_EXTERNAL (node->decl)
04b0eed0 1052 && !node->local.externally_visible);
e7d6beb0
JH
1053 }
1054 for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed)
1055 {
1056 if (vnode->needed
1057 && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl)))
1058 vnode->externally_visible = 1;
1059 gcc_assert (TREE_STATIC (vnode->decl));
b58b1157 1060 }
6674a6ce 1061
e7d6beb0
JH
1062 /* Because we have to be conservative on the boundaries of source
1063 level units, it is possible that we marked some functions in
1064 reachable just because they might be used later via external
1065 linkage, but after making them local they are really unreachable
1066 now. */
1067 cgraph_remove_unreachable_nodes (true, cgraph_dump_file);
1068
b58b1157 1069 if (cgraph_dump_file)
6674a6ce
KZ
1070 {
1071 fprintf (cgraph_dump_file, "\nMarking local functions:");
1072 for (node = cgraph_nodes; node; node = node->next)
1073 if (node->local.local)
1074 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1075 fprintf (cgraph_dump_file, "\n\n");
e7d6beb0
JH
1076 fprintf (cgraph_dump_file, "\nMarking externally visible functions:");
1077 for (node = cgraph_nodes; node; node = node->next)
1078 if (node->local.externally_visible)
1079 fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
1080 fprintf (cgraph_dump_file, "\n\n");
85c33455 1081 }
e7d6beb0 1082 cgraph_function_flags_ready = true;
6674a6ce 1083}
dafc5b82 1084
18c6ada9
JH
1085/* Return true when function body of DECL still needs to be kept around
1086 for later re-use. */
1087bool
1088cgraph_preserve_function_body_p (tree decl)
1089{
1090 struct cgraph_node *node;
1091 /* Keep the body; we're going to dump it. */
9f8628ba 1092 if (dump_enabled_p (TDI_tree_all))
18c6ada9
JH
1093 return true;
1094 if (!cgraph_global_info_ready)
1095 return (DECL_INLINE (decl) && !flag_really_no_inline);
1096 /* Look if there is any clone around. */
1097 for (node = cgraph_node (decl); node; node = node->next_clone)
1098 if (node->global.inlined_to)
1099 return true;
1100 return false;
1101}
1102
1c4a429a
JH
1103/* Perform simple optimizations based on callgraph. */
1104
1105void
db0e878d 1106cgraph_optimize (void)
1c4a429a 1107{
18c6ada9
JH
1108#ifdef ENABLE_CHECKING
1109 verify_cgraph ();
1110#endif
4a46cbfb 1111 if (!flag_unit_at_a_time)
cd9c7bd2
JH
1112 {
1113 cgraph_varpool_assemble_pending_decls ();
1114 return;
1115 }
857e7259
ZW
1116
1117 process_pending_assemble_externals ();
cd9c7bd2
JH
1118
1119 /* Frontend may output common variables after the unit has been finalized.
1120 It is safe to deal with them here as they are always zero initialized. */
1121 cgraph_varpool_analyze_pending_decls ();
857e7259 1122
a194aa56 1123 timevar_push (TV_CGRAPHOPT);
b58b1157
JH
1124 if (!quiet_flag)
1125 fprintf (stderr, "Performing intraprocedural optimizations\n");
7d82fe7c 1126
e7d6beb0 1127 cgraph_function_and_variable_visibility ();
a194aa56
JH
1128 if (cgraph_dump_file)
1129 {
7d82fe7c 1130 fprintf (cgraph_dump_file, "Marked ");
a194aa56
JH
1131 dump_cgraph (cgraph_dump_file);
1132 }
b4861090 1133 ipa_passes ();
6b02a499
JH
1134 /* This pass remove bodies of extern inline functions we never inlined.
1135 Do this later so other IPA passes see what is really going on. */
1136 cgraph_remove_unreachable_nodes (false, dump_file);
dafc5b82 1137 cgraph_global_info_ready = true;
a194aa56
JH
1138 if (cgraph_dump_file)
1139 {
7d82fe7c 1140 fprintf (cgraph_dump_file, "Optimized ");
a194aa56 1141 dump_cgraph (cgraph_dump_file);
cd9c7bd2 1142 dump_varpool (cgraph_dump_file);
a194aa56
JH
1143 }
1144 timevar_pop (TV_CGRAPHOPT);
1c4a429a 1145
b58b1157 1146 /* Output everything. */
7d82fe7c
KC
1147 if (!quiet_flag)
1148 fprintf (stderr, "Assembling functions:\n");
18c6ada9
JH
1149#ifdef ENABLE_CHECKING
1150 verify_cgraph ();
1151#endif
6674a6ce 1152
6674a6ce 1153 cgraph_mark_functions_to_output ();
a20af5b8 1154 cgraph_expand_all_functions ();
cd9c7bd2
JH
1155 cgraph_varpool_remove_unreferenced_decls ();
1156
1157 cgraph_varpool_assemble_pending_decls ();
1158
a194aa56
JH
1159 if (cgraph_dump_file)
1160 {
7d82fe7c 1161 fprintf (cgraph_dump_file, "\nFinal ");
a194aa56
JH
1162 dump_cgraph (cgraph_dump_file);
1163 }
18c6ada9
JH
1164#ifdef ENABLE_CHECKING
1165 verify_cgraph ();
6de9cd9a
DN
1166 /* Double check that all inline clones are gone and that all
1167 function bodies have been released from memory. */
1168 if (flag_unit_at_a_time
9f8628ba 1169 && !dump_enabled_p (TDI_tree_all)
6de9cd9a
DN
1170 && !(sorrycount || errorcount))
1171 {
1172 struct cgraph_node *node;
1173 bool error_found = false;
1174
1175 for (node = cgraph_nodes; node; node = node->next)
1176 if (node->analyzed
1177 && (node->global.inlined_to
1178 || DECL_SAVED_TREE (node->decl)))
1179 {
1180 error_found = true;
1181 dump_cgraph_node (stderr, node);
1182 }
1183 if (error_found)
1184 internal_error ("Nodes with no released memory found.");
1185 }
18c6ada9 1186#endif
1c4a429a 1187}
c9b9aa64
RH
1188
1189/* Generate and emit a static constructor or destructor. WHICH must be
1190 one of 'I' or 'D'. BODY should be a STATEMENT_LIST containing
1191 GENERIC statements. */
1192
1193void
35b6fdcf 1194cgraph_build_static_cdtor (char which, tree body, int priority)
c9b9aa64
RH
1195{
1196 static int counter = 0;
1197 char which_buf[16];
b785f485 1198 tree decl, name, resdecl;
c9b9aa64
RH
1199
1200 sprintf (which_buf, "%c_%d", which, counter++);
1201 name = get_file_function_name_long (which_buf);
1202
1203 decl = build_decl (FUNCTION_DECL, name,
1204 build_function_type (void_type_node, void_list_node));
1205 current_function_decl = decl;
1206
b785f485
RH
1207 resdecl = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1208 DECL_ARTIFICIAL (resdecl) = 1;
1209 DECL_IGNORED_P (resdecl) = 1;
1210 DECL_RESULT (decl) = resdecl;
1211
c9b9aa64
RH
1212 allocate_struct_function (decl);
1213
1214 TREE_STATIC (decl) = 1;
1215 TREE_USED (decl) = 1;
1216 DECL_ARTIFICIAL (decl) = 1;
1217 DECL_IGNORED_P (decl) = 1;
1218 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1219 DECL_SAVED_TREE (decl) = body;
1220 TREE_PUBLIC (decl) = ! targetm.have_ctors_dtors;
1221 DECL_UNINLINABLE (decl) = 1;
1222
1223 DECL_INITIAL (decl) = make_node (BLOCK);
1224 TREE_USED (DECL_INITIAL (decl)) = 1;
1225
1226 DECL_SOURCE_LOCATION (decl) = input_location;
1227 cfun->function_end_locus = input_location;
1228
341c100f
NS
1229 switch (which)
1230 {
1231 case 'I':
1232 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1233 break;
1234 case 'D':
1235 DECL_STATIC_DESTRUCTOR (decl) = 1;
1236 break;
1237 default:
1238 gcc_unreachable ();
1239 }
c9b9aa64
RH
1240
1241 gimplify_function_tree (decl);
1242
1243 /* ??? We will get called LATE in the compilation process. */
1244 if (cgraph_global_info_ready)
e21aff8a
SB
1245 {
1246 tree_lowering_passes (decl);
1247 tree_rest_of_compilation (decl);
1248 }
c9b9aa64
RH
1249 else
1250 cgraph_finalize_function (decl, 0);
1251
1252 if (targetm.have_ctors_dtors)
1253 {
1254 void (*fn) (rtx, int);
1255
1256 if (which == 'I')
1257 fn = targetm.asm_out.constructor;
1258 else
1259 fn = targetm.asm_out.destructor;
35b6fdcf 1260 fn (XEXP (DECL_RTL (decl), 0), priority);
c9b9aa64
RH
1261 }
1262}
9b3e897d
PB
1263
1264void
1265init_cgraph (void)
1266{
1267 cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
1268}