diff gcc/lto-symtab.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children f6334be47118
line wrap: on
line diff
--- a/gcc/lto-symtab.c	Fri Feb 12 23:41:23 2010 +0900
+++ b/gcc/lto-symtab.c	Mon May 24 12:47:05 2010 +0900
@@ -44,6 +44,9 @@
   /* The cgraph node if decl is a function decl.  Filled in during the
      merging process.  */
   struct cgraph_node *node;
+  /* The varpool node if decl is a variable decl.  Filled in during the
+     merging process.  */
+  struct varpool_node *vnode;
   /* LTO file-data and symbol resolution for this decl.  */
   struct lto_file_decl_data * GTY((skip (""))) file_data;
   enum ld_plugin_symbol_resolution resolution;
@@ -62,6 +65,15 @@
 	     param_is (struct lto_symtab_entry_def)))
   htab_t lto_symtab_identifiers;
 
+/* Free symtab hashtable.  */
+
+void
+lto_symtab_free (void)
+{
+  htab_delete (lto_symtab_identifiers);
+  lto_symtab_identifiers = NULL;
+}
+
 /* Return the hash value of an lto_symtab_entry_t object pointed to by P.  */
 
 static hashval_t
@@ -69,7 +81,7 @@
 {
   const struct lto_symtab_entry_def *base =
     (const struct lto_symtab_entry_def *) p;
-  return htab_hash_string (IDENTIFIER_POINTER (base->id));
+  return IDENTIFIER_HASH_VALUE (base->id);
 }
 
 /* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs
@@ -94,9 +106,10 @@
   const struct lto_symtab_entry_def *base =
      (const struct lto_symtab_entry_def *) p;
 
-  /* Keep this only if the decl or the chain is marked.  */
-  return (ggc_marked_p (base->decl)
-	  || (base->next && ggc_marked_p (base->next)));
+  /* Keep this only if the common IDENTIFIER_NODE of the symtab chain
+     is marked which it will be if at least one of the DECLs in the
+     chain is marked.  */
+  return ggc_marked_p (base->id);
 }
 
 /* Lazily initialize resolution hash tables.  */
@@ -211,15 +224,8 @@
       next = e->next_caller;
       cgraph_redirect_edge_callee (e, prevailing_node);
     }
-
-  /* There are not supposed to be any outgoing edges from a node we
-     replace.  Still this can happen for multiple instances of weak
-     functions.  */
-  for (e = node->callees; e; e = next)
-    {
-      next = e->next_callee;
-      cgraph_remove_edge (e);
-    }
+  /* Redirect incomming references.  */
+  ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
   if (node->same_body)
     {
@@ -244,6 +250,54 @@
   cgraph_remove_node (node);
 }
 
+/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
+   all edges and removing the old node.  */
+
+static void
+lto_varpool_replace_node (struct varpool_node *vnode,
+			  struct varpool_node *prevailing_node)
+{
+  /* Merge node flags.  */
+  if (vnode->needed)
+    {
+      gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
+      varpool_mark_needed_node (prevailing_node);
+    }
+  /* Relink aliases.  */
+  if (vnode->extra_name && !vnode->alias)
+    {
+      struct varpool_node *alias, *last;
+      for (alias = vnode->extra_name;
+	   alias; alias = alias->next)
+	{
+	  last = alias;
+	  alias->extra_name = prevailing_node;
+	}
+
+      if (prevailing_node->extra_name)
+	{
+	  last->next = prevailing_node->extra_name;
+	  prevailing_node->extra_name->prev = last;
+	}
+      prevailing_node->extra_name = vnode->extra_name;
+      vnode->extra_name = NULL;
+    }
+  gcc_assert (!vnode->finalized || prevailing_node->finalized);
+  gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
+
+  /* When replacing by an alias, the references goes to the original
+     variable.  */
+  if (prevailing_node->alias && prevailing_node->extra_name)
+    prevailing_node = prevailing_node->extra_name;
+  ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list);
+
+  /* Be sure we can garbage collect the initializer.  */
+  if (DECL_INITIAL (vnode->decl))
+    DECL_INITIAL (vnode->decl) = error_mark_node;
+  /* Finally remove the replaced node.  */
+  varpool_remove_node (vnode);
+}
+
 /* Merge two variable or function symbol table entries PREVAILING and ENTRY.
    Return false if the symbols are not fully compatible and a diagnostic
    should be emitted.  */
