* cgraph.c (cgraph_hash, assembler_name_hash): Remove.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Apr 2012 10:53:22 +0000 (10:53 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 17 Apr 2012 10:53:22 +0000 (10:53 +0000)
(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
gcc/Makefile.in
gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-inline-transform.c
gcc/symtab.c
gcc/varpool.c

index 3d8388b..024ffcb 100644 (file)
@@ -1,3 +1,45 @@
+2012-04-16  Jan Hubicka  <jh@suse.cz>
+
+       * 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  <sandra@codesourcery.com>
 
        * doc/invoke.texi:  Copy-edit to put verbs in the present tense
index de82764..0070cea 100644 (file)
@@ -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 \
index 6a54db9..f5f662c 100644 (file)
@@ -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;
index e2f3b0b..39372f1 100644 (file)
@@ -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 *
index d875c78..c6cbd01 100644 (file)
@@ -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
index c30f33d..9e7c4df 100644 (file)
@@ -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"
index 8fd9e8a..e41a780 100644 (file)
@@ -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;
 }