diff gcc/lto-symtab.c @ 67:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children
line wrap: on
line diff
--- a/gcc/lto-symtab.c	Tue May 25 18:58:51 2010 +0900
+++ b/gcc/lto-symtab.c	Tue Mar 22 17:18:12 2011 +0900
@@ -1,5 +1,5 @@
 /* LTO symbol table.
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -21,11 +21,10 @@
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "tree.h"
 #include "gimple.h"
-#include "ggc.h"	/* lambda.h needs this */
-#include "lambda.h"	/* gcd */
+#include "ggc.h"
 #include "hashtab.h"
 #include "plugin-api.h"
 #include "lto-streamer.h"
@@ -50,6 +49,8 @@
   /* LTO file-data and symbol resolution for this decl.  */
   struct lto_file_decl_data * GTY((skip (""))) file_data;
   enum ld_plugin_symbol_resolution resolution;
+  /* True when resolution was guessed and not read from the file.  */
+  bool guessed;
   /* Pointer to the next entry with the same key.  Before decl merging
      this links all symbols from the different TUs.  After decl merging
      this links merged but incompatible decls, thus all prevailing ones
@@ -152,8 +153,9 @@
   if (TREE_CODE (decl) == FUNCTION_DECL)
     gcc_assert (!DECL_ABSTRACT (decl));
 
-  new_entry = GGC_CNEW (struct lto_symtab_entry_def);
-  new_entry->id = DECL_ASSEMBLER_NAME (decl);
+  new_entry = ggc_alloc_cleared_lto_symtab_entry_def ();
+  new_entry->id = (*targetm.asm_out.mangle_assembler_name)
+		  (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
   new_entry->decl = decl;
   new_entry->resolution = resolution;
   new_entry->file_data = file_data;
@@ -188,7 +190,8 @@
 
   gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
 
-  e = lto_symtab_get (DECL_ASSEMBLER_NAME (decl));
+  e = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
+		      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
   while (e && e->decl != decl)
     e = e->next;
   if (!e)
@@ -206,6 +209,26 @@
 			 struct cgraph_node *prevailing_node)
 {
   struct cgraph_edge *e, *next;
+  bool no_aliases_please = false;
+  bool compatible_p;
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i"
+ 	       " for symbol %s\n",
+	       cgraph_node_name (node), node->uid,
+	       cgraph_node_name (prevailing_node),
+	       prevailing_node->uid,
+	       IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name)
+		 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)))));
+    }
+
+  if (prevailing_node->same_body_alias)
+    {
+      if (prevailing_node->thunk.thunk_p)
+	no_aliases_please = true;
+      prevailing_node = prevailing_node->same_body;
+    }
 
   /* Merge node flags.  */
   if (node->needed)
@@ -219,35 +242,53 @@
     }
 
   /* Redirect all incoming edges.  */
+  compatible_p
+    = gimple_types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)),
+				 TREE_TYPE (TREE_TYPE (node->decl)), GTC_DIAG);
   for (e = node->callers; e; e = next)
     {
       next = e->next_caller;
       cgraph_redirect_edge_callee (e, prevailing_node);
+      /* If there is a mismatch between the supposed callee return type and
+	 the real one do not attempt to inline this function.
+	 ???  We really need a way to match function signatures for ABI
+	 compatibility and perform related promotions at inlining time.  */
+      if (!compatible_p)
+	e->call_stmt_cannot_inline_p = 1;
     }
   /* Redirect incomming references.  */
   ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
-  if (node->same_body)
+  /* If we have aliases, redirect them to the prevailing node.  */
+  if (!node->same_body_alias && node->same_body)
     {
-      struct cgraph_node *alias;
+      struct cgraph_node *alias, *last;
+      /* We prevail aliases/tunks by a thunk.  This is doable but
+         would need thunk combination.  Hopefully no ABI changes will
+         every be crazy enough.  */
+      gcc_assert (!no_aliases_please);
 
       for (alias = node->same_body; alias; alias = alias->next)
-	if (DECL_ASSEMBLER_NAME_SET_P (alias->decl))
-	  {
-	    lto_symtab_entry_t se
-	      = lto_symtab_get (DECL_ASSEMBLER_NAME (alias->decl));
-
-	    for (; se; se = se->next)
-	      if (se->node == node)
-		{
-		  se->node = NULL;
-		  break;
-		}
-	  }
+	{
+	  last = alias;
+	  gcc_assert (alias->same_body_alias);
+	  alias->same_body = prevailing_node;
+	}
+      last->next = prevailing_node->same_body;
+      /* Node with aliases is prevailed by alias.
+	 We could handle this, but combining thunks together will be tricky.
+	 Hopefully this does not happen.  */
+      if (prevailing_node->same_body)
+	prevailing_node->same_body->previous = last;
+      prevailing_node->same_body = node->same_body;
+      node->same_body = NULL;
     }
 
   /* Finally remove the replaced node.  */
