From cfbe30aa5574ac64c03e6048dce58d1c850d835b Mon Sep 17 00:00:00 2001 From: hubicka Date: Tue, 17 Apr 2012 10:53:22 +0000 Subject: [PATCH] * cgraph.c (cgraph_hash, assembler_name_hash): Remove. (hash_node, eq_node): Remove. (cgraph_create_node): Do not handle hashtable. (cgraph_get_node): Remove. (cgraph_insert_node_to_hashtable): Remove. (hash_node_by_assembler_name): Remove. (eq_assembler_name): Remove. (cgraph_node_for_asm): Rewrite. (cgraph_find_replacement_node): Break out from ... (cgraph_remove_node): ... here; do not maintain hashtables. (change_decl_assembler_name): Remove. (cgraph_clone_node): Do not maintain hashtables. * cgraph.h (const_symtab_node): New typedef. (cgraph_insert_node_to_hashtable): Remove. (symtab_get_node, symtab_node_for_asm, symtab_insert_node_to_hashtable): Declare. (cgraph_find_replacement_node): Declare. (cgraph_get_node, varpool_get_node): Turn into inlines. (cgraph, varpool): Work sanely on NULL pointers. (FOR_EACH_SYMBOL): New walker. * ipa-inline-transform.c (save_inline_function_body): Use symtab_insert_node_to_hashtable. * symtab.c: Include ggc.h and diagnostics.h (symtab_hash, assembler_name_hash): New static vars; (hash_node, eq_node, hash_node_by_assembler_name, eq_assembler_name, insert_to_assembler_name_hash, unlink_from_assembler_name_hash): New. (symtab_register_node): Update hashtables. (symtab_insert_node_to_hashtable): New. (symtab_unregister_node): Update hashtables. (symtab_get_node): New. (symtab_node_for_asm): New. (change_decl_assembler_name): New. * Makefile.in (symtab.o): Needs GTY. * varpool.c (varpool_hash): Remove. (hash_varpool_node, eq_varpool_node, varpool_get_node): Remove. (varpool_node): Rewrite using varpool_get_node. (varpool_remove_node): DO not maintain hashtables. (varpool_node_for_asm); Rewrite. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186525 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 42 +++++ gcc/Makefile.in | 4 +- gcc/cgraph.c | 407 +++++++++++---------------------------------- gcc/cgraph.h | 37 ++++- gcc/ipa-inline-transform.c | 2 +- gcc/symtab.c | 239 ++++++++++++++++++++++++++ gcc/varpool.c | 68 +------- 7 files changed, 420 insertions(+), 379 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3d8388b..024ffcb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,45 @@ +2012-04-16 Jan Hubicka + + * cgraph.c (cgraph_hash, assembler_name_hash): Remove. + (hash_node, eq_node): Remove. + (cgraph_create_node): Do not handle hashtable. + (cgraph_get_node): Remove. + (cgraph_insert_node_to_hashtable): Remove. + (hash_node_by_assembler_name): Remove. + (eq_assembler_name): Remove. + (cgraph_node_for_asm): Rewrite. + (cgraph_find_replacement_node): Break out from ... + (cgraph_remove_node): ... here; do not maintain hashtables. + (change_decl_assembler_name): Remove. + (cgraph_clone_node): Do not maintain hashtables. + * cgraph.h (const_symtab_node): New typedef. + (cgraph_insert_node_to_hashtable): Remove. + (symtab_get_node, symtab_node_for_asm, + symtab_insert_node_to_hashtable): Declare. + (cgraph_find_replacement_node): Declare. + (cgraph_get_node, varpool_get_node): Turn into inlines. + (cgraph, varpool): Work sanely on NULL pointers. + (FOR_EACH_SYMBOL): New walker. + * ipa-inline-transform.c (save_inline_function_body): Use + symtab_insert_node_to_hashtable. + * symtab.c: Include ggc.h and diagnostics.h + (symtab_hash, assembler_name_hash): New static vars; + (hash_node, eq_node, hash_node_by_assembler_name, + eq_assembler_name, insert_to_assembler_name_hash, + unlink_from_assembler_name_hash): New. + (symtab_register_node): Update hashtables. + (symtab_insert_node_to_hashtable): New. + (symtab_unregister_node): Update hashtables. + (symtab_get_node): New. + (symtab_node_for_asm): New. + (change_decl_assembler_name): New. + * Makefile.in (symtab.o): Needs GTY. + * varpool.c (varpool_hash): Remove. + (hash_varpool_node, eq_varpool_node, varpool_get_node): Remove. + (varpool_node): Rewrite using varpool_get_node. + (varpool_remove_node): DO not maintain hashtables. + (varpool_node_for_asm); Rewrite. + 2012-04-16 Sandra Loosemore * doc/invoke.texi: Copy-edit to put verbs in the present tense diff --git a/gcc/Makefile.in b/gcc/Makefile.in index de82764..0070cea 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2912,7 +2912,7 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(TARGET_H) symtab.o : symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \ - $(HASHTAB_H) + $(HASHTAB_H) gt-symtab.h cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \ gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ @@ -3690,7 +3690,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/fixed-value.h \ $(srcdir)/output.h $(srcdir)/cfgloop.h \ $(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \ - $(srcdir)/reload.h $(srcdir)/caller-save.c \ + $(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \ $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/matrix-reorg.c \ $(srcdir)/dbxout.c \ diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 6a54db9..f5f662c 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -119,11 +119,6 @@ static void cgraph_node_remove_callers (struct cgraph_node *node); static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); static inline void cgraph_edge_remove_callee (struct cgraph_edge *e); -/* Hash table used to convert declarations into nodes. */ -static GTY((param_is (union symtab_node_def))) htab_t cgraph_hash; -/* Hash table used to convert assembler names into nodes. */ -static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash; - /* Queue of cgraph nodes scheduled to be lowered. */ symtab_node x_cgraph_nodes_queue; #define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue) @@ -419,26 +414,6 @@ cgraph_call_node_duplication_hooks (struct cgraph_node *node1, } } -/* Returns a hash code for P. */ - -static hashval_t -hash_node (const void *p) -{ - const struct cgraph_node *n = (const struct cgraph_node *) p; - return (hashval_t) DECL_UID (n->symbol.decl); -} - - -/* Returns nonzero if P1 and P2 are equal. */ - -static int -eq_node (const void *p1, const void *p2) -{ - const struct cgraph_node *n1 = (const struct cgraph_node *) p1; - const struct cgraph_node *n2 = (const struct cgraph_node *) p2; - return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl); -} - /* Allocate new callgraph node. */ static inline struct cgraph_node * @@ -479,42 +454,18 @@ cgraph_create_node_1 (void) struct cgraph_node * cgraph_create_node (tree decl) { - struct cgraph_node key, *node, **slot; - + struct cgraph_node *node = cgraph_create_node_1 (); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); - if (!cgraph_hash) - cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL); - - key.symbol.decl = decl; - slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT); - gcc_assert (!*slot); - - node = cgraph_create_node_1 (); node->symbol.decl = decl; - symtab_register_node ((symtab_node)node); - *slot = node; + symtab_register_node ((symtab_node) node); + if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) { node->origin = cgraph_get_create_node (DECL_CONTEXT (decl)); node->next_nested = node->origin->nested; node->origin->nested = node; } - if (assembler_name_hash) - { - void **aslot; - tree name = DECL_ASSEMBLER_NAME (decl); - - aslot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - INSERT); - /* We can have multiple declarations with same assembler name. For C++ - it is __builtin_strlen and strlen, for instance. Do we need to - record them all? Original implementation marked just first one - so lets hope for the best. */ - if (*aslot == NULL) - *aslot = node; - } return node; } @@ -629,100 +580,18 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, return node; } -/* Returns the cgraph node assigned to DECL or NULL if no cgraph node - is assigned. */ - -struct cgraph_node * -cgraph_get_node (const_tree decl) -{ - struct cgraph_node key, *node = NULL, **slot; - - gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); - - if (!cgraph_hash) - return NULL; - - key.symbol.decl = CONST_CAST2 (tree, const_tree, decl); - - slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, - NO_INSERT); - - if (slot && *slot) - node = *slot; - return node; -} - -/* Insert already constructed node into hashtable. */ - -void -cgraph_insert_node_to_hashtable (struct cgraph_node *node) -{ - struct cgraph_node **slot; - - slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT); - - gcc_assert (!*slot); - *slot = node; -} - -/* Returns a hash code for P. */ - -static hashval_t -hash_node_by_assembler_name (const void *p) -{ - const struct cgraph_node *n = (const struct cgraph_node *) p; - return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl)); -} - -/* Returns nonzero if P1 and P2 are equal. */ - -static int -eq_assembler_name (const void *p1, const void *p2) -{ - const struct cgraph_node *n1 = (const struct cgraph_node *) p1; - const_tree name = (const_tree)p2; - return (decl_assembler_name_equal (n1->symbol.decl, name)); -} - /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. Return NULL if there's no such node. */ struct cgraph_node * cgraph_node_for_asm (tree asmname) { - struct cgraph_node *node; - void **slot; - - if (!assembler_name_hash) - { - assembler_name_hash = - htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name, - NULL); - FOR_EACH_FUNCTION (node) - if (!node->global.inlined_to) - { - tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); - slot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - INSERT); - /* We can have multiple declarations with same assembler name. For C++ - it is __builtin_strlen and strlen, for instance. Do we need to - record them all? Original implementation marked just first one - so lets hope for the best. */ - if (!*slot) - *slot = node; - } - } - - slot = htab_find_slot_with_hash (assembler_name_hash, asmname, - decl_assembler_name_hash (asmname), - NO_INSERT); + symtab_node node = symtab_node_for_asm (asmname); - if (slot) - { - node = (struct cgraph_node *) *slot; - return node; - } + /* We do not want to look at inline clones. */ + for (node = symtab_node_for_asm (asmname); node; node = node->symbol.next_sharing_asm_name) + if (symtab_function_p (node) && !cgraph(node)->global.inlined_to) + return cgraph (node); return NULL; } @@ -1392,13 +1261,96 @@ cgraph_release_function_body (struct cgraph_node *node) DECL_INITIAL (node->symbol.decl) = error_mark_node; } +/* NODE is being removed from symbol table; see if its entry can be replaced by + other inline clone. */ +struct cgraph_node * +cgraph_find_replacement_node (struct cgraph_node *node) +{ + struct cgraph_node *next_inline_clone, *replacement; + + for (next_inline_clone = node->clones; + next_inline_clone + && next_inline_clone->symbol.decl != node->symbol.decl; + next_inline_clone = next_inline_clone->next_sibling_clone) + ; + + /* If there is inline clone of the node being removed, we need + to put it into the position of removed node and reorganize all + other clones to be based on it. */ + if (next_inline_clone) + { + struct cgraph_node *n; + struct cgraph_node *new_clones; + + replacement = next_inline_clone; + + /* Unlink inline clone from the list of clones of removed node. */ + if (next_inline_clone->next_sibling_clone) + next_inline_clone->next_sibling_clone->prev_sibling_clone + = next_inline_clone->prev_sibling_clone; + if (next_inline_clone->prev_sibling_clone) + { + gcc_assert (node->clones != next_inline_clone); + next_inline_clone->prev_sibling_clone->next_sibling_clone + = next_inline_clone->next_sibling_clone; + } + else + { + gcc_assert (node->clones == next_inline_clone); + node->clones = next_inline_clone->next_sibling_clone; + } + + new_clones = node->clones; + node->clones = NULL; + + /* Copy clone info. */ + next_inline_clone->clone = node->clone; + + /* Now place it into clone tree at same level at NODE. */ + next_inline_clone->clone_of = node->clone_of; + next_inline_clone->prev_sibling_clone = NULL; + next_inline_clone->next_sibling_clone = NULL; + if (node->clone_of) + { + if (node->clone_of->clones) + node->clone_of->clones->prev_sibling_clone = next_inline_clone; + next_inline_clone->next_sibling_clone = node->clone_of->clones; + node->clone_of->clones = next_inline_clone; + } + + /* Merge the clone list. */ + if (new_clones) + { + if (!next_inline_clone->clones) + next_inline_clone->clones = new_clones; + else + { + n = next_inline_clone->clones; + while (n->next_sibling_clone) + n = n->next_sibling_clone; + n->next_sibling_clone = new_clones; + new_clones->prev_sibling_clone = n; + } + } + + /* Update clone_of pointers. */ + n = new_clones; + while (n) + { + n->clone_of = next_inline_clone; + n = n->next_sibling_clone; + } + return replacement; + } + else + return NULL; +} + /* Remove the node from cgraph. */ void cgraph_remove_node (struct cgraph_node *node) { - void **slot; - bool kill_body = false; struct cgraph_node *n; int uid = node->uid; @@ -1423,91 +1375,6 @@ cgraph_remove_node (struct cgraph_node *node) *node2 = node->next_nested; } symtab_unregister_node ((symtab_node)node); - slot = htab_find_slot (cgraph_hash, node, NO_INSERT); - if (*slot == node) - { - struct cgraph_node *next_inline_clone; - - for (next_inline_clone = node->clones; - next_inline_clone - && next_inline_clone->symbol.decl != node->symbol.decl; - next_inline_clone = next_inline_clone->next_sibling_clone) - ; - - /* If there is inline clone of the node being removed, we need - to put it into the position of removed node and reorganize all - other clones to be based on it. */ - if (next_inline_clone) - { - struct cgraph_node *n; - struct cgraph_node *new_clones; - - *slot = next_inline_clone; - - /* Unlink inline clone from the list of clones of removed node. */ - if (next_inline_clone->next_sibling_clone) - next_inline_clone->next_sibling_clone->prev_sibling_clone - = next_inline_clone->prev_sibling_clone; - if (next_inline_clone->prev_sibling_clone) - { - gcc_assert (node->clones != next_inline_clone); - next_inline_clone->prev_sibling_clone->next_sibling_clone - = next_inline_clone->next_sibling_clone; - } - else - { - gcc_assert (node->clones == next_inline_clone); - node->clones = next_inline_clone->next_sibling_clone; - } - - new_clones = node->clones; - node->clones = NULL; - - /* Copy clone info. */ - next_inline_clone->clone = node->clone; - - /* Now place it into clone tree at same level at NODE. */ - next_inline_clone->clone_of = node->clone_of; - next_inline_clone->prev_sibling_clone = NULL; - next_inline_clone->next_sibling_clone = NULL; - if (node->clone_of) - { - if (node->clone_of->clones) - node->clone_of->clones->prev_sibling_clone = next_inline_clone; - next_inline_clone->next_sibling_clone = node->clone_of->clones; - node->clone_of->clones = next_inline_clone; - } - - /* Merge the clone list. */ - if (new_clones) - { - if (!next_inline_clone->clones) - next_inline_clone->clones = new_clones; - else - { - n = next_inline_clone->clones; - while (n->next_sibling_clone) - n = n->next_sibling_clone; - n->next_sibling_clone = new_clones; - new_clones->prev_sibling_clone = n; - } - } - - /* Update clone_of pointers. */ - n = new_clones; - while (n) - { - n->clone_of = next_inline_clone; - n = n->next_sibling_clone; - } - } - else - { - htab_clear_slot (cgraph_hash, slot); - kill_body = true; - } - - } if (node->prev_sibling_clone) node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; else if (node->clone_of) @@ -1549,29 +1416,15 @@ cgraph_remove_node (struct cgraph_node *node) itself is kept in the cgraph even after it is compiled. Check whether we are done with this body and reclaim it proactively if this is the case. */ - if (!kill_body && *slot) - { - struct cgraph_node *n = (struct cgraph_node *) *slot; - if (!n->clones && !n->clone_of && !n->global.inlined_to + n = cgraph_get_node (node->symbol.decl); + if (!n + || (!n->clones && !n->clone_of && !n->global.inlined_to && (cgraph_global_info_ready && (TREE_ASM_WRITTEN (n->symbol.decl) || DECL_EXTERNAL (n->symbol.decl) - || n->symbol.in_other_partition))) - kill_body = true; - } - if (assembler_name_hash) - { - tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); - slot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - NO_INSERT); - /* Inline clones are not hashed. */ - if (slot && *slot == node) - htab_clear_slot (assembler_name_hash, slot); - } - - if (kill_body) + || n->symbol.in_other_partition)))) cgraph_release_function_body (node); + node->symbol.decl = NULL; if (node->call_site_hash) { @@ -1939,51 +1792,6 @@ debug_cgraph (void) dump_cgraph (stderr); } - -/* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables. */ - -void -change_decl_assembler_name (tree decl, tree name) -{ - struct cgraph_node *node; - void **slot; - if (!DECL_ASSEMBLER_NAME_SET_P (decl)) - SET_DECL_ASSEMBLER_NAME (decl, name); - else - { - if (name == DECL_ASSEMBLER_NAME (decl)) - return; - - if (assembler_name_hash - && TREE_CODE (decl) == FUNCTION_DECL - && (node = cgraph_get_node (decl)) != NULL) - { - tree old_name = DECL_ASSEMBLER_NAME (decl); - slot = htab_find_slot_with_hash (assembler_name_hash, old_name, - decl_assembler_name_hash (old_name), - NO_INSERT); - /* Inline clones are not hashed. */ - if (slot && *slot == node) - htab_clear_slot (assembler_name_hash, slot); - } - if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) - && DECL_RTL_SET_P (decl)) - warning (0, "%D renamed after being referenced in assembly", decl); - - SET_DECL_ASSEMBLER_NAME (decl, name); - } - if (assembler_name_hash - && TREE_CODE (decl) == FUNCTION_DECL - && (node = cgraph_get_node (decl)) != NULL) - { - slot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - INSERT); - gcc_assert (!*slot); - *slot = node; - } -} - /* Add a top-level asm statement to the list. */ struct cgraph_asm_node * @@ -2154,25 +1962,6 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, n->clones = new_node; new_node->clone_of = n; - if (n->symbol.decl != decl) - { - struct cgraph_node **slot; - slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, new_node, INSERT); - gcc_assert (!*slot); - *slot = new_node; - if (assembler_name_hash) - { - void **aslot; - tree name = DECL_ASSEMBLER_NAME (decl); - - aslot = htab_find_slot_with_hash (assembler_name_hash, name, - decl_assembler_name_hash (name), - INSERT); - gcc_assert (!*aslot); - *aslot = new_node; - } - } - if (call_duplication_hook) cgraph_call_node_duplication_hooks (n, new_node); return new_node; diff --git a/gcc/cgraph.h b/gcc/cgraph.h index e2f3b0b..39372f1 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -40,6 +40,7 @@ enum symtab_type union symtab_node_def; typedef union symtab_node_def *symtab_node; +typedef const union symtab_node_def *const_symtab_node; /* Base of all entries in the symbol table. The symtab_node is inherited by cgraph and varpol nodes. */ @@ -60,6 +61,12 @@ struct GTY(()) symtab_node_base /* Linked list of symbol table entries starting with symtab_nodes. */ symtab_node next; symtab_node previous; + /* Linked list of symbols with the same asm name. There may be multiple + entries for single symbol name in the case of LTO resolutions, + existence of inline clones, or duplicated declaration. The last case + is a long standing bug frontends and builtin handling. */ + symtab_node next_sharing_asm_name; + symtab_node previous_sharing_asm_name; PTR GTY ((skip)) aux; @@ -499,15 +506,18 @@ extern bool same_body_aliases_done; void symtab_register_node (symtab_node); void symtab_unregister_node (symtab_node); void symtab_remove_node (symtab_node); +symtab_node symtab_get_node (const_tree); +symtab_node symtab_node_for_asm (const_tree asmname); +void symtab_insert_node_to_hashtable (symtab_node); /* In cgraph.c */ void dump_cgraph (FILE *); void debug_cgraph (void); void dump_cgraph_node (FILE *, struct cgraph_node *); void debug_cgraph_node (struct cgraph_node *); -void cgraph_insert_node_to_hashtable (struct cgraph_node *node); void cgraph_remove_edge (struct cgraph_edge *); void cgraph_remove_node (struct cgraph_node *); +struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *); void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *); bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *); void cgraph_release_function_body (struct cgraph_node *); @@ -518,7 +528,6 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int, gcov_type, int); struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void); -struct cgraph_node * cgraph_get_node (const_tree); struct cgraph_node * cgraph_create_node (tree); struct cgraph_node * cgraph_get_create_node (tree); struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree); @@ -697,7 +706,6 @@ void cgraph_make_node_local (struct cgraph_node *); bool cgraph_node_can_be_local_p (struct cgraph_node *); -struct varpool_node * varpool_get_node (const_tree decl); void varpool_remove_node (struct varpool_node *node); void varpool_finalize_named_section_flags (struct varpool_node *node); bool varpool_assemble_pending_decls (void); @@ -734,7 +742,7 @@ static inline struct cgraph_node * cgraph (symtab_node node) { gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION); - return &node->x_function; + return (struct cgraph_node *)node; } /* Return varpool node for given symbol and check it is a variable. */ @@ -742,9 +750,28 @@ static inline struct varpool_node * varpool (symtab_node node) { gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE); - return &node->x_variable; + return (struct varpool_node *)node; } +/* Return callgraph node for given symbol and check it is a function. */ +static inline struct cgraph_node * +cgraph_get_node (const_tree decl) +{ + gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL); + return cgraph (symtab_get_node (decl)); +} + +/* Return varpool node for given symbol and check it is a function. */ +static inline struct varpool_node * +varpool_get_node (const_tree decl) +{ + gcc_checking_assert (TREE_CODE (decl) == VAR_DECL); + return varpool (symtab_get_node (decl)); +} + +/* Walk all symbols. */ +#define FOR_EACH_SYMBOL(node) \ + for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next) /* Return first reachable static variable with initializer. */ static inline struct varpool_node * diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index d875c78..c6cbd01 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -278,7 +278,7 @@ save_inline_function_body (struct cgraph_node *node) /* first_clone will be turned into real function. */ first_clone = node->clones; first_clone->symbol.decl = copy_node (node->symbol.decl); - cgraph_insert_node_to_hashtable (first_clone); + symtab_insert_node_to_hashtable ((symtab_node) first_clone); gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl)); /* Now reshape the clone tree, so all other clones descends from diff --git a/gcc/symtab.c b/gcc/symtab.c index c30f33d..9e7c4df 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -25,7 +25,14 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-inline.h" #include "hashtab.h" +#include "ggc.h" #include "cgraph.h" +#include "diagnostic.h" + +/* Hash table used to convert declarations into nodes. */ +static GTY((param_is (union symtab_node_def))) htab_t symtab_hash; +/* Hash table used to convert assembler names into nodes. */ +static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash; /* Linked list of symbol table nodes. */ symtab_node symtab_nodes; @@ -35,29 +42,153 @@ symtab_node symtab_nodes; them, to support -fno-toplevel-reorder. */ int symtab_order; +/* Returns a hash code for P. */ + +static hashval_t +hash_node (const void *p) +{ + const_symtab_node n = (const_symtab_node ) p; + return (hashval_t) DECL_UID (n->symbol.decl); +} + + +/* Returns nonzero if P1 and P2 are equal. */ + +static int +eq_node (const void *p1, const void *p2) +{ + const_symtab_node n1 = (const_symtab_node) p1; + const_symtab_node n2 = (const_symtab_node) p2; + return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl); +} + +/* Returns a hash code for P. */ + +static hashval_t +hash_node_by_assembler_name (const void *p) +{ + const_symtab_node n = (const_symtab_node) p; + return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl)); +} + +/* Returns nonzero if P1 and P2 are equal. */ + +static int +eq_assembler_name (const void *p1, const void *p2) +{ + const_symtab_node n1 = (const_symtab_node) p1; + const_tree name = (const_tree)p2; + return (decl_assembler_name_equal (n1->symbol.decl, name)); +} + +/* Insert NODE to assembler name hash. */ + +static void +insert_to_assembler_name_hash (symtab_node node) +{ + gcc_checking_assert (!node->symbol.previous_sharing_asm_name + && !node->symbol.next_sharing_asm_name); + if (assembler_name_hash) + { + void **aslot; + tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); + + aslot = htab_find_slot_with_hash (assembler_name_hash, name, + decl_assembler_name_hash (name), + INSERT); + gcc_assert (*aslot != node); + node->symbol.next_sharing_asm_name = (symtab_node)*aslot; + if (*aslot != NULL) + ((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node; + *aslot = node; + } + +} + +/* Remove NODE from assembler name hash. */ + +static void +unlink_from_assembler_name_hash (symtab_node node) +{ + if (assembler_name_hash) + { + if (node->symbol.next_sharing_asm_name) + node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name + = node->symbol.previous_sharing_asm_name; + if (node->symbol.previous_sharing_asm_name) + { + node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name + = node->symbol.next_sharing_asm_name; + } + else + { + tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); + void **slot; + slot = htab_find_slot_with_hash (assembler_name_hash, name, + decl_assembler_name_hash (name), + NO_INSERT); + gcc_assert (*slot == node); + if (!node->symbol.next_sharing_asm_name) + htab_clear_slot (assembler_name_hash, slot); + else + *slot = node->symbol.next_sharing_asm_name; + } + } +} + + /* Add node into symbol table. This function is not used directly, but via cgraph/varpool node creation routines. */ void symtab_register_node (symtab_node node) { + struct symtab_node_base key; + symtab_node *slot; + node->symbol.next = symtab_nodes; node->symbol.previous = NULL; if (symtab_nodes) symtab_nodes->symbol.previous = node; symtab_nodes = node; + if (!symtab_hash) + symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); + key.decl = node->symbol.decl; + slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT); + if (*slot == NULL) + *slot = node; + + insert_to_assembler_name_hash (node); + node->symbol.order = symtab_order++; ipa_empty_ref_list (&node->symbol.ref_list); } +/* Make NODE to be the one symtab hash is pointing to. Used when reshaping tree + of inline clones. */ + +void +symtab_insert_node_to_hashtable (symtab_node node) +{ + struct symtab_node_base key; + symtab_node *slot; + + if (!symtab_hash) + symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); + key.decl = node->symbol.decl; + slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT); + *slot = node; +} + /* Remove node from symbol table. This function is not used directly, but via cgraph/varpool node removal routines. */ void symtab_unregister_node (symtab_node node) { + void **slot; ipa_remove_all_references (&node->symbol.ref_list); ipa_remove_all_refering (&node->symbol.ref_list); @@ -83,6 +214,46 @@ symtab_unregister_node (symtab_node node) node->symbol.next->symbol.previous = node->symbol.previous; node->symbol.next = NULL; node->symbol.previous = NULL; + + slot = htab_find_slot (symtab_hash, node, NO_INSERT); + if (*slot == node) + { + symtab_node replacement_node = NULL; + if (symtab_function_p (node)) + replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node)); + if (!replacement_node) + htab_clear_slot (symtab_hash, slot); + else + *slot = replacement_node; + } + unlink_from_assembler_name_hash (node); +} + +/* Return symbol table node associated with DECL, if any, + and NULL otherwise. */ + +symtab_node +symtab_get_node (const_tree decl) +{ + symtab_node *slot; + struct symtab_node_base key; + + gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL + || (TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) + || in_lto_p))); + + if (!symtab_hash) + return NULL; + + key.decl = CONST_CAST2 (tree, const_tree, decl); + + slot = (symtab_node *) htab_find_slot (symtab_hash, &key, + NO_INSERT); + + if (slot) + return *slot; + return NULL; } /* Remove symtab NODE from the symbol table. */ @@ -95,3 +266,71 @@ symtab_remove_node (symtab_node node) else if (symtab_variable_p (node)) varpool_remove_node (varpool (node)); } + +/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. + Return NULL if there's no such node. */ + +symtab_node +symtab_node_for_asm (const_tree asmname) +{ + symtab_node node; + void **slot; + + if (!assembler_name_hash) + { + assembler_name_hash = + htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name, + NULL); + FOR_EACH_SYMBOL (node) + insert_to_assembler_name_hash (node); + } + + slot = htab_find_slot_with_hash (assembler_name_hash, asmname, + decl_assembler_name_hash (asmname), + NO_INSERT); + + if (slot) + { + node = (symtab_node) *slot; + return node; + } + return NULL; +} + +/* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */ + +void +change_decl_assembler_name (tree decl, tree name) +{ + symtab_node node = NULL; + + /* We can have user ASM names on things, like global register variables, that + are not in the symbol table. */ + if ((TREE_CODE (decl) == VAR_DECL + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) + || TREE_CODE (decl) == FUNCTION_DECL) + node = symtab_get_node (decl); + if (!DECL_ASSEMBLER_NAME_SET_P (decl)) + { + SET_DECL_ASSEMBLER_NAME (decl, name); + if (node) + insert_to_assembler_name_hash (node); + } + else + { + if (name == DECL_ASSEMBLER_NAME (decl)) + return; + + if (node) + unlink_from_assembler_name_hash (node); + if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) + && DECL_RTL_SET_P (decl)) + warning (0, "%D renamed after being referenced in assembly", decl); + + SET_DECL_ASSEMBLER_NAME (decl, name); + if (node) + insert_to_assembler_name_hash (node); + } +} + +#include "gt-symtab.h" diff --git a/gcc/varpool.c b/gcc/varpool.c index 8fd9e8a..e41a780 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -48,9 +48,6 @@ along with GCC; see the file COPYING3. If not see All variables supposed to be output into final file needs to be explicitly marked by frontend via VARPOOL_FINALIZE_DECL function. */ -/* Hash table used to convert declarations into nodes. */ -static GTY((param_is (union symtab_node_def))) htab_t varpool_hash; - /* Queue of cgraph nodes scheduled to be lowered and output. The queue is maintained via mark_needed_node, linked via node->next_needed pointer. @@ -84,66 +81,20 @@ varpool_node_name (struct varpool_node *node) return lang_hooks.decl_printable_name (node->symbol.decl, 2); } -/* Returns a hash code for P. */ -static hashval_t -hash_varpool_node (const void *p) -{ - const struct varpool_node *n = (const struct varpool_node *) p; - return (hashval_t) DECL_UID (n->symbol.decl); -} - -/* Returns nonzero if P1 and P2 are equal. */ -static int -eq_varpool_node (const void *p1, const void *p2) -{ - const struct varpool_node *n1 = - (const struct varpool_node *) p1; - const struct varpool_node *n2 = - (const struct varpool_node *) p2; - return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl); -} - -/* Return varpool node assigned to DECL without creating new one. */ -struct varpool_node * -varpool_get_node (const_tree decl) -{ - struct varpool_node key, **slot; - - gcc_assert (TREE_CODE (decl) == VAR_DECL - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))); - - if (!varpool_hash) - return NULL; - key.symbol.decl = CONST_CAST2 (tree, const_tree, decl); - slot = (struct varpool_node **) - htab_find_slot (varpool_hash, &key, NO_INSERT); - if (!slot) - return NULL; - return *slot; -} - /* Return varpool node assigned to DECL. Create new one when needed. */ struct varpool_node * varpool_node (tree decl) { - struct varpool_node key, *node, **slot; - + struct varpool_node *node = varpool_get_node (decl); gcc_assert (TREE_CODE (decl) == VAR_DECL && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p)); + if (node) + return node; - if (!varpool_hash) - varpool_hash = htab_create_ggc (10, hash_varpool_node, - eq_varpool_node, NULL); - key.symbol.decl = decl; - slot = (struct varpool_node **) - htab_find_slot (varpool_hash, &key, INSERT); - if (*slot) - return *slot; node = ggc_alloc_cleared_varpool_node (); node->symbol.type = SYMTAB_VARIABLE; node->symbol.decl = decl; symtab_register_node ((symtab_node)node); - *slot = node; return node; } @@ -151,10 +102,6 @@ varpool_node (tree decl) void varpool_remove_node (struct varpool_node *node) { - void **slot; - slot = htab_find_slot (varpool_hash, node, NO_INSERT); - gcc_assert (*slot == node); - htab_clear_slot (varpool_hash, slot); gcc_assert (!varpool_assembled_nodes_queue); symtab_unregister_node ((symtab_node)node); if (varpool_first_unanalyzed_node == node) @@ -238,12 +185,9 @@ debug_varpool (void) struct varpool_node * varpool_node_for_asm (tree asmname) { - struct varpool_node *node; - - FOR_EACH_VARIABLE (node) - if (decl_assembler_name_equal (node->symbol.decl, asmname)) - return node; - + symtab_node node = symtab_node_for_asm (asmname); + if (node && symtab_variable_p (node)) + return varpool (node); return NULL; } -- 2.7.4