summaryrefslogtreecommitdiff
path: root/gcc/symtab.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2012-04-17 12:53:22 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2012-04-17 10:53:22 +0000
commit1ab24192d5e8e4fcee353bb5c024995e5439f5e3 (patch)
tree74a135bcf142920c4746545d97004d6d4f499f76 /gcc/symtab.c
parent332781bba582208a138ae93c2f20e45d202fc3e5 (diff)
downloadgcc-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.c239
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"