1 /* Callgraph handling code.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 #include "coretypes.h"
27 #include "langhooks.h"
39 /* Hash table used to convert declarations into nodes. */
40 static GTY((param_is (struct cgraph_node
))) htab_t cgraph_hash
;
42 /* The linked list of cgraph nodes. */
43 struct cgraph_node
*cgraph_nodes
;
45 /* Queue of cgraph nodes scheduled to be lowered. */
46 struct cgraph_node
*cgraph_nodes_queue
;
48 /* Number of nodes in existence. */
51 /* Maximal uid used in cgraph nodes. */
54 /* Set when whole unit has been analyzed so we can access global info. */
55 bool cgraph_global_info_ready
= false;
57 /* Hash table used to convert declarations into nodes. */
58 static GTY((param_is (struct cgraph_varpool_node
))) htab_t cgraph_varpool_hash
;
60 /* Queue of cgraph nodes scheduled to be lowered and output. */
61 struct cgraph_varpool_node
*cgraph_varpool_nodes_queue
;
63 /* Number of nodes in existence. */
64 int cgraph_varpool_n_nodes
;
66 /* The linked list of cgraph varpool nodes. */
67 static GTY(()) struct cgraph_varpool_node
*cgraph_varpool_nodes
;
69 static struct cgraph_edge
*create_edge (struct cgraph_node
*,
70 struct cgraph_node
*);
71 static void cgraph_remove_edge (struct cgraph_node
*, struct cgraph_node
*);
72 static hashval_t
hash_node (const void *);
73 static int eq_node (const void *, const void *);
75 /* Returns a hash code for P. */
78 hash_node (const void *p
)
81 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
82 (((struct cgraph_node
*) p
)->decl
)));
85 /* Returns nonzero if P1 and P2 are equal. */
88 eq_node (const void *p1
, const void *p2
)
90 return ((DECL_ASSEMBLER_NAME (((struct cgraph_node
*) p1
)->decl
)) ==
94 /* Return cgraph node assigned to DECL. Create new one when needed. */
96 cgraph_node (tree decl
)
98 struct cgraph_node
*node
;
99 struct cgraph_node
**slot
;
101 if (TREE_CODE (decl
) != FUNCTION_DECL
)
105 cgraph_hash
= htab_create_ggc (10, hash_node
, eq_node
, NULL
);
107 slot
= (struct cgraph_node
**)
108 htab_find_slot_with_hash (cgraph_hash
, DECL_ASSEMBLER_NAME (decl
),
109 IDENTIFIER_HASH_VALUE
110 (DECL_ASSEMBLER_NAME (decl
)), 1);
113 node
= ggc_alloc_cleared (sizeof (*node
));
115 node
->next
= cgraph_nodes
;
116 node
->uid
= cgraph_max_uid
++;
118 cgraph_nodes
->previous
= node
;
119 node
->previous
= NULL
;
123 if (DECL_CONTEXT (decl
) && TREE_CODE (DECL_CONTEXT (decl
)) == FUNCTION_DECL
)
125 node
->origin
= cgraph_node (DECL_CONTEXT (decl
));
126 node
->next_nested
= node
->origin
->nested
;
127 node
->origin
->nested
= node
;
132 /* Try to find existing function for identifier ID. */
134 cgraph_node_for_identifier (tree id
)
136 struct cgraph_node
**slot
;
138 if (TREE_CODE (id
) != IDENTIFIER_NODE
)
144 slot
= (struct cgraph_node
**)
145 htab_find_slot_with_hash (cgraph_hash
, id
,
146 IDENTIFIER_HASH_VALUE (id
), 0);
152 /* Create edge from CALLER to CALLEE in the cgraph. */
154 static struct cgraph_edge
*
155 create_edge (struct cgraph_node
*caller
, struct cgraph_node
*callee
)
157 struct cgraph_edge
*edge
= ggc_alloc (sizeof (struct cgraph_edge
));
158 struct cgraph_edge
*edge2
;
160 edge
->inline_call
= false;
161 /* At the moment we don't associate calls with specific CALL_EXPRs
162 as we probably ought to, so we must preserve inline_call flags to
163 be the same in all copies of the same edge. */
164 if (cgraph_global_info_ready
)
165 for (edge2
= caller
->callees
; edge2
; edge2
= edge2
->next_callee
)
166 if (edge2
->callee
== callee
)
168 edge
->inline_call
= edge2
->inline_call
;
172 edge
->caller
= caller
;
173 edge
->callee
= callee
;
174 edge
->next_caller
= callee
->callers
;
175 edge
->next_callee
= caller
->callees
;
176 caller
->callees
= edge
;
177 callee
->callers
= edge
;
181 /* Remove the edge from CALLER to CALLEE in the cgraph. */
184 cgraph_remove_edge (struct cgraph_node
*caller
, struct cgraph_node
*callee
)
186 struct cgraph_edge
**edge
, **edge2
;
188 for (edge
= &callee
->callers
; *edge
&& (*edge
)->caller
!= caller
;
189 edge
= &((*edge
)->next_caller
))
193 *edge
= (*edge
)->next_caller
;
194 for (edge2
= &caller
->callees
; *edge2
&& (*edge2
)->callee
!= callee
;
195 edge2
= &(*edge2
)->next_callee
)
199 *edge2
= (*edge2
)->next_callee
;
202 /* Remove the node from cgraph. */
205 cgraph_remove_node (struct cgraph_node
*node
)
208 while (node
->callers
)
209 cgraph_remove_edge (node
->callers
->caller
, node
);
210 while (node
->callees
)
211 cgraph_remove_edge (node
, node
->callees
->callee
);
213 cgraph_remove_node (node
->nested
);
216 struct cgraph_node
**node2
= &node
->origin
->nested
;
218 while (*node2
!= node
)
219 node2
= &(*node2
)->next_nested
;
220 *node2
= node
->next_nested
;
223 node
->previous
->next
= node
->next
;
227 node
->next
->previous
= node
->previous
;
228 DECL_SAVED_TREE (node
->decl
) = NULL
;
230 htab_find_slot_with_hash (cgraph_hash
, DECL_ASSEMBLER_NAME (node
->decl
),
231 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
233 htab_clear_slot (cgraph_hash
, slot
);
234 /* Do not free the structure itself so the walk over chain can continue. */
237 /* Notify finalize_compilation_unit that given node is reachable
240 cgraph_mark_needed_node (struct cgraph_node
*node
, int needed
)
245 if (!node
->reachable
&& DECL_SAVED_TREE (node
->decl
))
249 node
->next_needed
= cgraph_nodes_queue
;
250 cgraph_nodes_queue
= node
;
251 notice_global_symbol (node
->decl
);
253 /* At the moment frontend automatically emits all nested functions. */
256 struct cgraph_node
*node2
;
258 for (node2
= node
->nested
; node2
; node2
= node2
->next_nested
)
259 if (!node2
->reachable
)
260 cgraph_mark_needed_node (node2
, 0);
266 /* Record call from CALLER to CALLEE */
269 cgraph_record_call (tree caller
, tree callee
)
271 return create_edge (cgraph_node (caller
), cgraph_node (callee
));
275 cgraph_remove_call (tree caller
, tree callee
)
277 cgraph_remove_edge (cgraph_node (caller
), cgraph_node (callee
));
280 /* Return true when CALLER_DECL calls CALLEE_DECL. */
283 cgraph_calls_p (tree caller_decl
, tree callee_decl
)
285 struct cgraph_node
*caller
= cgraph_node (caller_decl
);
286 struct cgraph_node
*callee
= cgraph_node (callee_decl
);
287 struct cgraph_edge
*edge
;
289 for (edge
= callee
->callers
; edge
&& (edge
)->caller
!= caller
;
290 edge
= (edge
->next_caller
))
295 /* Return local info for the compiled function. */
297 struct cgraph_local_info
*
298 cgraph_local_info (tree decl
)
300 struct cgraph_node
*node
;
301 if (TREE_CODE (decl
) != FUNCTION_DECL
)
303 node
= cgraph_node (decl
);
307 /* Return local info for the compiled function. */
309 struct cgraph_global_info
*
310 cgraph_global_info (tree decl
)
312 struct cgraph_node
*node
;
313 if (TREE_CODE (decl
) != FUNCTION_DECL
|| !cgraph_global_info_ready
)
315 node
= cgraph_node (decl
);
316 return &node
->global
;
319 /* Return local info for the compiled function. */
321 struct cgraph_rtl_info
*
322 cgraph_rtl_info (tree decl
)
324 struct cgraph_node
*node
;
325 if (TREE_CODE (decl
) != FUNCTION_DECL
)
327 node
= cgraph_node (decl
);
328 if (decl
!= current_function_decl
329 && !TREE_ASM_WRITTEN (node
->decl
))
334 /* Return name of the node used in debug output. */
336 cgraph_node_name (struct cgraph_node
*node
)
338 return (*lang_hooks
.decl_printable_name
) (node
->decl
, 2);
341 /* Dump the callgraph. */
344 dump_cgraph (FILE *f
)
346 struct cgraph_node
*node
;
348 fprintf (f
, "\nCallgraph:\n\n");
349 for (node
= cgraph_nodes
; node
; node
= node
->next
)
351 struct cgraph_edge
*edge
;
352 fprintf (f
, "%s", cgraph_node_name (node
));
353 if (node
->local
.self_insns
)
354 fprintf (f
, " %i insns", node
->local
.self_insns
);
356 fprintf (f
, " nested in: %s", cgraph_node_name (node
->origin
));
358 fprintf (f
, " needed");
359 else if (node
->reachable
)
360 fprintf (f
, " reachable");
361 if (DECL_SAVED_TREE (node
->decl
))
362 fprintf (f
, " tree");
364 if (node
->local
.disregard_inline_limits
)
365 fprintf (f
, " always_inline");
366 else if (node
->local
.inlinable
)
367 fprintf (f
, " inlinable");
368 if (node
->global
.insns
&& node
->global
.insns
!= node
->local
.self_insns
)
369 fprintf (f
, " %i insns after inlining", node
->global
.insns
);
370 if (node
->global
.cloned_times
> 1)
371 fprintf (f
, " cloned %ix", node
->global
.cloned_times
);
373 fprintf (f
, "\n called by :");
374 for (edge
= node
->callers
; edge
; edge
= edge
->next_caller
)
376 fprintf (f
, "%s ", cgraph_node_name (edge
->caller
));
377 if (edge
->inline_call
)
378 fprintf(f
, "(inlined) ");
381 fprintf (f
, "\n calls: ");
382 for (edge
= node
->callees
; edge
; edge
= edge
->next_callee
)
384 fprintf (f
, "%s ", cgraph_node_name (edge
->callee
));
385 if (edge
->inline_call
)
386 fprintf(f
, "(inlined) ");
392 /* Returns a hash code for P. */
395 cgraph_varpool_hash_node (const void *p
)
398 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
399 (((struct cgraph_varpool_node
*) p
)->decl
)));
402 /* Returns nonzero if P1 and P2 are equal. */
405 eq_cgraph_varpool_node (const void *p1
, const void *p2
)
407 return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node
*) p1
)->decl
)) ==
411 /* Return cgraph_varpool node assigned to DECL. Create new one when needed. */
412 struct cgraph_varpool_node
*
413 cgraph_varpool_node (tree decl
)
415 struct cgraph_varpool_node
*node
;
416 struct cgraph_varpool_node
**slot
;
418 if (!DECL_P (decl
) || TREE_CODE (decl
) == FUNCTION_DECL
)
421 if (!cgraph_varpool_hash
)
422 cgraph_varpool_hash
= htab_create_ggc (10, cgraph_varpool_hash_node
,
423 eq_cgraph_varpool_node
, NULL
);
426 slot
= (struct cgraph_varpool_node
**)
427 htab_find_slot_with_hash (cgraph_varpool_hash
, DECL_ASSEMBLER_NAME (decl
),
428 IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (decl
)),
432 node
= ggc_alloc_cleared (sizeof (*node
));
434 cgraph_varpool_n_nodes
++;
435 cgraph_varpool_nodes
= node
;
440 /* Try to find existing function for identifier ID. */
441 struct cgraph_varpool_node
*
442 cgraph_varpool_node_for_identifier (tree id
)
444 struct cgraph_varpool_node
**slot
;
446 if (TREE_CODE (id
) != IDENTIFIER_NODE
)
449 if (!cgraph_varpool_hash
)
452 slot
= (struct cgraph_varpool_node
**)
453 htab_find_slot_with_hash (cgraph_varpool_hash
, id
,
454 IDENTIFIER_HASH_VALUE (id
), 0);
460 /* Notify finalize_compilation_unit that given node is reachable
463 cgraph_varpool_mark_needed_node (struct cgraph_varpool_node
*node
)
465 if (!node
->needed
&& node
->finalized
)
467 node
->next_needed
= cgraph_varpool_nodes_queue
;
468 cgraph_varpool_nodes_queue
= node
;
469 notice_global_symbol (node
->decl
);
475 cgraph_varpool_finalize_decl (tree decl
)
477 struct cgraph_varpool_node
*node
= cgraph_varpool_node (decl
);
479 if (node
->needed
&& !node
->finalized
)
481 node
->next_needed
= cgraph_varpool_nodes_queue
;
482 cgraph_varpool_nodes_queue
= node
;
484 node
->finalized
= true;
486 if (/* Externally visible variables must be output. The exception are
487 COMDAT functions that must be output only when they are needed. */
488 (TREE_PUBLIC (decl
) && !DECL_COMDAT (decl
))
489 /* Function whose name is output to the assembler file must be produced.
490 It is possible to assemble the name later after finalizing the function
491 and the fact is noticed in assemble_name then. */
492 || (DECL_ASSEMBLER_NAME_SET_P (decl
)
493 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
))))
495 cgraph_varpool_mark_needed_node (node
);
500 cgraph_varpool_assemble_pending_decls (void)
502 bool changed
= false;
504 while (cgraph_varpool_nodes_queue
)
506 tree decl
= cgraph_varpool_nodes_queue
->decl
;
507 struct cgraph_varpool_node
*node
= cgraph_varpool_nodes_queue
;
509 cgraph_varpool_nodes_queue
= cgraph_varpool_nodes_queue
->next_needed
;
510 if (!TREE_ASM_WRITTEN (decl
))
512 assemble_variable (decl
, 0, 1, 0);
515 node
->next_needed
= NULL
;
521 #include "gt-cgraph.h"