]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cgraph.c
Patch from Andrew Pinksi.
[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
dafc5b82
JH
51/* Set when whole unit has been analyzed so we can access global info. */
52bool cgraph_global_info_ready = false;
53
e69529cd 54/* Hash table used to convert declarations into nodes. */
ed2df68b 55static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
e69529cd
JH
56
57/* Queue of cgraph nodes scheduled to be lowered and output. */
58struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
59
60/* Number of nodes in existence. */
61int cgraph_varpool_n_nodes;
62
ed2df68b
JH
63/* The linked list of cgraph varpool nodes. */
64static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
65
e72fcfe8
JH
66static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
67 struct cgraph_node *));
18d13f34 68static void cgraph_remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
fad205ff
KG
69static hashval_t hash_node PARAMS ((const void *));
70static int eq_node PARAMS ((const void *, const void *));
e72fcfe8
JH
71
72/* Returns a hash code for P. */
73
74static hashval_t
75hash_node (p)
fad205ff 76 const void *p;
e72fcfe8 77{
ed2df68b
JH
78 return ((hashval_t)
79 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
80 (((struct cgraph_node *) p)->decl)));
e72fcfe8
JH
81}
82
6356f892 83/* Returns nonzero if P1 and P2 are equal. */
e72fcfe8
JH
84
85static int
86eq_node (p1, p2)
fad205ff
KG
87 const void *p1;
88 const void *p2;
e72fcfe8
JH
89{
90 return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
1668aabc 91 (tree) p2);
e72fcfe8
JH
92}
93
94/* Return cgraph node assigned to DECL. Create new one when needed. */
1c4a429a 95struct cgraph_node *
e72fcfe8
JH
96cgraph_node (decl)
97 tree decl;
98{
99 struct cgraph_node *node;
100 struct cgraph_node **slot;
101
988d1653
JH
102 if (TREE_CODE (decl) != FUNCTION_DECL)
103 abort ();
104
e72fcfe8 105 if (!cgraph_hash)
ed2df68b 106 cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
e72fcfe8 107
ed2df68b
JH
108 slot = (struct cgraph_node **)
109 htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl),
110 IDENTIFIER_HASH_VALUE
111 (DECL_ASSEMBLER_NAME (decl)), 1);
e72fcfe8
JH
112 if (*slot)
113 return *slot;
ed2df68b 114 node = ggc_alloc_cleared (sizeof (*node));
e72fcfe8
JH
115 node->decl = decl;
116 node->next = cgraph_nodes;
18d13f34
JH
117 if (cgraph_nodes)
118 cgraph_nodes->previous = node;
119 node->previous = NULL;
e72fcfe8
JH
120 cgraph_nodes = node;
121 cgraph_n_nodes++;
122 *slot = node;
5c2e00ee 123 if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
e72fcfe8
JH
124 {
125 node->origin = cgraph_node (DECL_CONTEXT (decl));
126 node->next_nested = node->origin->nested;
127 node->origin->nested = node;
128 }
129 return node;
130}
131
1668aabc
JH
132/* Try to find existing function for identifier ID. */
133struct cgraph_node *
134cgraph_node_for_identifier (id)
135 tree id;
136{
137 struct cgraph_node **slot;
138
139 if (TREE_CODE (id) != IDENTIFIER_NODE)
140 abort ();
141
142 if (!cgraph_hash)
e69529cd 143 return NULL;
1668aabc 144
ed2df68b
JH
145 slot = (struct cgraph_node **)
146 htab_find_slot_with_hash (cgraph_hash, id,
147 IDENTIFIER_HASH_VALUE (id), 0);
1668aabc
JH
148 if (!slot)
149 return NULL;
150 return *slot;
151}
152
e72fcfe8
JH
153/* Create edge from CALLER to CALLEE in the cgraph. */
154
155static struct cgraph_edge *
156create_edge (caller, callee)
157 struct cgraph_node *caller, *callee;
158{
ed2df68b 159 struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
e72fcfe8
JH
160
161 edge->caller = caller;
162 edge->callee = callee;
163 edge->next_caller = callee->callers;
164 edge->next_callee = caller->callees;
165 caller->callees = edge;
166 callee->callers = edge;
167 return edge;
168}
169
170/* Remove the edge from CALLER to CALLEE in the cgraph. */
171
172static void
18d13f34 173cgraph_remove_edge (caller, callee)
e72fcfe8
JH
174 struct cgraph_node *caller, *callee;
175{
176 struct cgraph_edge **edge, **edge2;
177
178 for (edge = &callee->callers; *edge && (*edge)->caller != caller;
179 edge = &((*edge)->next_caller))
180 continue;
181 if (!*edge)
182 abort ();
183 *edge = (*edge)->next_caller;
184 for (edge2 = &caller->callees; *edge2 && (*edge2)->callee != callee;
185 edge2 = &(*edge2)->next_callee)
186 continue;
187 if (!*edge2)
188 abort ();
189 *edge2 = (*edge2)->next_callee;
190}
191
18d13f34
JH
192/* Remove the node from cgraph. */
193
194void
195cgraph_remove_node (node)
196 struct cgraph_node *node;
197{
198 while (node->callers)
199 cgraph_remove_edge (node->callers->caller, node);
200 while (node->callees)
201 cgraph_remove_edge (node, node->callees->callee);
202 while (node->nested)
203 cgraph_remove_node (node->nested);
204 if (node->origin)
205 {
206 struct cgraph_node **node2 = &node->origin->nested;
207
208 while (*node2 != node)
209 node2 = &(*node2)->next_nested;
210 *node2 = node->next_nested;
211 }
212 if (node->previous)
213 node->previous->next = node->next;
214 else
215 cgraph_nodes = node;
216 if (node->next)
217 node->next->previous = node->previous;
218 DECL_SAVED_TREE (node->decl) = NULL;
219 /* Do not free the structure itself so the walk over chain can continue. */
220}
221
1668aabc
JH
222/* Notify finalize_compilation_unit that given node is reachable
223 or needed. */
224void
225cgraph_mark_needed_node (node, needed)
226 struct cgraph_node *node;
227 int needed;
228{
229 if (needed)
230 {
231 node->needed = 1;
232 }
233 if (!node->reachable)
234 {
235 node->reachable = 1;
236 if (DECL_SAVED_TREE (node->decl))
237 {
8bd87c4e 238 node->next_needed = cgraph_nodes_queue;
1668aabc
JH
239 cgraph_nodes_queue = node;
240 }
241 }
242}
243
18d13f34 244
e72fcfe8
JH
245/* Record call from CALLER to CALLEE */
246
1c4a429a
JH
247struct cgraph_edge *
248cgraph_record_call (caller, callee)
e72fcfe8
JH
249 tree caller, callee;
250{
251 return create_edge (cgraph_node (caller), cgraph_node (callee));
252}
253
254void
255cgraph_remove_call (caller, callee)
256 tree caller, callee;
257{
18d13f34 258 cgraph_remove_edge (cgraph_node (caller), cgraph_node (callee));
e72fcfe8
JH
259}
260
261/* Return true when CALLER_DECL calls CALLEE_DECL. */
262
263bool
264cgraph_calls_p (caller_decl, callee_decl)
265 tree caller_decl, callee_decl;
266{
267 struct cgraph_node *caller = cgraph_node (caller_decl);
268 struct cgraph_node *callee = cgraph_node (callee_decl);
269 struct cgraph_edge *edge;
270
271 for (edge = callee->callers; edge && (edge)->caller != caller;
272 edge = (edge->next_caller))
273 continue;
274 return edge != NULL;
275}
276
dafc5b82
JH
277/* Return local info for the compiled function. */
278
279struct cgraph_local_info *
280cgraph_local_info (decl)
281 tree decl;
282{
283 struct cgraph_node *node;
284 if (TREE_CODE (decl) != FUNCTION_DECL)
285 abort ();
286 node = cgraph_node (decl);
287 return &node->local;
288}
289
290/* Return local info for the compiled function. */
291
292struct cgraph_global_info *
293cgraph_global_info (decl)
294 tree decl;
295{
296 struct cgraph_node *node;
297 if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
298 abort ();
299 node = cgraph_node (decl);
300 return &node->global;
301}
302
b255a036
JH
303/* Return local info for the compiled function. */
304
305struct cgraph_rtl_info *
306cgraph_rtl_info (decl)
307 tree decl;
308{
309 struct cgraph_node *node;
310 if (TREE_CODE (decl) != FUNCTION_DECL)
311 abort ();
312 node = cgraph_node (decl);
313 if (decl != current_function_decl
314 && !TREE_ASM_WRITTEN (node->decl))
315 return NULL;
316 return &node->rtl;
317}
318
a194aa56
JH
319/* Return name of the node used in debug output. */
320const char *
321cgraph_node_name (node)
322 struct cgraph_node *node;
323{
324 return (*lang_hooks.decl_printable_name) (node->decl, 2);
325}
dafc5b82 326
e72fcfe8
JH
327/* Dump the callgraph. */
328
329void
330dump_cgraph (f)
331 FILE *f;
332{
333 struct cgraph_node *node;
334
335 fprintf (f, "\nCallgraph:\n\n");
336 for (node = cgraph_nodes; node; node = node->next)
337 {
338 struct cgraph_edge *edge;
a194aa56 339 fprintf (f, "%s", cgraph_node_name (node));
e72fcfe8 340 if (node->origin)
a194aa56 341 fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
e72fcfe8
JH
342 if (node->needed)
343 fprintf (f, " needed");
344 else if (node->reachable)
345 fprintf (f, " reachable");
346 if (DECL_SAVED_TREE (node->decl))
347 fprintf (f, " tree");
348
349 fprintf (f, "\n called by :");
350 for (edge = node->callers; edge; edge = edge->next_caller)
a194aa56 351 fprintf (f, "%s ", cgraph_node_name (edge->caller));
e72fcfe8
JH
352
353 fprintf (f, "\n calls: ");
354 for (edge = node->callees; edge; edge = edge->next_callee)
a194aa56 355 fprintf (f, "%s ", cgraph_node_name (edge->callee));
e72fcfe8
JH
356 fprintf (f, "\n");
357 }
358}
988d1653 359
e69529cd
JH
360/* Returns a hash code for P. */
361
362static hashval_t
363cgraph_varpool_hash_node (const PTR p)
364{
ed2df68b
JH
365 return ((hashval_t)
366 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
367 (((struct cgraph_varpool_node *) p)->decl)));
e69529cd
JH
368}
369
f1ba665b 370/* Returns nonzero if P1 and P2 are equal. */
e69529cd
JH
371
372static int
373eq_cgraph_varpool_node (const PTR p1, const PTR p2)
374{
375 return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) ==
376 (tree) p2);
377}
378
379/* Return cgraph_varpool node assigned to DECL. Create new one when needed. */
380struct cgraph_varpool_node *
381cgraph_varpool_node (tree decl)
382{
383 struct cgraph_varpool_node *node;
384 struct cgraph_varpool_node **slot;
385
386 if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
387 abort ();
388
389 if (!cgraph_varpool_hash)
ed2df68b
JH
390 cgraph_varpool_hash = htab_create_ggc (10, cgraph_varpool_hash_node,
391 eq_cgraph_varpool_node, NULL);
392
e69529cd 393
ed2df68b
JH
394 slot = (struct cgraph_varpool_node **)
395 htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl),
396 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (decl)),
397 1);
e69529cd
JH
398 if (*slot)
399 return *slot;
ed2df68b 400 node = ggc_alloc_cleared (sizeof (*node));
e69529cd
JH
401 node->decl = decl;
402 cgraph_varpool_n_nodes++;
ed2df68b 403 cgraph_varpool_nodes = node;
e69529cd 404 *slot = node;
e69529cd
JH
405 return node;
406}
407
408/* Try to find existing function for identifier ID. */
409struct cgraph_varpool_node *
410cgraph_varpool_node_for_identifier (tree id)
411{
412 struct cgraph_varpool_node **slot;
413
414 if (TREE_CODE (id) != IDENTIFIER_NODE)
415 abort ();
416
417 if (!cgraph_varpool_hash)
418 return NULL;
419
ed2df68b
JH
420 slot = (struct cgraph_varpool_node **)
421 htab_find_slot_with_hash (cgraph_varpool_hash, id,
422 IDENTIFIER_HASH_VALUE (id), 0);
e69529cd
JH
423 if (!slot)
424 return NULL;
425 return *slot;
426}
427
428/* Notify finalize_compilation_unit that given node is reachable
429 or needed. */
430void
431cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
432{
433 if (!node->needed && node->finalized)
434 {
8bd87c4e 435 node->next_needed = cgraph_varpool_nodes_queue;
e69529cd
JH
436 cgraph_varpool_nodes_queue = node;
437 }
438 node->needed = 1;
439}
440
441void
442cgraph_varpool_finalize_decl (tree decl)
443{
444 struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
445
446 if (node->needed && !node->finalized)
447 {
8bd87c4e 448 node->next_needed = cgraph_varpool_nodes_queue;
e69529cd
JH
449 cgraph_varpool_nodes_queue = node;
450 }
451 node->finalized = true;
452
453 if (/* Externally visible variables must be output. The exception are
454 COMDAT functions that must be output only when they are needed. */
455 (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
456 /* Function whose name is output to the assembler file must be produced.
457 It is possible to assemble the name later after finalizing the function
458 and the fact is noticed in assemble_name then. */
459 || (DECL_ASSEMBLER_NAME_SET_P (decl)
460 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
461 {
462 cgraph_varpool_mark_needed_node (node);
463 }
464}
465
466bool
467cgraph_varpool_assemble_pending_decls ()
468{
469 bool changed = false;
470
471 while (cgraph_varpool_nodes_queue)
472 {
473 tree decl = cgraph_varpool_nodes_queue->decl;
474 struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
475
8bd87c4e 476 cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
e69529cd
JH
477 if (!TREE_ASM_WRITTEN (decl))
478 {
479 assemble_variable (decl, 0, 1, 0);
480 changed = true;
481 }
8bd87c4e 482 node->next_needed = NULL;
e69529cd
JH
483 }
484 return changed;
485}
486
487
988d1653 488#include "gt-cgraph.h"