-  cgraph_remove_node (node);
+  if (node->same_body_alias)
+    cgraph_remove_same_body_alias (node);
+  else
+    cgraph_remove_node (node);
 }
 
 /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
@@ -319,7 +360,8 @@
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      if (TREE_TYPE (prevailing_decl) != TREE_TYPE (decl))
+      if (!gimple_types_compatible_p (TREE_TYPE (prevailing_decl),
+				      TREE_TYPE (decl), GTC_DIAG))
 	/* If we don't have a merged type yet...sigh.  The linker
 	   wouldn't complain if the types were mismatched, so we
 	   probably shouldn't either.  Just use the type from
@@ -352,7 +394,7 @@
      fixup process didn't yet run.  */
   prevailing_type = gimple_register_type (prevailing_type);
   type = gimple_register_type (type);
-  if (prevailing_type != type)
+  if (!gimple_types_compatible_p (prevailing_type, type, GTC_DIAG))
     {
       if (COMPLETE_TYPE_P (type))
 	return false;
@@ -377,7 +419,9 @@
 	  if (TREE_CODE (tem1) != TREE_CODE (tem2))
 	    return false;
 
-	  if (gimple_register_type (tem1) != gimple_register_type (tem2))
+	  if (!gimple_types_compatible_p (gimple_register_type (tem1),
+					  gimple_register_type (tem2),
+					  GTC_DIAG))
 	    return false;
 	}
 
@@ -410,6 +454,7 @@
 {
   if (DECL_EXTERNAL (e->decl)
       || DECL_COMDAT (e->decl)
+      || DECL_ONE_ONLY (e->decl)
       || DECL_WEAK (e->decl))
     return true;
 
@@ -433,7 +478,9 @@
 
   /* For functions we need a non-discarded body.  */
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
-    return (e->node && e->node->analyzed);
+    return (e->node
+	    && (e->node->analyzed
+	        || (e->node->same_body_alias && e->node->same_body->analyzed)));
 
   /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
@@ -461,15 +508,9 @@
   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
     {
       if (TREE_CODE (e->decl) == FUNCTION_DECL)
-	e->node = cgraph_get_node (e->decl);
+	e->node = cgraph_get_node_or_alias (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->vnode = varpool_get_node (e->decl);
     }
 
   e = (lto_symtab_entry_t) *slot;
@@ -485,12 +526,14 @@
       if (!lto_symtab_resolve_can_prevail_p (e))
 	{
 	  e->resolution = LDPR_RESOLVED_IR;
+          e->guessed = true;
 	  continue;
 	}
 
       /* Set a default resolution - the final prevailing one will get
          adjusted later.  */
       e->resolution = LDPR_PREEMPTED_IR;
+      e->guessed = true;
       if (!lto_symtab_resolve_replaceable_p (e))
 	{
 	  if (prevailing)
@@ -530,24 +573,34 @@
     return;
 
 found:
-  if (TREE_CODE (prevailing->decl) == VAR_DECL
-      && TREE_READONLY (prevailing->decl))
+  /* If current lto files represent the whole program,
+    it is correct to use LDPR_PREVALING_DEF_IRONLY.
+    If current lto files are part of whole program, internal
+    resolver doesn't know if it is LDPR_PREVAILING_DEF
+    or LDPR_PREVAILING_DEF_IRONLY.  Use IRONLY conforms to
+    using -fwhole-program.  Otherwise, it doesn't
+    matter using either LDPR_PREVAILING_DEF or
+    LDPR_PREVAILING_DEF_IRONLY
+    
+    FIXME: above workaround due to gold plugin makes some
+    variables IRONLY, which are indeed PREVAILING_DEF in
+    resolution file.  These variables still need manual
+    externally_visible attribute.  */
     prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY;
-  else
-    prevailing->resolution = LDPR_PREVAILING_DEF;
+    prevailing->guessed = true;
 }
 
 /* Merge all decls in the symbol table chain to the prevailing decl and
-   issue diagnostics about type mismatches.  */
+   issue diagnostics about type mismatches.  If DIAGNOSED_P is true
+   do not issue further diagnostics.*/
 
 static void
-lto_symtab_merge_decls_2 (void **slot)
+lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
 {
   lto_symtab_entry_t prevailing, e;
   VEC(tree, heap) *mismatches = NULL;
   unsigned i;
   tree decl;
-  bool diagnosed_p = false;
 
   /* Nothing to do for a single entry.  */
   prevailing = (lto_symtab_entry_t) *slot;
@@ -557,16 +610,18 @@
   /* Try to merge each entry with the prevailing one.  */
   for (e = prevailing->next; e; e = e->next)
     {
-      if (!lto_symtab_merge (prevailing, e))
+      if (!lto_symtab_merge (prevailing, e)
+	  && !diagnosed_p)
 	VEC_safe_push (tree, heap, mismatches, e->decl);
     }
   if (VEC_empty (tree, mismatches))
     return;
 
   /* Diagnose all mismatched re-declarations.  */
-  for (i = 0; VEC_iterate (tree, mismatches, i, decl); ++i)
+  FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
     {
-      if (TREE_TYPE (prevailing->decl) != TREE_TYPE (decl))
+      if (!gimple_types_compatible_p (TREE_TYPE (prevailing->decl),
+				      TREE_TYPE (decl), GTC_DIAG))
 	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
 				   "type of %qD does not match original "
 				   "declaration", decl);
@@ -609,8 +664,12 @@
   /* Assert it's the only one.  */
   if (prevailing)
     for (e = prevailing->next; e; e = e->next)
-      gcc_assert (e->resolution != LDPR_PREVAILING_DEF_IRONLY
-		  && e->resolution != LDPR_PREVAILING_DEF);
+      {
+	if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
+	    || e->resolution == LDPR_PREVAILING_DEF)
+	  fatal_error ("multiple prevailing defs for %qE",
+		       DECL_NAME (prevailing->decl));
+      }
 
   /* If there's not a prevailing symbol yet it's an external reference.
      Happens a lot during ltrans.  Choose the first symbol with a
@@ -691,13 +750,23 @@
 
   /* Merge the chain to the single prevailing decl and diagnose
      mismatches.  */
-  lto_symtab_merge_decls_2 (slot);
+  lto_symtab_merge_decls_2 (slot, diagnosed_p);
+
+  /* Store resolution decision into the callgraph.  
+     In LTRANS don't overwrite information we stored into callgraph at
+     WPA stage.
+
+     Do not bother to store guessed decisions.  Generic code knows how
+     to handle UNKNOWN relocation well.
 
-  /* Drop all but the prevailing decl from the symtab.  */
-  if (TREE_CODE (prevailing->decl) != FUNCTION_DECL
-      && TREE_CODE (prevailing->decl) != VAR_DECL)
-    prevailing->next = NULL;
-
+     The problem with storing guessed decision is whether to use
+     PREVAILING_DEF or PREVAILING_DEF_IRONLY.  First one would disable
+     some whole program optimizations, while ther second would imply
+     to many whole program assumptions.  */
+  if (prevailing->node && !flag_ltrans && !prevailing->guessed)
+    prevailing->node->resolution = prevailing->resolution;
+  else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed)
+    prevailing->vnode->resolution = prevailing->resolution;
   return 1;
 }
 
