]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraph.c
* config/i386/i386.h (ix86_return_in_memory): Add prototype.
[thirdparty/gcc.git] / gcc / cgraph.c
CommitLineData
e72fcfe8
JH
1/* Callgraph handling code.
2 Copyright (C) 2003 Free Software Foundation, Inc.
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
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "tree.h"
e72fcfe8
JH
27#include "langhooks.h"
28#include "hashtab.h"
29#include "toplev.h"
30#include "flags.h"
31#include "ggc.h"
32#include "debug.h"
33#include "target.h"
1c4a429a 34#include "cgraph.h"
988d1653 35#include "varray.h"
e69529cd 36#include "output.h"
988d1653 37
e72fcfe8
JH
38
39/* Hash table used to convert declarations into nodes. */
ed2df68b 40static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
e72fcfe8
JH
41
42/* The linked list of cgraph nodes. */
1c4a429a 43struct cgraph_node *cgraph_nodes;
e72fcfe8 44
1668aabc
JH
45/* Queue of cgraph nodes scheduled to be lowered. */
46struct cgraph_node *cgraph_nodes_queue;
47
e72fcfe8 48/* Number of nodes in existence. */
1c4a429a 49int cgraph_n_nodes;
e72fcfe8 50
b58b1157
JH
51/* Maximal uid used in cgraph nodes. */
52int cgraph_max_uid;
53
dafc5b82
JH
54/* Set when whole unit has been analyzed so we can access global info. */
55bool cgraph_global_info_ready = false;
56
e69529cd 57/* Hash table used to convert declarations into nodes. */
ed2df68b 58static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
e69529cd
JH
59
60/* Queue of cgraph nodes scheduled to be lowered and output. */
61struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
62
63/* Number of nodes in existence. */
64int cgraph_varpool_n_nodes;
65
ed2df68b
JH
66/* The linked list of cgraph varpool nodes. */
67static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
68
439f7bc3
AJ
69static struct cgraph_edge *create_edge (struct cgraph_node *,
70 struct cgraph_node *);
439f7bc3
AJ
71static hashval_t hash_node (const void *);
72static int eq_node (const void *, const void *);
e72fcfe8
JH
73
74/* Returns a hash code for P. */
75
76static hashval_t
439f7bc3 77hash_node (const void *p)
e72fcfe8 78{
ed2df68b
JH
79 return ((hashval_t)
80 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
81 (((struct cgraph_node *) p)->decl)));
e72fcfe8
JH
82}
83
6356f892 84/* Returns nonzero if P1 and P2 are equal. */
e72fcfe8
JH
85
86static int
439f7bc3 87eq_node (const void *p1, const void *p2)
e72fcfe8
JH
88{
89 return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
1668aabc 90 (tree) p2);
e72fcfe8
JH
91}
92
93/* Return cgraph node assigned to DECL. Create new one when needed. */
1c4a429a 94struct cgraph_node *
439f7bc3 95cgraph_node (tree decl)
e72fcfe8
JH
96{
97 struct cgraph_node *node;
98 struct cgraph_node **slot;
99
988d1653
JH
100 if (TREE_CODE (decl) != FUNCTION_DECL)
101 abort ();
102
e72fcfe8 103 if (!cgraph_hash)
ed2df68b 104 cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
e72fcfe8 105
ed2df68b
JH
106 slot = (struct cgraph_node **)
107 htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl),
108 IDENTIFIER_HASH_VALUE
109 (DECL_ASSEMBLER_NAME (decl)), 1);
e72fcfe8
JH
110 if (*slot)
111 return *slot;
ed2df68b 112 node = ggc_alloc_cleared (sizeof (*node));
e72fcfe8
JH
113 node->decl = decl;
114 node->next = cgraph_nodes;
b58b1157 115 node->uid = cgraph_max_uid++;
18d13f34
JH
116 if (cgraph_nodes)
117 cgraph_nodes->previous = node;
118 node->previous = NULL;
e72fcfe8
JH
119 cgraph_nodes = node;
120 cgraph_n_nodes++;
121 *slot = node;
5c2e00ee 122 if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
e72fcfe8
JH
123 {
124 node->origin = cgraph_node (DECL_CONTEXT (decl));
125 node->next_nested = node->origin->nested;
126 node->origin->nested = node;
127 }
128 return node;
129}
130
1668aabc
JH
131/* Try to find existing function for identifier ID. */
132struct cgraph_node *
439f7bc3 133cgraph_node_for_identifier (tree id)
1668aabc
JH
134{
135 struct cgraph_node **slot;
136
137 if (TREE_CODE (id) != IDENTIFIER_NODE)
138 abort ();
139
140 if (!cgraph_hash)
e69529cd 141 return NULL;
1668aabc 142
ed2df68b
JH
143 slot = (struct cgraph_node **)
144 htab_find_slot_with_hash (cgraph_hash, id,
439f7bc3 145 IDENTIFIER_HASH_VALUE (id), 0);
1668aabc
JH
146 if (!slot)
147 return NULL;
148 return *slot;
149}
150
e72fcfe8
JH
151/* Create edge from CALLER to CALLEE in the cgraph. */
152
153static struct cgraph_edge *
439f7bc3 154create_edge (struct cgraph_node *caller, struct cgraph_node *callee)
e72fcfe8 155{
ed2df68b 156 struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
b58b1157
JH
157 struct cgraph_edge *edge2;
158
159 edge->inline_call = false;
160 /* At the moment we don't associate calls with specific CALL_EXPRs
161 as we probably ought to, so we must preserve inline_call flags to
162 be the same in all copies of the same edge. */
163 if (cgraph_global_info_ready)
fdacb904 164 for (edge2 = caller->callees; edge2; edge2 = edge2->next_callee)
b58b1157
JH
165 if (edge2->callee == callee)
166 {
167 edge->inline_call = edge2->inline_call;
168 break;
169 }
e72fcfe8
JH
170
171 edge->caller = caller;
172 edge->callee = callee;
173 edge->next_caller = callee->callers;
174 edge->next_callee = caller->callees;
175 caller->callees = edge;
176 callee->callers = edge;
177 return edge;
178}
179
180/* Remove the edge from CALLER to CALLEE in the cgraph. */
181
cb967da5 182void
439f7bc3 183cgraph_remove_edge (struct cgraph_node *caller, struct cgraph_node *callee)
e72fcfe8
JH
184{
185 struct cgraph_edge **edge, **edge2;
186
187 for (edge = &callee->callers; *edge && (*edge)->caller != caller;
188 edge = &((*edge)->next_caller))
189 continue;
190 if (!*edge)
191 abort ();
192 *edge = (*edge)->next_caller;
193 for (edge2 = &caller->callees; *edge2 && (*edge2)->callee != callee;
194 edge2 = &(*edge2)->next_callee)
195 continue;
196 if (!*edge2)
197 abort ();
198 *edge2 = (*edge2)->next_callee;
199}
200
18d13f34
JH
201/* Remove the node from cgraph. */
202
203void
439f7bc3 204cgraph_remove_node (struct cgraph_node *node)
18d13f34 205{
2ee1067b 206 void **slot;
18d13f34
JH
207 while (node->callers)
208 cgraph_remove_edge (node->callers->caller, node);
209 while (node->callees)
210 cgraph_remove_edge (node, node->callees->callee);
211 while (node->nested)
212 cgraph_remove_node (node->nested);
213 if (node->origin)
214 {
215 struct cgraph_node **node2 = &node->origin->nested;
216
217 while (*node2 != node)
218 node2 = &(*node2)->next_nested;
219 *node2 = node->next_nested;
220 }
221 if (node->previous)
222 node->previous->next = node->next;
223 else
224 cgraph_nodes = node;
225 if (node->next)
226 node->next->previous = node->previous;
227 DECL_SAVED_TREE (node->decl) = NULL;
2ee1067b
JH
228 slot =
229 htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (node->decl),
230 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
231 (node->decl)), 1);
232 htab_clear_slot (cgraph_hash, slot);
18d13f34
JH
233 /* Do not free the structure itself so the walk over chain can continue. */
234}
235
8dafba3c
RH
236/* Notify finalize_compilation_unit that given node is reachable. */
237
1668aabc 238void
8dafba3c 239cgraph_mark_reachable_node (struct cgraph_node *node)
1668aabc 240{
ba245151 241 if (!node->reachable && node->local.finalized)
1668aabc 242 {
ba245151 243 notice_global_symbol (node->decl);
1668aabc 244 node->reachable = 1;
e767b5be
JH
245
246 node->next_needed = cgraph_nodes_queue;
247 cgraph_nodes_queue = node;
248
249 /* At the moment frontend automatically emits all nested functions. */
250 if (node->nested)
1668aabc 251 {
e767b5be
JH
252 struct cgraph_node *node2;
253
254 for (node2 = node->nested; node2; node2 = node2->next_nested)
255 if (!node2->reachable)
8dafba3c 256 cgraph_mark_reachable_node (node2);
e767b5be 257 }
1668aabc
JH
258 }
259}
260
8dafba3c
RH
261/* Likewise indicate that a node is needed, i.e. reachable via some
262 external means. */
263
264void
265cgraph_mark_needed_node (struct cgraph_node *node)
266{
267 node->needed = 1;
268 cgraph_mark_reachable_node (node);
269}
18d13f34 270
e72fcfe8
JH
271/* Record call from CALLER to CALLEE */
272
1c4a429a 273struct cgraph_edge *
439f7bc3 274cgraph_record_call (tree caller, tree callee)
e72fcfe8
JH
275{
276 return create_edge (cgraph_node (caller), cgraph_node (callee));
277}
278
279void
439f7bc3 280cgraph_remove_call (tree caller, tree callee)
e72fcfe8 281{
18d13f34 282 cgraph_remove_edge (cgraph_node (caller), cgraph_node (callee));
e72fcfe8
JH
283}
284
285/* Return true when CALLER_DECL calls CALLEE_DECL. */
286
287bool
439f7bc3 288cgraph_calls_p (tree caller_decl, tree callee_decl)
e72fcfe8
JH
289{
290 struct cgraph_node *caller = cgraph_node (caller_decl);
291 struct cgraph_node *callee = cgraph_node (callee_decl);
292 struct cgraph_edge *edge;
293
294 for (edge = callee->callers; edge && (edge)->caller != caller;
295 edge = (edge->next_caller))
296 continue;
297 return edge != NULL;
298}
299
dafc5b82
JH
300/* Return local info for the compiled function. */
301
302struct cgraph_local_info *
439f7bc3 303cgraph_local_info (tree decl)
dafc5b82
JH
304{
305 struct cgraph_node *node;
306 if (TREE_CODE (decl) != FUNCTION_DECL)
307 abort ();
308 node = cgraph_node (decl);
309 return &node->local;
310}
311
312/* Return local info for the compiled function. */
313
314struct cgraph_global_info *
439f7bc3 315cgraph_global_info (tree decl)
dafc5b82
JH
316{
317 struct cgraph_node *node;
318 if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
319 abort ();
320 node = cgraph_node (decl);
321 return &node->global;
322}
323
b255a036
JH
324/* Return local info for the compiled function. */
325
326struct cgraph_rtl_info *
439f7bc3 327cgraph_rtl_info (tree decl)
b255a036
JH
328{
329 struct cgraph_node *node;
330 if (TREE_CODE (decl) != FUNCTION_DECL)
331 abort ();
332 node = cgraph_node (decl);
333 if (decl != current_function_decl
334 && !TREE_ASM_WRITTEN (node->decl))
335 return NULL;
336 return &node->rtl;
337}
338
a194aa56
JH
339/* Return name of the node used in debug output. */
340const char *
439f7bc3 341cgraph_node_name (struct cgraph_node *node)
a194aa56
JH
342{
343 return (*lang_hooks.decl_printable_name) (node->decl, 2);
344}
dafc5b82 345
e72fcfe8
JH
346/* Dump the callgraph. */
347
348void
439f7bc3 349dump_cgraph (FILE *f)
e72fcfe8
JH
350{
351 struct cgraph_node *node;
352
353 fprintf (f, "\nCallgraph:\n\n");
354 for (node = cgraph_nodes; node; node = node->next)
355 {
356 struct cgraph_edge *edge;
a194aa56 357 fprintf (f, "%s", cgraph_node_name (node));
b58b1157
JH
358 if (node->local.self_insns)
359 fprintf (f, " %i insns", node->local.self_insns);
e72fcfe8 360 if (node->origin)
a194aa56 361 fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
e72fcfe8
JH
362 if (node->needed)
363 fprintf (f, " needed");
364 else if (node->reachable)
365 fprintf (f, " reachable");
366 if (DECL_SAVED_TREE (node->decl))
367 fprintf (f, " tree");
368
b3c3af2f 369 if (node->local.disregard_inline_limits)
b58b1157
JH
370 fprintf (f, " always_inline");
371 else if (node->local.inlinable)
372 fprintf (f, " inlinable");
373 if (node->global.insns && node->global.insns != node->local.self_insns)
374 fprintf (f, " %i insns after inlining", node->global.insns);
375 if (node->global.cloned_times > 1)
376 fprintf (f, " cloned %ix", node->global.cloned_times);
b58b1157 377
7dd87381 378 fprintf (f, "\n called by: ");
e72fcfe8 379 for (edge = node->callers; edge; edge = edge->next_caller)
b58b1157
JH
380 {
381 fprintf (f, "%s ", cgraph_node_name (edge->caller));
382 if (edge->inline_call)
383 fprintf(f, "(inlined) ");
384 }
e72fcfe8
JH
385
386 fprintf (f, "\n calls: ");
387 for (edge = node->callees; edge; edge = edge->next_callee)
b58b1157
JH
388 {
389 fprintf (f, "%s ", cgraph_node_name (edge->callee));
390 if (edge->inline_call)
391 fprintf(f, "(inlined) ");
392 }
e72fcfe8
JH
393 fprintf (f, "\n");
394 }
395}
988d1653 396
e69529cd
JH
397/* Returns a hash code for P. */
398
399static hashval_t
439f7bc3 400cgraph_varpool_hash_node (const void *p)
e69529cd 401{
ed2df68b
JH
402 return ((hashval_t)
403 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
404 (((struct cgraph_varpool_node *) p)->decl)));
e69529cd
JH
405}
406
f1ba665b 407/* Returns nonzero if P1 and P2 are equal. */
e69529cd
JH
408
409static int
439f7bc3 410eq_cgraph_varpool_node (const void *p1, const void *p2)
e69529cd
JH
411{
412 return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) ==
413 (tree) p2);
414}
415
416/* Return cgraph_varpool node assigned to DECL. Create new one when needed. */
417struct cgraph_varpool_node *
418cgraph_varpool_node (tree decl)
419{
420 struct cgraph_varpool_node *node;
421 struct cgraph_varpool_node **slot;
422
423 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
424 abort ();
425
426 if (!cgraph_varpool_hash)
ed2df68b
JH
427 cgraph_varpool_hash = htab_create_ggc (10, cgraph_varpool_hash_node,
428 eq_cgraph_varpool_node, NULL);
429
e69529cd 430
ed2df68b
JH
431 slot = (struct cgraph_varpool_node **)
432 htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl),
433 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (decl)),
434 1);
e69529cd
JH
435 if (*slot)
436 return *slot;
ed2df68b 437 node = ggc_alloc_cleared (sizeof (*node));
e69529cd
JH
438 node->decl = decl;
439 cgraph_varpool_n_nodes++;
ed2df68b 440 cgraph_varpool_nodes = node;
e69529cd 441 *slot = node;
e69529cd
JH
442 return node;
443}
444
445/* Try to find existing function for identifier ID. */
446struct cgraph_varpool_node *
447cgraph_varpool_node_for_identifier (tree id)
448{
449 struct cgraph_varpool_node **slot;
450
451 if (TREE_CODE (id) != IDENTIFIER_NODE)
452 abort ();
453
454 if (!cgraph_varpool_hash)
455 return NULL;
456
ed2df68b
JH
457 slot = (struct cgraph_varpool_node **)
458 htab_find_slot_with_hash (cgraph_varpool_hash, id,
459 IDENTIFIER_HASH_VALUE (id), 0);
e69529cd
JH
460 if (!slot)
461 return NULL;
462 return *slot;
463}
464
465/* Notify finalize_compilation_unit that given node is reachable
466 or needed. */
467void
468cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
469{
470 if (!node->needed && node->finalized)
471 {
8bd87c4e 472 node->next_needed = cgraph_varpool_nodes_queue;
e69529cd 473 cgraph_varpool_nodes_queue = node;
810db579 474 notice_global_symbol (node->decl);
e69529cd
JH
475 }
476 node->needed = 1;
477}
478
479void
480cgraph_varpool_finalize_decl (tree decl)
481{
482 struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
d853a20e
JH
483
484 /* The first declaration of a variable that comes through this function
485 decides whether it is global (in C, has external linkage)
486 or local (in C, has internal linkage). So do nothing more
487 if this function has already run. */
488 if (node->finalized)
489 return;
490 if (node->needed)
e69529cd 491 {
8bd87c4e 492 node->next_needed = cgraph_varpool_nodes_queue;
e69529cd 493 cgraph_varpool_nodes_queue = node;
ba245151 494 notice_global_symbol (decl);
e69529cd
JH
495 }
496 node->finalized = true;
497
498 if (/* Externally visible variables must be output. The exception are
499 COMDAT functions that must be output only when they are needed. */
500 (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
501 /* Function whose name is output to the assembler file must be produced.
502 It is possible to assemble the name later after finalizing the function
503 and the fact is noticed in assemble_name then. */
504 || (DECL_ASSEMBLER_NAME_SET_P (decl)
505 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
506 {
507 cgraph_varpool_mark_needed_node (node);
508 }
509}
510
511bool
439f7bc3 512cgraph_varpool_assemble_pending_decls (void)
e69529cd
JH
513{
514 bool changed = false;
515
516 while (cgraph_varpool_nodes_queue)
517 {
518 tree decl = cgraph_varpool_nodes_queue->decl;
519 struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
520
8bd87c4e 521 cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
e69529cd
JH
522 if (!TREE_ASM_WRITTEN (decl))
523 {
524 assemble_variable (decl, 0, 1, 0);
525 changed = true;
526 }
8bd87c4e 527 node->next_needed = NULL;
e69529cd
JH
528 }
529 return changed;
530}
531
532
988d1653 533#include "gt-cgraph.h"