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 "tree-inline.h"
00088 #include "langhooks.h"
00089 #include "hashtab.h"
00090 #include "toplev.h"
00091 #include "flags.h"
00092 #include "ggc.h"
00093 #include "debug.h"
00094 #include "target.h"
00095 #include "basic-block.h"
00096 #include "cgraph.h"
00097 #include "varray.h"
00098 #include "output.h"
00099 #include "intl.h"
00100 #include "tree-gimple.h"
00101 #include "tree-dump.h"
00102
00103 static void cgraph_node_remove_callers (struct cgraph_node *node);
00104 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
00105 static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
00106
00107
00108 static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
00109
00110
00111 struct cgraph_node *cgraph_nodes;
00112
00113
00114 struct cgraph_node *cgraph_nodes_queue;
00115
00116
00117
00118
00119 struct cgraph_node *cgraph_expand_queue;
00120
00121
00122 int cgraph_n_nodes;
00123
00124
00125 int cgraph_max_uid;
00126
00127
00128 bool cgraph_global_info_ready = false;
00129
00130
00131 bool cgraph_function_flags_ready = false;
00132
00133
00134 static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
00135
00136
00137 struct cgraph_varpool_node *cgraph_varpool_nodes_queue, *cgraph_varpool_first_unanalyzed_node;
00138
00139
00140 struct cgraph_varpool_node *cgraph_varpool_nodes;
00141
00142
00143 struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
00144
00145
00146 struct cgraph_asm_node *cgraph_asm_nodes;
00147
00148
00149 static GTY(()) struct cgraph_asm_node *cgraph_asm_last_node;
00150
00151
00152
00153
00154 int cgraph_order;
00155
00156 static hashval_t hash_node (const void *);
00157 static int eq_node (const void *, const void *);
00158
00159
00160
00161 static hashval_t
00162 hash_node (const void *p)
00163 {
00164 const struct cgraph_node *n = (const struct cgraph_node *) p;
00165 return (hashval_t) DECL_UID (n->decl);
00166 }
00167
00168
00169
00170 static int
00171 eq_node (const void *p1, const void *p2)
00172 {
00173 const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
00174 const struct cgraph_node *n2 = (const struct cgraph_node *) p2;
00175 return DECL_UID (n1->decl) == DECL_UID (n2->decl);
00176 }
00177
00178
00179 static struct cgraph_node *
00180 cgraph_create_node (void)
00181 {
00182 struct cgraph_node *node;
00183
00184 node = GGC_CNEW (struct cgraph_node);
00185 node->next = cgraph_nodes;
00186 node->uid = cgraph_max_uid++;
00187 node->order = cgraph_order++;
00188 if (cgraph_nodes)
00189 cgraph_nodes->previous = node;
00190 node->previous = NULL;
00191 node->global.estimated_growth = INT_MIN;
00192 cgraph_nodes = node;
00193 cgraph_n_nodes++;
00194 return node;
00195 }
00196
00197
00198 struct cgraph_node *
00199 cgraph_node (tree decl)
00200 {
00201 struct cgraph_node key, *node, **slot;
00202
00203 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00204
00205 if (!cgraph_hash)
00206 cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
00207
00208 key.decl = decl;
00209
00210 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
00211
00212 if (*slot)
00213 {
00214 node = *slot;
00215 if (!node->master_clone)
00216 node->master_clone = node;
00217 return node;
00218 }
00219
00220 node = cgraph_create_node ();
00221 node->decl = decl;
00222 *slot = node;
00223 if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
00224 {
00225 node->origin = cgraph_node (DECL_CONTEXT (decl));
00226 node->next_nested = node->origin->nested;
00227 node->origin->nested = node;
00228 node->master_clone = node;
00229 }
00230 return node;
00231 }
00232
00233
00234
00235 void
00236 cgraph_insert_node_to_hashtable (struct cgraph_node *node)
00237 {
00238 struct cgraph_node **slot;
00239
00240 slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
00241
00242 gcc_assert (!*slot);
00243 *slot = node;
00244 }
00245
00246
00247
00248 static bool
00249 decl_assembler_name_equal (tree decl, tree asmname)
00250 {
00251 tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
00252
00253 if (decl_asmname == asmname)
00254 return true;
00255
00256
00257
00258
00259
00260
00261
00262 if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
00263 {
00264 const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
00265 size_t ulp_len = strlen (user_label_prefix);
00266
00267 if (ulp_len == 0)
00268 ;
00269 else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
00270 decl_str += ulp_len;
00271 else
00272 return false;
00273
00274 return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
00275 }
00276
00277 return false;
00278 }
00279
00280
00281
00282
00283
00284 struct cgraph_node *
00285 cgraph_node_for_asm (tree asmname)
00286 {
00287 struct cgraph_node *node;
00288
00289 for (node = cgraph_nodes; node ; node = node->next)
00290 if (decl_assembler_name_equal (node->decl, asmname))
00291 return node;
00292
00293 return NULL;
00294 }
00295
00296
00297
00298 static hashval_t
00299 edge_hash (const void *x)
00300 {
00301 return htab_hash_pointer (((struct cgraph_edge *) x)->call_stmt);
00302 }
00303
00304
00305
00306 static int
00307 edge_eq (const void *x, const void *y)
00308 {
00309 return ((struct cgraph_edge *) x)->call_stmt == y;
00310 }
00311
00312
00313 struct cgraph_edge *
00314 cgraph_edge (struct cgraph_node *node, tree call_stmt)
00315 {
00316 struct cgraph_edge *e, *e2;
00317 int n = 0;
00318
00319 if (node->call_site_hash)
00320 return htab_find_with_hash (node->call_site_hash, call_stmt,
00321 htab_hash_pointer (call_stmt));
00322
00323
00324
00325
00326
00327
00328 for (e = node->callees; e; e= e->next_callee)
00329 {
00330 if (e->call_stmt == call_stmt)
00331 break;
00332 n++;
00333 }
00334 if (n > 100)
00335 {
00336 node->call_site_hash = htab_create_ggc (120, edge_hash, edge_eq, NULL);
00337 for (e2 = node->callees; e2; e2 = e2->next_callee)
00338 {
00339 void **slot;
00340 slot = htab_find_slot_with_hash (node->call_site_hash,
00341 e2->call_stmt,
00342 htab_hash_pointer (e2->call_stmt),
00343 INSERT);
00344 gcc_assert (!*slot);
00345 *slot = e2;
00346 }
00347 }
00348 return e;
00349 }
00350
00351
00352 void
00353 cgraph_set_call_stmt (struct cgraph_edge *e, tree new_stmt)
00354 {
00355 if (e->caller->call_site_hash)
00356 {
00357 htab_remove_elt_with_hash (e->caller->call_site_hash,
00358 e->call_stmt,
00359 htab_hash_pointer (e->call_stmt));
00360 }
00361 e->call_stmt = new_stmt;
00362 if (e->caller->call_site_hash)
00363 {
00364 void **slot;
00365 slot = htab_find_slot_with_hash (e->caller->call_site_hash,
00366 e->call_stmt,
00367 htab_hash_pointer
00368 (e->call_stmt), INSERT);
00369 gcc_assert (!*slot);
00370 *slot = e;
00371 }
00372 }
00373
00374
00375
00376 struct cgraph_edge *
00377 cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
00378 tree call_stmt, gcov_type count, int nest)
00379 {
00380 struct cgraph_edge *edge = GGC_NEW (struct cgraph_edge);
00381 #ifdef ENABLE_CHECKING
00382 struct cgraph_edge *e;
00383
00384 for (e = caller->callees; e; e = e->next_callee)
00385 gcc_assert (e->call_stmt != call_stmt);
00386 #endif
00387
00388 gcc_assert (get_call_expr_in (call_stmt));
00389
00390 if (!DECL_SAVED_TREE (callee->decl))
00391 edge->inline_failed = N_("function body not available");
00392 else if (callee->local.redefined_extern_inline)
00393 edge->inline_failed = N_("redefined extern inline functions are not "
00394 "considered for inlining");
00395 else if (callee->local.inlinable)
00396 edge->inline_failed = N_("function not considered for inlining");
00397 else
00398 edge->inline_failed = N_("function not inlinable");
00399
00400 edge->aux = NULL;
00401
00402 edge->caller = caller;
00403 edge->callee = callee;
00404 edge->call_stmt = call_stmt;
00405 edge->prev_caller = NULL;
00406 edge->next_caller = callee->callers;
00407 if (callee->callers)
00408 callee->callers->prev_caller = edge;
00409 edge->prev_callee = NULL;
00410 edge->next_callee = caller->callees;
00411 if (caller->callees)
00412 caller->callees->prev_callee = edge;
00413 caller->callees = edge;
00414 callee->callers = edge;
00415 edge->count = count;
00416 edge->loop_nest = nest;
00417 if (caller->call_site_hash)
00418 {
00419 void **slot;
00420 slot = htab_find_slot_with_hash (caller->call_site_hash,
00421 edge->call_stmt,
00422 htab_hash_pointer
00423 (edge->call_stmt),
00424 INSERT);
00425 gcc_assert (!*slot);
00426 *slot = edge;
00427 }
00428 return edge;
00429 }
00430
00431
00432
00433 static inline void
00434 cgraph_edge_remove_callee (struct cgraph_edge *e)
00435 {
00436 if (e->prev_caller)
00437 e->prev_caller->next_caller = e->next_caller;
00438 if (e->next_caller)
00439 e->next_caller->prev_caller = e->prev_caller;
00440 if (!e->prev_caller)
00441 e->callee->callers = e->next_caller;
00442 }
00443
00444
00445
00446 static inline void
00447 cgraph_edge_remove_caller (struct cgraph_edge *e)
00448 {
00449 if (e->prev_callee)
00450 e->prev_callee->next_callee = e->next_callee;
00451 if (e->next_callee)
00452 e->next_callee->prev_callee = e->prev_callee;
00453 if (!e->prev_callee)
00454 e->caller->callees = e->next_callee;
00455 if (e->caller->call_site_hash)
00456 htab_remove_elt_with_hash (e->caller->call_site_hash,
00457 e->call_stmt,
00458 htab_hash_pointer (e->call_stmt));
00459 }
00460
00461
00462
00463 void
00464 cgraph_remove_edge (struct cgraph_edge *e)
00465 {
00466
00467 cgraph_edge_remove_callee (e);
00468
00469
00470 cgraph_edge_remove_caller (e);
00471 }
00472
00473
00474
00475
00476 void
00477 cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
00478 {
00479
00480 cgraph_edge_remove_callee (e);
00481
00482
00483 e->prev_caller = NULL;
00484 if (n->callers)
00485 n->callers->prev_caller = e;
00486 e->next_caller = n->callers;
00487 n->callers = e;
00488 e->callee = n;
00489 }
00490
00491
00492
00493 void
00494 cgraph_node_remove_callees (struct cgraph_node *node)
00495 {
00496 struct cgraph_edge *e;
00497
00498
00499
00500
00501 for (e = node->callees; e; e = e->next_callee)
00502 cgraph_edge_remove_callee (e);
00503 node->callees = NULL;
00504 if (node->call_site_hash)
00505 {
00506 htab_delete (node->call_site_hash);
00507 node->call_site_hash = NULL;
00508 }
00509 }
00510
00511
00512
00513 static void
00514 cgraph_node_remove_callers (struct cgraph_node *node)
00515 {
00516 struct cgraph_edge *e;
00517
00518
00519
00520
00521 for (e = node->callers; e; e = e->next_caller)
00522 cgraph_edge_remove_caller (e);
00523 node->callers = NULL;
00524 }
00525
00526
00527
00528 void
00529 cgraph_remove_node (struct cgraph_node *node)
00530 {
00531 void **slot;
00532 bool kill_body = false;
00533
00534 cgraph_node_remove_callers (node);
00535 cgraph_node_remove_callees (node);
00536
00537
00538 node->needed = node->reachable = false;
00539 while (node->nested)
00540 cgraph_remove_node (node->nested);
00541 if (node->origin)
00542 {
00543 struct cgraph_node **node2 = &node->origin->nested;
00544
00545 while (*node2 != node)
00546 node2 = &(*node2)->next_nested;
00547 *node2 = node->next_nested;
00548 }
00549 if (node->previous)
00550 node->previous->next = node->next;
00551 else
00552 cgraph_nodes = node->next;
00553 if (node->next)
00554 node->next->previous = node->previous;
00555 node->next = NULL;
00556 node->previous = NULL;
00557 slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
00558 if (*slot == node)
00559 {
00560 if (node->next_clone)
00561 {
00562 struct cgraph_node *new_node = node->next_clone;
00563 struct cgraph_node *n;
00564
00565
00566 for (n = new_node; n; n = n->next_clone)
00567 n->master_clone = new_node;
00568
00569 *slot = new_node;
00570 node->next_clone->prev_clone = NULL;
00571 }
00572 else
00573 {
00574 htab_clear_slot (cgraph_hash, slot);
00575 kill_body = true;
00576 }
00577 }
00578 else
00579 {
00580 node->prev_clone->next_clone = node->next_clone;
00581 if (node->next_clone)
00582 node->next_clone->prev_clone = node->prev_clone;
00583 }
00584
00585
00586
00587
00588
00589 if (!kill_body && *slot)
00590 {
00591 struct cgraph_node *n = (struct cgraph_node *) *slot;
00592 if (!n->next_clone && !n->global.inlined_to
00593 && (cgraph_global_info_ready
00594 && (TREE_ASM_WRITTEN (n->decl) || DECL_EXTERNAL (n->decl))))
00595 kill_body = true;
00596 }
00597
00598 if (kill_body && flag_unit_at_a_time)
00599 {
00600 DECL_SAVED_TREE (node->decl) = NULL;
00601 DECL_STRUCT_FUNCTION (node->decl) = NULL;
00602 DECL_INITIAL (node->decl) = error_mark_node;
00603 }
00604 node->decl = NULL;
00605 if (node->call_site_hash)
00606 {
00607 htab_delete (node->call_site_hash);
00608 node->call_site_hash = NULL;
00609 }
00610 cgraph_n_nodes--;
00611
00612 }
00613
00614
00615
00616 void
00617 cgraph_mark_reachable_node (struct cgraph_node *node)
00618 {
00619 if (!node->reachable && node->local.finalized)
00620 {
00621 notice_global_symbol (node->decl);
00622 node->reachable = 1;
00623 gcc_assert (!cgraph_global_info_ready);
00624
00625 node->next_needed = cgraph_nodes_queue;
00626 cgraph_nodes_queue = node;
00627 }
00628 }
00629
00630
00631
00632
00633 void
00634 cgraph_mark_needed_node (struct cgraph_node *node)
00635 {
00636 node->needed = 1;
00637 cgraph_mark_reachable_node (node);
00638 }
00639
00640
00641
00642 struct cgraph_local_info *
00643 cgraph_local_info (tree decl)
00644 {
00645 struct cgraph_node *node;
00646
00647 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00648 node = cgraph_node (decl);
00649 return &node->local;
00650 }
00651
00652
00653
00654 struct cgraph_global_info *
00655 cgraph_global_info (tree decl)
00656 {
00657 struct cgraph_node *node;
00658
00659 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL && cgraph_global_info_ready);
00660 node = cgraph_node (decl);
00661 return &node->global;
00662 }
00663
00664
00665
00666 struct cgraph_rtl_info *
00667 cgraph_rtl_info (tree decl)
00668 {
00669 struct cgraph_node *node;
00670
00671 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
00672 node = cgraph_node (decl);
00673 if (decl != current_function_decl
00674 && !TREE_ASM_WRITTEN (node->decl))
00675 return NULL;
00676 return &node->rtl;
00677 }
00678
00679
00680 const char *
00681 cgraph_node_name (struct cgraph_node *node)
00682 {
00683 return lang_hooks.decl_printable_name (node->decl, 2);
00684 }
00685
00686
00687 static const char *
00688 cgraph_varpool_node_name (struct cgraph_varpool_node *node)
00689 {
00690 return lang_hooks.decl_printable_name (node->decl, 2);
00691 }
00692
00693
00694 static const char * const availability_names[] =
00695 {"unset", "not_available", "overwrittable", "available", "local"};
00696
00697
00698 void
00699 dump_cgraph_node (FILE *f, struct cgraph_node *node)
00700 {
00701 struct cgraph_edge *edge;
00702 fprintf (f, "%s/%i:", cgraph_node_name (node), node->uid);
00703 if (node->global.inlined_to)
00704 fprintf (f, " (inline copy in %s/%i)",
00705 cgraph_node_name (node->global.inlined_to),
00706 node->global.inlined_to->uid);
00707 if (cgraph_function_flags_ready)
00708 fprintf (f, " availability:%s",
00709 availability_names [cgraph_function_body_availability (node)]);
00710 if (node->master_clone && node->master_clone->uid != node->uid)
00711 fprintf (f, "(%i)", node->master_clone->uid);
00712 if (node->count)
00713 fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
00714 (HOST_WIDEST_INT)node->count);
00715 if (node->local.self_insns)
00716 fprintf (f, " %i insns", node->local.self_insns);
00717 if (node->global.insns && node->global.insns != node->local.self_insns)
00718 fprintf (f, " (%i after inlining)", node->global.insns);
00719 if (node->origin)
00720 fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
00721 if (node->needed)
00722 fprintf (f, " needed");
00723 else if (node->reachable)
00724 fprintf (f, " reachable");
00725 if (DECL_SAVED_TREE (node->decl))
00726 fprintf (f, " tree");
00727 if (node->output)
00728 fprintf (f, " output");
00729 if (node->local.local)
00730 fprintf (f, " local");
00731 if (node->local.externally_visible)
00732 fprintf (f, " externally_visible");
00733 if (node->local.finalized)
00734 fprintf (f, " finalized");
00735 if (node->local.disregard_inline_limits)
00736 fprintf (f, " always_inline");
00737 else if (node->local.inlinable)
00738 fprintf (f, " inlinable");
00739 if (node->local.redefined_extern_inline)
00740 fprintf (f, " redefined_extern_inline");
00741 if (TREE_ASM_WRITTEN (node->decl))
00742 fprintf (f, " asm_written");
00743
00744 fprintf (f, "\n called by: ");
00745 for (edge = node->callers; edge; edge = edge->next_caller)
00746 {
00747 fprintf (f, "%s/%i ", cgraph_node_name (edge->caller),
00748 edge->caller->uid);
00749 if (edge->count)
00750 fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
00751 (HOST_WIDEST_INT)edge->count);
00752 if (!edge->inline_failed)
00753 fprintf(f, "(inlined) ");
00754 }
00755
00756 fprintf (f, "\n calls: ");
00757 for (edge = node->callees; edge; edge = edge->next_callee)
00758 {
00759 fprintf (f, "%s/%i ", cgraph_node_name (edge->callee),
00760 edge->callee->uid);
00761 if (!edge->inline_failed)
00762 fprintf(f, "(inlined) ");
00763 if (edge->count)
00764 fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ",
00765 (HOST_WIDEST_INT)edge->count);
00766 if (edge->loop_nest)
00767 fprintf (f, "(nested in %i loops) ", edge->loop_nest);
00768 }
00769 fprintf (f, "\n");
00770 }
00771
00772
00773
00774 void
00775 dump_cgraph (FILE *f)
00776 {
00777 struct cgraph_node *node;
00778
00779 fprintf (f, "callgraph:\n\n");
00780 for (node = cgraph_nodes; node; node = node->next)
00781 dump_cgraph_node (f, node);
00782 }
00783
00784
00785 void
00786 dump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
00787 {
00788 fprintf (f, "%s:", cgraph_varpool_node_name (node));
00789 fprintf (f, " availability:%s",
00790 cgraph_function_flags_ready
00791 ? availability_names[cgraph_variable_initializer_availability (node)]
00792 : "not-ready");
00793 if (DECL_INITIAL (node->decl))
00794 fprintf (f, " initialized");
00795 if (node->needed)
00796 fprintf (f, " needed");
00797 if (node->analyzed)
00798 fprintf (f, " analyzed");
00799 if (node->finalized)
00800 fprintf (f, " finalized");
00801 if (node->output)
00802 fprintf (f, " output");
00803 if (node->externally_visible)
00804 fprintf (f, " externally_visible");
00805 fprintf (f, "\n");
00806 }
00807
00808
00809
00810 void
00811 dump_varpool (FILE *f)
00812 {
00813 struct cgraph_varpool_node *node;
00814
00815 fprintf (f, "variable pool:\n\n");
00816 for (node = cgraph_varpool_nodes; node; node = node->next_needed)
00817 dump_cgraph_varpool_node (f, node);
00818 }
00819
00820
00821
00822 static hashval_t
00823 hash_varpool_node (const void *p)
00824 {
00825 const struct cgraph_varpool_node *n = (const struct cgraph_varpool_node *) p;
00826 return (hashval_t) DECL_UID (n->decl);
00827 }
00828
00829
00830
00831 static int
00832 eq_varpool_node (const void *p1, const void *p2)
00833 {
00834 const struct cgraph_varpool_node *n1 =
00835 (const struct cgraph_varpool_node *) p1;
00836 const struct cgraph_varpool_node *n2 =
00837 (const struct cgraph_varpool_node *) p2;
00838 return DECL_UID (n1->decl) == DECL_UID (n2->decl);
00839 }
00840
00841
00842 struct cgraph_varpool_node *
00843 cgraph_varpool_node (tree decl)
00844 {
00845 struct cgraph_varpool_node key, *node, **slot;
00846
00847 gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL);
00848
00849 if (!cgraph_varpool_hash)
00850 cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node,
00851 eq_varpool_node, NULL);
00852 key.decl = decl;
00853 slot = (struct cgraph_varpool_node **)
00854 htab_find_slot (cgraph_varpool_hash, &key, INSERT);
00855 if (*slot)
00856 return *slot;
00857 node = GGC_CNEW (struct cgraph_varpool_node);
00858 node->decl = decl;
00859 node->order = cgraph_order++;
00860 node->next = cgraph_varpool_nodes;
00861 cgraph_varpool_nodes = node;
00862 *slot = node;
00863 return node;
00864 }
00865
00866 struct cgraph_varpool_node *
00867 cgraph_varpool_node_for_asm (tree asmname)
00868 {
00869 struct cgraph_varpool_node *node;
00870
00871 for (node = cgraph_varpool_nodes; node ; node = node->next)
00872 if (decl_assembler_name_equal (node->decl, asmname))
00873 return node;
00874
00875 return NULL;
00876 }
00877
00878
00879 void
00880 change_decl_assembler_name (tree decl, tree name)
00881 {
00882 if (!DECL_ASSEMBLER_NAME_SET_P (decl))
00883 {
00884 SET_DECL_ASSEMBLER_NAME (decl, name);
00885 return;
00886 }
00887 if (name == DECL_ASSEMBLER_NAME (decl))
00888 return;
00889
00890 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
00891 && DECL_RTL_SET_P (decl))
00892 warning (0, "%D renamed after being referenced in assembly", decl);
00893
00894 SET_DECL_ASSEMBLER_NAME (decl, name);
00895 }
00896
00897
00898
00899 void
00900 cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *node)
00901 {
00902 if (cgraph_varpool_last_needed_node)
00903 cgraph_varpool_last_needed_node->next_needed = node;
00904 cgraph_varpool_last_needed_node = node;
00905 node->next_needed = NULL;
00906 if (!cgraph_varpool_nodes_queue)
00907 cgraph_varpool_nodes_queue = node;
00908 if (!cgraph_varpool_first_unanalyzed_node)
00909 cgraph_varpool_first_unanalyzed_node = node;
00910 notice_global_symbol (node->decl);
00911 }
00912
00913
00914 void
00915 cgraph_varpool_reset_queue (void)
00916 {
00917 cgraph_varpool_last_needed_node = NULL;
00918 cgraph_varpool_nodes_queue = NULL;
00919 cgraph_varpool_first_unanalyzed_node = NULL;
00920 }
00921
00922
00923
00924 void
00925 cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
00926 {
00927 #ifdef KEY
00928 tree decl = node->decl;
00929 #endif
00930
00931 if (!node->needed && node->finalized
00932 && !TREE_ASM_WRITTEN (node->decl))
00933 cgraph_varpool_enqueue_needed_node (node);
00934 node->needed = 1;
00935
00936 #ifdef KEY
00937 if (gspin_invoked(decl) && TREE_CODE(decl) == VAR_DECL)
00938 gs_set_flag_value (decl, GS_DECL_NEEDED, 1);
00939 #endif
00940 }
00941
00942
00943
00944
00945
00946
00947 bool
00948 decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
00949 {
00950
00951 if (node->externally_visible)
00952 return true;
00953 if (!flag_unit_at_a_time
00954 && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
00955 return true;
00956
00957
00958
00959
00960 if (DECL_ASSEMBLER_NAME_SET_P (decl)
00961 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
00962 return true;
00963
00964
00965
00966 if (node->needed)
00967 return true;
00968
00969
00970
00971 if (TREE_PUBLIC (decl) && !flag_whole_program && !DECL_COMDAT (decl)
00972 && !DECL_EXTERNAL (decl))
00973 return true;
00974
00975
00976
00977 if (flag_unit_at_a_time && flag_toplevel_reorder)
00978 return false;
00979
00980
00981 if (DECL_COMDAT (decl))
00982 return false;
00983 return true;
00984 }
00985
00986 void
00987 cgraph_varpool_finalize_decl (tree decl)
00988 {
00989 struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
00990
00991
00992
00993
00994
00995 if (node->finalized)
00996 {
00997 if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
00998 cgraph_varpool_assemble_pending_decls ();
00999 return;
01000 }
01001 if (node->needed)
01002 cgraph_varpool_enqueue_needed_node (node);
01003 node->finalized = true;
01004
01005 if (decide_is_variable_needed (node, decl))
01006 cgraph_varpool_mark_needed_node (node);
01007
01008
01009
01010 else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
01011 cgraph_varpool_mark_needed_node (node);
01012 if (cgraph_global_info_ready || (!flag_unit_at_a_time && !flag_openmp))
01013 cgraph_varpool_assemble_pending_decls ();
01014 }
01015
01016
01017
01018 struct cgraph_asm_node *
01019 cgraph_add_asm_node (tree asm_str)
01020 {
01021 struct cgraph_asm_node *node;
01022
01023 node = GGC_CNEW (struct cgraph_asm_node);
01024 node->asm_str = asm_str;
01025 node->order = cgraph_order++;
01026 node->next = NULL;
01027 if (cgraph_asm_nodes == NULL)
01028 cgraph_asm_nodes = node;
01029 else
01030 cgraph_asm_last_node->next = node;
01031 cgraph_asm_last_node = node;
01032 return node;
01033 }
01034
01035
01036 bool
01037 cgraph_function_possibly_inlined_p (tree decl)
01038 {
01039 if (!cgraph_global_info_ready)
01040 return (DECL_INLINE (decl) && !flag_really_no_inline);
01041 return DECL_POSSIBLY_INLINED (decl);
01042 }
01043
01044
01045 struct cgraph_edge *
01046 cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
01047 tree call_stmt, gcov_type count_scale, int loop_nest,
01048 bool update_original)
01049 {
01050 struct cgraph_edge *new;
01051
01052 new = cgraph_create_edge (n, e->callee, call_stmt,
01053 e->count * count_scale / REG_BR_PROB_BASE,
01054 e->loop_nest + loop_nest);
01055
01056 new->inline_failed = e->inline_failed;
01057 if (update_original)
01058 {
01059 e->count -= new->count;
01060 if (e->count < 0)
01061 e->count = 0;
01062 }
01063 return new;
01064 }
01065
01066
01067
01068
01069
01070
01071
01072 struct cgraph_node *
01073 cgraph_clone_node (struct cgraph_node *n, gcov_type count, int loop_nest,
01074 bool update_original)
01075 {
01076 struct cgraph_node *new = cgraph_create_node ();
01077 struct cgraph_edge *e;
01078 gcov_type count_scale;
01079
01080 new->decl = n->decl;
01081 new->origin = n->origin;
01082 if (new->origin)
01083 {
01084 new->next_nested = new->origin->nested;
01085 new->origin->nested = new;
01086 }
01087 new->analyzed = n->analyzed;
01088 new->local = n->local;
01089 new->global = n->global;
01090 new->rtl = n->rtl;
01091 new->master_clone = n->master_clone;
01092 new->count = count;
01093 if (n->count)
01094 count_scale = new->count * REG_BR_PROB_BASE / n->count;
01095 else
01096 count_scale = 0;
01097 if (update_original)
01098 {
01099 n->count -= count;
01100 if (n->count < 0)
01101 n->count = 0;
01102 }
01103
01104 for (e = n->callees;e; e=e->next_callee)
01105 cgraph_clone_edge (e, new, e->call_stmt, count_scale, loop_nest,
01106 update_original);
01107
01108 new->next_clone = n->next_clone;
01109 new->prev_clone = n;
01110 n->next_clone = new;
01111 if (new->next_clone)
01112 new->next_clone->prev_clone = new;
01113
01114 return new;
01115 }
01116
01117
01118
01119 bool
01120 cgraph_is_master_clone (struct cgraph_node *n)
01121 {
01122 return (n == cgraph_master_clone (n));
01123 }
01124
01125 struct cgraph_node *
01126 cgraph_master_clone (struct cgraph_node *n)
01127 {
01128 enum availability avail = cgraph_function_body_availability (n);
01129
01130 if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
01131 return NULL;
01132
01133 if (!n->master_clone)
01134 n->master_clone = cgraph_node (n->decl);
01135
01136 return n->master_clone;
01137 }
01138
01139
01140 void
01141 cgraph_unnest_node (struct cgraph_node *node)
01142 {
01143 struct cgraph_node **node2 = &node->origin->nested;
01144 gcc_assert (node->origin);
01145
01146 while (*node2 != node)
01147 node2 = &(*node2)->next_nested;
01148 *node2 = node->next_nested;
01149 node->origin = NULL;
01150 }
01151
01152
01153
01154 enum availability
01155 cgraph_function_body_availability (struct cgraph_node *node)
01156 {
01157 enum availability avail;
01158 gcc_assert (cgraph_function_flags_ready);
01159 if (!node->analyzed)
01160 avail = AVAIL_NOT_AVAILABLE;
01161 else if (node->local.local)
01162 avail = AVAIL_LOCAL;
01163 else if (node->local.externally_visible)
01164 avail = AVAIL_AVAILABLE;
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 else if (!(*targetm.binds_local_p) (node->decl)
01182 && !DECL_COMDAT (node->decl) && !DECL_EXTERNAL (node->decl))
01183 avail = AVAIL_OVERWRITABLE;
01184 else avail = AVAIL_AVAILABLE;
01185
01186 return avail;
01187 }
01188
01189
01190
01191 enum availability
01192 cgraph_variable_initializer_availability (struct cgraph_varpool_node *node)
01193 {
01194 gcc_assert (cgraph_function_flags_ready);
01195 if (!node->finalized)
01196 return AVAIL_NOT_AVAILABLE;
01197 if (!TREE_PUBLIC (node->decl))
01198 return AVAIL_AVAILABLE;
01199
01200
01201
01202 if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl))
01203 return AVAIL_OVERWRITABLE;
01204 return AVAIL_AVAILABLE;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219 void
01220 cgraph_add_new_function (tree fndecl)
01221 {
01222 struct cgraph_node *n = cgraph_node (fndecl);
01223 n->next_needed = cgraph_expand_queue;
01224 cgraph_expand_queue = n;
01225 }
01226
01227 #include "gt-cgraph.h"