@@ -383,11 +437,13 @@
 
   /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
-    return (DECL_SIZE (e->decl) != NULL_TREE
-	    /* The C++ frontend retains TREE_STATIC on the declaration
-	       of foo_ in struct Foo { static Foo *foo_; }; but it is
-	       not a definition.  g++.dg/lto/20090315_0.C.  */
-	    && !DECL_EXTERNAL (e->decl));
+    {
+      if (!e->vnode)
+	return false;
+      if (e->vnode->finalized)
+	return true;
+      return e->vnode->alias && e->vnode->extra_name->finalized;
+    }
 
   gcc_unreachable ();
 }
@@ -406,6 +462,14 @@
     {
       if (TREE_CODE (e->decl) == FUNCTION_DECL)
 	e->node = cgraph_get_node (e->decl);
+      else if (TREE_CODE (e->decl) == VAR_DECL)
+	{
+	  e->vnode = varpool_get_node (e->decl);
+	  /* The LTO plugin for gold doesn't handle common symbols
+	     properly.  Let us choose manually.  */
+	  if (DECL_COMMON (e->decl))
+	    e->resolution = LDPR_UNKNOWN;
+	}
     }
 
   e = (lto_symtab_entry_t) *slot;
@@ -559,17 +623,22 @@
 	while (!prevailing->node
 	       && prevailing->next)
 	  prevailing = prevailing->next;
-      /* We do not stream varpool nodes, so the first decl has to
-	 be good enough for now.
-	 ???  For QOI choose a variable with readonly initializer
-	 if there is one.  This matches C++
-	 struct Foo { static const int i = 1; }; without a real
-	 definition.  */
+      /* For variables chose with a priority variant with vnode
+	 attached (i.e. from unit where external declaration of
+	 variable is actually used).
+	 When there are multiple variants, chose one with size.
+	 This is needed for C++ typeinfos, for example in
+	 lto/20081204-1 there are typeifos in both units, just
+	 one of them do have size.  */
       if (TREE_CODE (prevailing->decl) == VAR_DECL)
-	while (!(TREE_READONLY (prevailing->decl)
-		 && DECL_INITIAL (prevailing->decl))
-	       && prevailing->next)
-	  prevailing = prevailing->next;
+	{
+	  for (e = prevailing->next; e; e = e->next)
+	    if ((!prevailing->vnode && e->vnode)
+		|| ((prevailing->vnode != NULL) == (e->vnode != NULL)
+		    && !COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
+		    && COMPLETE_TYPE_P (TREE_TYPE (e->decl))))
+	      prevailing = e;
+	}
     }
 
   /* Move it first in the list.  */
@@ -625,7 +694,8 @@
   lto_symtab_merge_decls_2 (slot);
 
   /* Drop all but the prevailing decl from the symtab.  */
-  if (TREE_CODE (prevailing->decl) != FUNCTION_DECL)
+  if (TREE_CODE (prevailing->decl) != FUNCTION_DECL
+      && TREE_CODE (prevailing->decl) != VAR_DECL)
     prevailing->next = NULL;
 
   return 1;
@@ -650,8 +720,6 @@
   if (!prevailing->next)
     return 1;
 
-  gcc_assert (TREE_CODE (prevailing->decl) == FUNCTION_DECL);
-
   /* Replace the cgraph node of each entry with the prevailing one.  */
   for (e = prevailing->next; e; e = e->next)
     {
@@ -672,6 +740,8 @@
 	    }
 	  lto_cgraph_replace_node (e->node, prevailing->node);
 	}
+      if (e->vnode != NULL)
+	lto_varpool_replace_node (e->vnode, prevailing->vnode);
     }
 
   /* Drop all but the prevailing decl from the symtab.  */