diff options
author | Jan Hubicka <jh@suse.cz> | 2012-04-17 12:53:22 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2012-04-17 10:53:22 +0000 |
commit | 1ab24192d5e8e4fcee353bb5c024995e5439f5e3 (patch) | |
tree | 74a135bcf142920c4746545d97004d6d4f499f76 /gcc/symtab.c | |
parent | 332781bba582208a138ae93c2f20e45d202fc3e5 (diff) | |
download | gcc-1ab24192d5e8e4fcee353bb5c024995e5439f5e3.tar.gz |
cgraph.c (cgraph_hash, [...]): Remove.
* 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.
From-SVN: r186525
Diffstat (limited to 'gcc/symtab.c')
-rw-r--r-- | gcc/symtab.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/gcc/symtab.c b/gcc/symtab.c index c30f33d703f..9e7c4df83e9 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" |