@@ -725,23 +794,25 @@
     {
       if (e->node != NULL)
 	{
-	  if (e->node->decl != e->decl && e->node->same_body)
+	  /* In case we prevail funcion by an alias, we can run into case
+	     that the alias has no cgraph node attached, since it was
+	     previously unused.  Create the node.  */
+	  if (!prevailing->node)
 	    {
-	      struct cgraph_node *alias;
-
-	      for (alias = e->node->same_body; alias; alias = alias->next)
-		if (alias->decl == e->decl)
-		  break;
-	      if (alias)
-		{
-		  cgraph_remove_same_body_alias (alias);
-		  continue;
-		}
+	      prevailing->node = cgraph_node (prevailing->decl);
+	      prevailing->node->alias = true;
 	    }
 	  lto_cgraph_replace_node (e->node, prevailing->node);
 	}
       if (e->vnode != NULL)
-	lto_varpool_replace_node (e->vnode, prevailing->vnode);
+	{
+	  if (!prevailing->vnode)
+	    {
+	      prevailing->vnode = varpool_node (prevailing->decl);
+	      prevailing->vnode->alias = true;
+	    }
+	  lto_varpool_replace_node (e->vnode, prevailing->vnode);
+	}
     }
 
   /* Drop all but the prevailing decl from the symtab.  */
@@ -756,8 +827,16 @@
 void
 lto_symtab_merge_cgraph_nodes (void)
 {
+  struct cgraph_node *node, *alias, *next;
   lto_symtab_maybe_init_hash_table ();
   htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+
+  for (node = cgraph_nodes; node; node = node->next)
+    for (alias = node->same_body; alias; alias = next)
+      {
+	next = alias->next;
+	alias->thunk.alias = lto_symtab_prevailing_decl (alias->thunk.alias);
+      }
 }
 
 /* Given the decl DECL, return the prevailing decl with the same name. */
@@ -779,7 +858,8 @@
   gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
 
   /* Walk through the list of candidates and return the one we merged to.  */
-  ret = lto_symtab_get (DECL_ASSEMBLER_NAME (decl));
+  ret = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
+			(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
   if (!ret)
     return NULL_TREE;