00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #include "config.h"
00083 #include "system.h"
00084 #include "coretypes.h"
00085 #include "tm.h"
00086 #include "tree.h"
00087 #include "langhooks.h"
00088 #include "hashtab.h"
00089 #include "toplev.h"
00090 #include "flags.h"
00091 #include "ggc.h"
00092 #include "debug.h"
00093 #include "target.h"
00094 #include "cgraph.h"
00095 #include "varray.h"
00096 #include "output.h"
00097 #include "intl.h"
00098 #ifdef KEY
00099 #include "gspin-gcc-interface.h"
00100 #endif
00101
00102 static void cgraph_node_remove_callers (struct cgraph_node *node);
00103 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
00104 static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
00105
00106
00107 static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
00108
00109
00110 struct cgraph_node *cgraph_nodes;
00111
00112
00113 struct cgraph_node *cgraph_nodes_queue;
00114
00115
00116 int cgraph_n_nodes;
00117
00118
00119 int cgraph_max_uid;
00120
00121
00122 bool cgraph_global_info_ready = false;
00123
00124
00125 static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
00126
00127
00128 struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
00129
00130
00131 static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
00132
00133 static hashval_t hash_node (const void *);
00134 static int eq_node (const void *, const void *);
00135
00136
00137
00138 static hashval_t
00139 hash_node (const void *p)
00140 {
00141 const struct cgraph_node *n = p;
00142 return (hashval_t) DECL_UID (n->decl);
00143 }
00144
00145
00146
00147 static int
00148 eq_node (const void *p1, const void *p2)
00149 {
00150 const struct cgraph_node *n1 = p1, *n2 = p2;
00151 return DECL_UID (n1->decl) == DECL_UID (n2->decl);
00152 }
00153
00154
00155 static struct cgraph_node *
00156 cgraph_create_node (void)
00157 {
00158 struct cgraph_node *node;
00159
00160 node = ggc_alloc_cleared (sizeof (*node));
00161 node->next = cgraph_nodes;
00162 node->uid = cgraph_max_uid++;
00163 if (cgraph_nodes)
00164 cgraph_nodes->previous = node;
00165 node->previous = NULL;
00166 cgraph_nodes = node;
00167 cgraph_n_nodes++;
00168 return node;
00169 }
00170
00171
00172 struct cgraph_node *
00173 cgraph_node (tree decl)
00174 {
00175 struct cgraph_node key, *node, **slot;
00176
00177 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00178
00179 if (!cgraph_hash)
00180 cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
00181
00182 key.decl = decl;
00183
00184 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
00185
00186 if (*slot)
00187 return *slot;
00188
00189 node = cgraph_create_node ();
00190 node->decl = decl;
00191 *slot = node;
00192 if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
00193 {
00194 node->origin = cgraph_node (DECL_CONTEXT (decl));
00195 node->next_nested = node->origin->nested;
00196 node->origin->nested = node;
00197 }
00198 return node;
00199 }
00200
00201
00202
00203 static bool
00204 decl_assembler_name_equal (tree decl, tree asmname)
00205 {
00206 tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
00207
00208 if (decl_asmname == asmname)
00209 return true;
00210
00211
00212
00213
00214
00215
00216
00217 if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
00218 {
00219 const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
00220 size_t ulp_len = strlen (user_label_prefix);
00221
00222 if (ulp_len == 0)
00223 ;
00224 else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
00225 decl_str += ulp_len;
00226 else
00227 return false;
00228
00229 return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
00230 }
00231
00232 return false;
00233 }
00234
00235
00236
00237
00238
00239 struct cgraph_node *
00240 cgraph_node_for_asm (tree asmname)
00241 {
00242 struct cgraph_node *node;
00243
00244 for (node = cgraph_nodes; node ; node = node->next)
00245 if (decl_assembler_name_equal (node->decl, asmname))
00246 return node;
00247
00248 return NULL;
00249 }
00250
00251
00252 struct cgraph_edge *
00253 cgraph_edge (struct cgraph_node *node, tree call_expr)
00254 {
00255 struct cgraph_edge *e;
00256
00257
00258
00259
00260
00261
00262 for (e = node->callees; e; e= e->next_callee)
00263 if (e->call_expr == call_expr)
00264 break;
00265 return e;
00266 }
00267
00268
00269
00270 struct cgraph_edge *
00271 cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
00272 tree call_expr)
00273 {
00274 struct cgraph_edge *edge = ggc_alloc (sizeof (struct cgraph_edge));
00275 #ifdef ENABLE_CHECKING
00276 struct cgraph_edge *e;
00277
00278 for (e = caller->callees; e; e = e->next_callee)
00279 gcc_assert (e->call_expr != call_expr);
00280 #endif
00281
00282 gcc_assert (TREE_CODE (call_expr) == CALL_EXPR);
00283
00284 if (!DECL_SAVED_TREE (callee->decl))
00285 edge->inline_failed = N_("function body not available");
00286 else if (callee->local.redefined_extern_inline)
00287 edge->inline_failed = N_("redefined extern inline functions are not "
00288 "considered for inlining");
00289 else if (callee->local.inlinable)
00290 edge->inline_failed = N_("function not considered for inlining");
00291 else
00292 edge->inline_failed = N_("function not inlinable");
00293
00294 edge->aux = NULL;
00295
00296 edge->caller = caller;
00297 edge->callee = callee;
00298 edge->call_expr = call_expr;
00299 edge->prev_caller = NULL;
00300 edge->next_caller = callee->callers;
00301 if (callee->callers)
00302 callee->callers->prev_caller = edge;
00303 edge->prev_callee = NULL;
00304 edge->next_callee = caller->callees;
00305 if (caller->callees)
00306 caller->callees->prev_callee = edge;
00307 caller->callees = edge;
00308 callee->callers = edge;
00309 return edge;
00310 }
00311
00312
00313
00314 static inline void
00315 cgraph_edge_remove_callee (struct cgraph_edge *e)
00316 {
00317 if (e->prev_caller)
00318 e->prev_caller->next_caller = e->next_caller;
00319 if (e->next_caller)
00320 e->next_caller->prev_caller = e->prev_caller;
00321 if (!e->prev_caller)
00322 e->callee->callers = e->next_caller;
00323 }
00324
00325
00326
00327 static inline void
00328 cgraph_edge_remove_caller (struct cgraph_edge *e)
00329 {
00330 if (e->prev_callee)
00331 e->prev_callee->next_callee = e->next_callee;
00332 if (e->next_callee)
00333 e->next_callee->prev_callee = e->prev_callee;
00334 if (!e->prev_callee)
00335 e->caller->callees = e->next_callee;
00336 }
00337
00338
00339
00340 void
00341 cgraph_remove_edge (struct cgraph_edge *e)
00342 {
00343
00344 cgraph_edge_remove_callee (e);
00345
00346
00347 cgraph_edge_remove_caller (e);
00348 }
00349
00350
00351
00352
00353 void
00354 cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
00355 {
00356
00357 cgraph_edge_remove_callee (e);
00358
00359
00360 e->prev_caller = NULL;
00361 if (n->callers)
00362 n->callers->prev_caller = e;
00363 e->next_caller = n->callers;
00364 n->callers = e;
00365 e->callee = n;
00366 }
00367
00368
00369
00370 void
00371 cgraph_node_remove_callees (struct cgraph_node *node)
00372 {
00373 struct cgraph_edge *e;
00374
00375
00376
00377
00378 for (e = node->callees; e; e = e->next_callee)
00379 cgraph_edge_remove_callee (e);
00380 node->callees = NULL;
00381 }
00382
00383
00384
00385 static void
00386 cgraph_node_remove_callers (struct cgraph_node *node)
00387 {
00388 struct cgraph_edge *e;
00389
00390
00391
00392
00393 for (e = node->callers; e; e = e->next_caller)
00394 cgraph_edge_remove_caller (e);
00395 node->callers = NULL;
00396 }
00397
00398
00399
00400 void
00401 cgraph_remove_node (struct cgraph_node *node)
00402 {
00403 void **slot;
00404 bool check_dead = 1;
00405
00406 cgraph_node_remove_callers (node);
00407 cgraph_node_remove_callees (node);
00408 while (node->nested)
00409 cgraph_remove_node (node->nested);
00410 if (node->origin)
00411 {
00412 struct cgraph_node **node2 = &node->origin->nested;
00413
00414 while (*node2 != node)
00415 node2 = &(*node2)->next_nested;
00416 *node2 = node->next_nested;
00417 }
00418 if (node->previous)
00419 node->previous->next = node->next;
00420 else
00421 cgraph_nodes = node->next;
00422 if (node->next)
00423 node->next->previous = node->previous;
00424 slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
00425 if (*slot == node)
00426 {
00427 if (node->next_clone)
00428 *slot = node->next_clone;
00429 else
00430 {
00431 htab_clear_slot (cgraph_hash, slot);
00432 if (!dump_enabled_p (TDI_tree_all))
00433 {
00434 DECL_SAVED_TREE (node->decl) = NULL;
00435 DECL_STRUCT_FUNCTION (node->decl) = NULL;
00436 }
00437 check_dead = false;
00438 }
00439 }
00440 else
00441 {
00442 struct cgraph_node *n;
00443
00444 for (n = *slot; n->next_clone != node; n = n->next_clone)
00445 continue;
00446 n->next_clone = node->next_clone;
00447 }
00448
00449
00450
00451 if (check_dead && flag_unit_at_a_time)
00452 {
00453 struct cgraph_node *n;
00454
00455 for (n = *slot; n; n = n->next_clone)
00456 if (n->global.inlined_to
00457 || (!n->global.inlined_to
00458 && !TREE_ASM_WRITTEN (n->decl) && !DECL_EXTERNAL (n->decl)))
00459 break;
00460 if (!n && !dump_enabled_p (TDI_tree_all))
00461 {
00462 DECL_SAVED_TREE (node->decl) = NULL;
00463 DECL_STRUCT_FUNCTION (node->decl) = NULL;
00464 DECL_INITIAL (node->decl) = error_mark_node;
00465 }
00466 }
00467 cgraph_n_nodes--;
00468
00469 }
00470
00471
00472
00473 void
00474 cgraph_mark_reachable_node (struct cgraph_node *node)
00475 {
00476 if (!node->reachable && node->local.finalized)
00477 {
00478 notice_global_symbol (node->decl);
00479 node->reachable = 1;
00480 #ifdef KEY
00481
00482
00483
00484 if (flag_spin_file && gspin_invoked(node->decl))
00485 gs_set_flag_value (node->decl, GS_DECL_REACHABLE, 1);
00486 #endif
00487 gcc_assert (!cgraph_global_info_ready);
00488
00489 node->next_needed = cgraph_nodes_queue;
00490 cgraph_nodes_queue = node;
00491 }
00492 }
00493
00494
00495
00496
00497 void
00498 cgraph_mark_needed_node (struct cgraph_node *node)
00499 {
00500 node->needed = 1;
00501 #ifdef KEY
00502
00503 if (flag_spin_file && gspin_invoked(node->decl))
00504 gs_set_flag_value (node->decl, GS_DECL_NEEDED, 1);
00505 #endif
00506 cgraph_mark_reachable_node (node);
00507 }
00508
00509
00510
00511 struct cgraph_local_info *
00512 cgraph_local_info (tree decl)
00513 {
00514 struct cgraph_node *node;
00515
00516 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00517 node = cgraph_node (decl);
00518 return &node->local;
00519 }
00520
00521
00522
00523 struct cgraph_global_info *
00524 cgraph_global_info (tree decl)
00525 {
00526 struct cgraph_node *node;
00527
00528 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL && cgraph_global_info_ready);
00529 node = cgraph_node (decl);
00530 return &node->global;
00531 }
00532
00533
00534
00535 struct cgraph_rtl_info *
00536 cgraph_rtl_info (tree decl)
00537 {
00538 struct cgraph_node *node;
00539
00540 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00541 node = cgraph_node (decl);
00542 if (decl != current_function_decl
00543 && !TREE_ASM_WRITTEN (node->decl))
00544 return NULL;
00545 return &node->rtl;
00546 }
00547
00548
00549 const char *
00550 cgraph_node_name (struct cgraph_node *node)
00551 {
00552 return lang_hooks.decl_printable_name (node->decl, 2);
00553 }
00554
00555
00556 void
00557 dump_cgraph_node (FILE *f, struct cgraph_node *node)
00558 {
00559 struct cgraph_edge *edge;
00560 fprintf (f, "%s/%i:", cgraph_node_name (node), node->uid);
00561 if (node->global.inlined_to)
00562 fprintf (f, " (inline copy in %s/%i)",
00563 cgraph_node_name (node->global.inlined_to),
00564 node->global.inlined_to->uid);
00565 if (node->local.self_insns)
00566 fprintf (f, " %i insns", node->local.self_insns);
00567 if (node->global.insns && node->global.insns != node->local.self_insns)
00568 fprintf (f, " (%i after inlining)", node->global.insns);
00569 if (node->origin)
00570 fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
00571 if (node->needed)
00572 fprintf (f, " needed");
00573 else if (node->reachable)
00574 fprintf (f, " reachable");
00575 if (DECL_SAVED_TREE (node->decl))
00576 fprintf (f, " tree");
00577 if (node->output)
00578 fprintf (f, " output");
00579 if (node->local.local)
00580 fprintf (f, " local");
00581 if (node->local.disregard_inline_limits)
00582 fprintf (f, " always_inline");
00583 else if (node->local.inlinable)
00584 fprintf (f, " inlinable");
00585 if (TREE_ASM_WRITTEN (node->decl))
00586 fprintf (f, " asm_written");
00587
00588 fprintf (f, "\n called by: ");
00589 for (edge = node->callers; edge; edge = edge->next_caller)
00590 {
00591 fprintf (f, "%s/%i ", cgraph_node_name (edge->caller),
00592 edge->caller->uid);
00593 if (!edge->inline_failed)
00594 fprintf(f, "(inlined) ");
00595 }
00596
00597 fprintf (f, "\n calls: ");
00598 for (edge = node->callees; edge; edge = edge->next_callee)
00599 {
00600 fprintf (f, "%s/%i ", cgraph_node_name (edge->callee),
00601 edge->callee->uid);
00602 if (!edge->inline_failed)
00603 fprintf(f, "(inlined) ");
00604 }
00605 fprintf (f, "\n");
00606 }
00607
00608
00609
00610 void
00611 dump_cgraph (FILE *f)
00612 {
00613 struct cgraph_node *node;
00614
00615 fprintf (f, "callgraph:\n\n");
00616 for (node = cgraph_nodes; node; node = node->next)
00617 dump_cgraph_node (f, node);
00618 }
00619
00620
00621
00622 static hashval_t
00623 hash_varpool_node (const void *p)
00624 {
00625 const struct cgraph_varpool_node *n = p;
00626 return (hashval_t) DECL_UID (n->decl);
00627 }
00628
00629
00630
00631 static int
00632 eq_varpool_node (const void *p1, const void *p2)
00633 {
00634 const struct cgraph_varpool_node *n1 = p1, *n2 = p2;
00635 return DECL_UID (n1->decl) == DECL_UID (n2->decl);
00636 }
00637
00638
00639 struct cgraph_varpool_node *
00640 cgraph_varpool_node (tree decl)
00641 {
00642 struct cgraph_varpool_node key, *node, **slot;
00643
00644 gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
00645
00646 if (!cgraph_varpool_hash)
00647 cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node,
00648 eq_varpool_node, NULL);
00649 key.decl = decl;
00650 slot = (struct cgraph_varpool_node **)
00651 htab_find_slot (cgraph_varpool_hash, &key, INSERT);
00652 if (*slot)
00653 return *slot;
00654 node = ggc_alloc_cleared (sizeof (*node));
00655 node->decl = decl;
00656 node->next = cgraph_varpool_nodes;
00657 cgraph_varpool_nodes = node;
00658 *slot = node;
00659 return node;
00660 }
00661
00662 struct cgraph_varpool_node *
00663 cgraph_varpool_node_for_asm (tree asmname)
00664 {
00665 struct cgraph_varpool_node *node;
00666
00667 for (node = cgraph_varpool_nodes; node ; node = node->next)
00668 if (decl_assembler_name_equal (node->decl, asmname))
00669 return node;
00670
00671 return NULL;
00672 }
00673
00674
00675 void
00676 change_decl_assembler_name (tree decl, tree name)
00677 {
00678 if (!DECL_ASSEMBLER_NAME_SET_P (decl))
00679 {
00680 SET_DECL_ASSEMBLER_NAME (decl, name);
00681 return;
00682 }
00683 if (name == DECL_ASSEMBLER_NAME (decl))
00684 return;
00685
00686 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
00687 && DECL_RTL_SET_P (decl))
00688 warning ("%D renamed after being referenced in assembly", decl);
00689
00690 SET_DECL_ASSEMBLER_NAME (decl, name);
00691 }
00692
00693
00694
00695 void
00696 cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
00697 {
00698 if (!node->needed && node->finalized)
00699 {
00700 node->next_needed = cgraph_varpool_nodes_queue;
00701 cgraph_varpool_nodes_queue = node;
00702 notice_global_symbol (node->decl);
00703 }
00704 node->needed = 1;
00705 }
00706
00707 void
00708 cgraph_varpool_finalize_decl (tree decl)
00709 {
00710 struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
00711
00712
00713
00714
00715
00716 if (node->finalized)
00717 return;
00718 if (node->needed)
00719 {
00720 node->next_needed = cgraph_varpool_nodes_queue;
00721 cgraph_varpool_nodes_queue = node;
00722 notice_global_symbol (decl);
00723 }
00724 node->finalized = true;
00725
00726 if (
00727
00728 (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
00729
00730
00731
00732 || (DECL_ASSEMBLER_NAME_SET_P (decl)
00733 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
00734 {
00735 cgraph_varpool_mark_needed_node (node);
00736 }
00737 }
00738
00739 bool
00740 cgraph_varpool_assemble_pending_decls (void)
00741 {
00742 bool changed = false;
00743
00744 while (cgraph_varpool_nodes_queue)
00745 {
00746 struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
00747 tree decl = node->decl;
00748
00749 cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
00750 if (!TREE_ASM_WRITTEN (decl) && !node->alias)
00751 {
00752 assemble_variable (decl, 0, 1, 0);
00753 changed = true;
00754 }
00755 node->next_needed = NULL;
00756 }
00757 return changed;
00758 }
00759
00760
00761 bool
00762 cgraph_function_possibly_inlined_p (tree decl)
00763 {
00764 if (!cgraph_global_info_ready)
00765 return (DECL_INLINE (decl) && !flag_really_no_inline);
00766 return DECL_POSSIBLY_INLINED (decl);
00767 }
00768
00769
00770 struct cgraph_edge *
00771 cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, tree call_expr)
00772 {
00773 struct cgraph_edge *new = cgraph_create_edge (n, e->callee, call_expr);
00774
00775 new->inline_failed = e->inline_failed;
00776 return new;
00777 }
00778
00779
00780 struct cgraph_node *
00781 cgraph_clone_node (struct cgraph_node *n)
00782 {
00783 struct cgraph_node *new = cgraph_create_node ();
00784 struct cgraph_edge *e;
00785
00786 new->decl = n->decl;
00787 new->origin = n->origin;
00788 if (new->origin)
00789 {
00790 new->next_nested = new->origin->nested;
00791 new->origin->nested = new;
00792 }
00793 new->analyzed = n->analyzed;
00794 new->local = n->local;
00795 new->global = n->global;
00796 new->rtl = n->rtl;
00797
00798 for (e = n->callees;e; e=e->next_callee)
00799 cgraph_clone_edge (e, new, e->call_expr);
00800
00801 new->next_clone = n->next_clone;
00802 n->next_clone = new;
00803
00804 return new;
00805 }
00806
00807
00808 void
00809 cgraph_unnest_node (struct cgraph_node *node)
00810 {
00811 struct cgraph_node **node2 = &node->origin->nested;
00812 gcc_assert (node->origin);
00813
00814 while (*node2 != node)
00815 node2 = &(*node2)->next_nested;
00816 *node2 = node->next_nested;
00817 node->origin = NULL;
00818 }
00819 #include "gt-cgraph.h"