X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcgraph.c;h=edde1a978d3296f0fef0e0b140896140c96a8868;hb=e561fc1cb16687a153589e70e16ede8de11116af;hp=c1e66f933a60c5e487b3fc28530b3f229939e2e2;hpb=7bd28bbae4ff4dd2612545c506c6c9d33bc28cfc;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cgraph.c b/gcc/cgraph.c index c1e66f933a6..edde1a978d3 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -61,7 +61,7 @@ The callgraph: The function inlining information is decided in advance and maintained in the callgraph as so called inline plan. For each inlined call, the callee's node is cloned to represent the - new function copy produced by inlininer. + new function copy produced by inliner. Each inlined call gets a unique corresponding clone node of the callee and the data structure is updated while inlining is performed, so the clones are eliminated and their callee edges redirected to the @@ -99,10 +99,6 @@ The varpool data structure: /* Hash table used to convert declarations into nodes. */ static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash; -/* We destructively update callgraph during inlining and thus we need to - keep information on whether inlining happened separately. */ -htab_t cgraph_inline_hash; - /* The linked list of cgraph nodes. */ struct cgraph_node *cgraph_nodes; @@ -138,9 +134,8 @@ static int eq_node (const void *, const void *); static hashval_t hash_node (const void *p) { - return ((hashval_t) - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME - (((struct cgraph_node *) p)->decl))); + const struct cgraph_node *n = p; + return (hashval_t) DECL_UID (n->decl); } /* Returns nonzero if P1 and P2 are equal. */ @@ -148,8 +143,8 @@ hash_node (const void *p) static int eq_node (const void *p1, const void *p2) { - return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) == - (tree) p2); + const struct cgraph_node *n1 = p1, *n2 = p2; + return DECL_UID (n1->decl) == DECL_UID (n2->decl); } /* Allocate new callgraph node and insert it into basic data structures. */ @@ -173,19 +168,17 @@ cgraph_create_node (void) struct cgraph_node * cgraph_node (tree decl) { - struct cgraph_node *node; - struct cgraph_node **slot; + struct cgraph_node key, *node, **slot; - if (TREE_CODE (decl) != FUNCTION_DECL) - abort (); + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); if (!cgraph_hash) cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL); - slot = (struct cgraph_node **) - htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl), - IDENTIFIER_HASH_VALUE - (DECL_ASSEMBLER_NAME (decl)), INSERT); + key.decl = decl; + + slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT); + if (*slot) return *slot; @@ -218,26 +211,6 @@ cgraph_edge (struct cgraph_node *node, tree call_expr) return e; } -/* Try to find existing function for identifier ID. */ -struct cgraph_node * -cgraph_node_for_identifier (tree id) -{ - struct cgraph_node **slot; - - if (TREE_CODE (id) != IDENTIFIER_NODE) - abort (); - - if (!cgraph_hash) - return NULL; - - slot = (struct cgraph_node **) - htab_find_slot_with_hash (cgraph_hash, id, - IDENTIFIER_HASH_VALUE (id), NO_INSERT); - if (!slot) - return NULL; - return *slot; -} - /* Create edge from CALLER to CALLEE in the cgraph. */ struct cgraph_edge * @@ -249,12 +222,10 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee, struct cgraph_edge *e; for (e = caller->callees; e; e = e->next_callee) - if (e->call_expr == call_expr) - abort (); + gcc_assert (e->call_expr != call_expr); #endif - if (TREE_CODE (call_expr) != CALL_EXPR) - abort (); + gcc_assert (TREE_CODE (call_expr) == CALL_EXPR); if (!DECL_SAVED_TREE (callee->decl)) edge->inline_failed = N_("function body not available"); @@ -288,14 +259,12 @@ cgraph_remove_edge (struct cgraph_edge *e) for (edge = &e->callee->callers; *edge && *edge != e; edge = &((*edge)->next_caller)) continue; - if (!*edge) - abort (); + gcc_assert (*edge); *edge = (*edge)->next_caller; for (edge2 = &e->caller->callees; *edge2 && *edge2 != e; edge2 = &(*edge2)->next_callee) continue; - if (!*edge2) - abort (); + gcc_assert (*edge2); *edge2 = (*edge2)->next_callee; } @@ -310,8 +279,7 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n) for (edge = &e->callee->callers; *edge && *edge != e; edge = &((*edge)->next_caller)) continue; - if (!*edge) - abort (); + gcc_assert (*edge); *edge = (*edge)->next_caller; e->callee = n; e->next_caller = n->callers; @@ -346,10 +314,7 @@ cgraph_remove_node (struct cgraph_node *node) cgraph_nodes = node->next; if (node->next) node->next->previous = node->previous; - slot = - htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (node->decl), - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME - (node->decl)), NO_INSERT); + slot = htab_find_slot (cgraph_hash, node, NO_INSERT); if (*slot == node) { if (node->next_clone) @@ -357,7 +322,7 @@ cgraph_remove_node (struct cgraph_node *node) else { htab_clear_slot (cgraph_hash, slot); - if (!dump_enabled_p (TDI_all)) + if (!dump_enabled_p (TDI_tree_all)) { DECL_SAVED_TREE (node->decl) = NULL; DECL_STRUCT_FUNCTION (node->decl) = NULL; @@ -385,10 +350,11 @@ cgraph_remove_node (struct cgraph_node *node) || (!n->global.inlined_to && !TREE_ASM_WRITTEN (n->decl) && !DECL_EXTERNAL (n->decl))) break; - if (!n && !dump_enabled_p (TDI_all)) + if (!n && !dump_enabled_p (TDI_tree_all)) { DECL_SAVED_TREE (node->decl) = NULL; DECL_STRUCT_FUNCTION (node->decl) = NULL; + DECL_INITIAL (node->decl) = error_mark_node; } } cgraph_n_nodes--; @@ -407,16 +373,6 @@ cgraph_mark_reachable_node (struct cgraph_node *node) node->next_needed = cgraph_nodes_queue; cgraph_nodes_queue = node; - - /* At the moment frontend automatically emits all nested functions. */ - if (node->nested) - { - struct cgraph_node *node2; - - for (node2 = node->nested; node2; node2 = node2->next_nested) - if (!node2->reachable) - cgraph_mark_reachable_node (node2); - } } } @@ -451,8 +407,8 @@ struct cgraph_local_info * cgraph_local_info (tree decl) { struct cgraph_node *node; - if (TREE_CODE (decl) != FUNCTION_DECL) - abort (); + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); node = cgraph_node (decl); return &node->local; } @@ -463,8 +419,8 @@ struct cgraph_global_info * cgraph_global_info (tree decl) { struct cgraph_node *node; - if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready) - abort (); + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL && cgraph_global_info_ready); node = cgraph_node (decl); return &node->global; } @@ -475,8 +431,8 @@ struct cgraph_rtl_info * cgraph_rtl_info (tree decl) { struct cgraph_node *node; - if (TREE_CODE (decl) != FUNCTION_DECL) - abort (); + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); node = cgraph_node (decl); if (decl != current_function_decl && !TREE_ASM_WRITTEN (node->decl)) @@ -515,7 +471,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) fprintf (f, " tree"); if (node->output) fprintf (f, " output"); - if (node->local.local) fprintf (f, " local"); if (node->local.disregard_inline_limits) @@ -560,39 +515,35 @@ dump_cgraph (FILE *f) /* Returns a hash code for P. */ static hashval_t -cgraph_varpool_hash_node (const void *p) +hash_varpool_node (const void *p) { - return ((hashval_t) - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME - (((struct cgraph_varpool_node *) p)->decl))); + const struct cgraph_varpool_node *n = p; + return (hashval_t) DECL_UID (n->decl); } /* Returns nonzero if P1 and P2 are equal. */ static int -eq_cgraph_varpool_node (const void *p1, const void *p2) +eq_varpool_node (const void *p1, const void *p2) { - return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) == - (tree) p2); + const struct cgraph_varpool_node *n1 = p1, *n2 = p2; + return DECL_UID (n1->decl) == DECL_UID (n2->decl); } /* Return cgraph_varpool node assigned to DECL. Create new one when needed. */ struct cgraph_varpool_node * cgraph_varpool_node (tree decl) { - struct cgraph_varpool_node *node; - struct cgraph_varpool_node **slot; + struct cgraph_varpool_node key, *node, **slot; - if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL) - abort (); + gcc_assert (DECL_P (decl) && TREE_CODE (decl) != FUNCTION_DECL); if (!cgraph_varpool_hash) - cgraph_varpool_hash = htab_create_ggc (10, cgraph_varpool_hash_node, - eq_cgraph_varpool_node, NULL); + cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node, + eq_varpool_node, NULL); + key.decl = decl; slot = (struct cgraph_varpool_node **) - htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl), - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (decl)), - INSERT); + htab_find_slot (cgraph_varpool_hash, &key, INSERT); if (*slot) return *slot; node = ggc_alloc_cleared (sizeof (*node)); @@ -607,10 +558,6 @@ cgraph_varpool_node (tree decl) void change_decl_assembler_name (tree decl, tree name) { - struct cgraph_node *node = NULL; - struct cgraph_varpool_node *vnode = NULL; - void **slot; - if (!DECL_ASSEMBLER_NAME_SET_P (decl)) { SET_DECL_ASSEMBLER_NAME (decl, name); @@ -623,83 +570,7 @@ change_decl_assembler_name (tree decl, tree name) && DECL_RTL_SET_P (decl)) warning ("%D renamed after being referenced in assembly", decl); - if (TREE_CODE (decl) == FUNCTION_DECL && cgraph_hash) - { - /* Take a look whether declaration is in the cgraph structure. */ - slot = - htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl), - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME - (decl)), NO_INSERT); - if (slot) - node = *slot; - - /* It is, verify that we are the canonical node for this decl. */ - if (node && node->decl == decl) - { - node = *slot; - htab_clear_slot (cgraph_hash, slot); - } - else - node = NULL; - } - if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && cgraph_varpool_hash) - { - /* Take a look whether declaration is in the cgraph structure. */ - slot = - htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl), - IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME - (decl)), NO_INSERT); - if (slot) - vnode = *slot; - - /* It is, verify that we are the canonical vnode for this decl. */ - if (vnode && vnode->decl == decl) - { - vnode = *slot; - htab_clear_slot (cgraph_varpool_hash, slot); - } - else - vnode = NULL; - } SET_DECL_ASSEMBLER_NAME (decl, name); - if (node) - { - slot = - htab_find_slot_with_hash (cgraph_hash, name, - IDENTIFIER_HASH_VALUE (name), INSERT); - if (*slot) - abort (); - *slot = node; - } - if (vnode) - { - slot = - htab_find_slot_with_hash (cgraph_varpool_hash, name, - IDENTIFIER_HASH_VALUE (name), INSERT); - if (*slot) - abort (); - *slot = vnode; - } -} - -/* Try to find existing function for identifier ID. */ -struct cgraph_varpool_node * -cgraph_varpool_node_for_identifier (tree id) -{ - struct cgraph_varpool_node **slot; - - if (TREE_CODE (id) != IDENTIFIER_NODE) - abort (); - - if (!cgraph_varpool_hash) - return NULL; - - slot = (struct cgraph_varpool_node **) - htab_find_slot_with_hash (cgraph_varpool_hash, id, - IDENTIFIER_HASH_VALUE (id), NO_INSERT); - if (!slot) - return NULL; - return *slot; } /* Notify finalize_compilation_unit that given node is reachable @@ -775,10 +646,7 @@ cgraph_function_possibly_inlined_p (tree decl) { if (!cgraph_global_info_ready) return (DECL_INLINE (decl) && !flag_really_no_inline); - if (!cgraph_inline_hash) - return false; - return (htab_find_slot (cgraph_inline_hash, DECL_ASSEMBLER_NAME (decl), - NO_INSERT) != NULL); + return DECL_POSSIBLY_INLINED (decl); } /* Create clone of E in the node N represented by CALL_EXPR the callgraph. */ @@ -818,4 +686,17 @@ cgraph_clone_node (struct cgraph_node *n) return new; } + +/* NODE is no longer nested function; update cgraph accordingly. */ +void +cgraph_unnest_node (struct cgraph_node *node) +{ + struct cgraph_node **node2 = &node->origin->nested; + gcc_assert (node->origin); + + while (*node2 != node) + node2 = &(*node2)->next_nested; + *node2 = node->next_nested; + node->origin = NULL; +} #include "gt-cgraph.h"