OSDN Git Service

compiler: Move import of Go export data to gcc side of interface.
[pf3gnuchains/gcc-fork.git] / gcc / lto-symtab.c
index 732940e..68c6231 100644 (file)
@@ -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 @@ along with GCC; see the file COPYING3.  If not see
 #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 @@ struct GTY(()) lto_symtab_entry_def
   /* 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
@@ -65,6 +66,15 @@ static GTY ((if_marked ("lto_symtab_entry_marked_p"),
             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
@@ -72,7 +82,7 @@ lto_symtab_entry_hash (const void *p)
 {
   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
@@ -143,8 +153,9 @@ lto_symtab_register_decl (tree decl,
   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;
@@ -179,7 +190,8 @@ lto_symtab_get_resolution (tree decl)
 
   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)
@@ -197,6 +209,18 @@ lto_cgraph_replace_node (struct cgraph_node *node,
                         struct cgraph_node *prevailing_node)
 {
   struct cgraph_edge *e, *next;
+  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)))));
+    }
 
   /* Merge node flags.  */
   if (node->needed)
@@ -210,33 +234,23 @@ lto_cgraph_replace_node (struct cgraph_node *node,
     }
 
   /* Redirect all incoming edges.  */
+  compatible_p
+    = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)),
+                         TREE_TYPE (TREE_TYPE (node->decl)));
   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)
-    {
-      struct cgraph_node *alias;
-
-      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;
-               }
-         }
-    }
-
   /* Finally remove the replaced node.  */
   cgraph_remove_node (node);
 }
@@ -254,34 +268,14 @@ lto_varpool_replace_node (struct varpool_node *vnode,
       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);
 }
@@ -307,7 +301,8 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      if (TREE_TYPE (prevailing_decl) != TREE_TYPE (decl))
+      if (!types_compatible_p (TREE_TYPE (prevailing_decl),
+                              TREE_TYPE (decl)))
        /* 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
@@ -336,11 +331,7 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
   prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
   type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
 
-  /* We have to register and fetch canonical types here as the global
-     fixup process didn't yet run.  */
-  prevailing_type = gimple_register_type (prevailing_type);
-  type = gimple_register_type (type);
-  if (prevailing_type != type)
+  if (!types_compatible_p (prevailing_type, type))
     {
       if (COMPLETE_TYPE_P (type))
        return false;
@@ -365,7 +356,7 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
          if (TREE_CODE (tem1) != TREE_CODE (tem2))
            return false;
 
-         if (gimple_register_type (tem1) != gimple_register_type (tem2))
+         if (!types_compatible_p (tem1, tem2))
            return false;
        }
 
@@ -398,6 +389,7 @@ lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
 {
   if (DECL_EXTERNAL (e->decl)
       || DECL_COMDAT (e->decl)
+      || DECL_ONE_ONLY (e->decl)
       || DECL_WEAK (e->decl))
     return true;
 
@@ -423,14 +415,11 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
     return (e->node && e->node->analyzed);
 
-  /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
     {
       if (!e->vnode)
        return false;
-      if (e->vnode->finalized)
-       return true;
-      return e->vnode->alias && e->vnode->extra_name->finalized;
+      return e->vnode->finalized;
     }
 
   gcc_unreachable ();
@@ -452,12 +441,14 @@ lto_symtab_resolve_symbols (void **slot)
        e->node = cgraph_get_node (e->decl);
       else if (TREE_CODE (e->decl) == VAR_DECL)
        e->vnode = varpool_get_node (e->decl);
+      if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
+         || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+         || e->resolution == LDPR_PREVAILING_DEF)
+       prevailing = e;
     }
 
-  e = (lto_symtab_entry_t) *slot;
-
   /* If the chain is already resolved there is nothing else to do.  */
-  if (e->resolution != LDPR_UNKNOWN)
+  if (prevailing)
     return;
 
   /* Find the single non-replaceable prevailing symbol and
@@ -467,12 +458,14 @@ lto_symtab_resolve_symbols (void **slot)
       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)
@@ -512,24 +505,34 @@ lto_symtab_resolve_symbols (void **slot)
     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;
@@ -539,16 +542,17 @@ lto_symtab_merge_decls_2 (void **slot)
   /* 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 (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl)))
        diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
                                   "type of %qD does not match original "
                                   "declaration", decl);
@@ -584,6 +588,7 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
   for (prevailing = (lto_symtab_entry_t) *slot;
        prevailing
        && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY
+       && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
        && prevailing->resolution != LDPR_PREVAILING_DEF;
        prevailing = prevailing->next)
     ;
@@ -591,8 +596,13 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
   /* 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_IRONLY_EXP
+           || 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
@@ -667,19 +677,25 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
       inform (DECL_SOURCE_LOCATION (prevailing->decl),
              "previously declared here");
 
-  /* Register and adjust types of the entries.  */
-  for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
-    TREE_TYPE (e->decl) = gimple_register_type (TREE_TYPE (e->decl));
-
   /* Merge the chain to the single prevailing decl and diagnose
      mismatches.  */
-  lto_symtab_merge_decls_2 (slot);
-
-  /* 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;
-
+  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.
+
+     The problem with storing guessed decision is whether to use
+     PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
+     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;
 }
 
@@ -707,23 +723,25 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
     {
       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_create_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.  */
@@ -738,8 +756,18 @@ lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
 void
 lto_symtab_merge_cgraph_nodes (void)
 {
+  struct cgraph_node *node;
+  struct varpool_node *vnode;
   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)
+    if ((node->thunk.thunk_p || node->alias)
+       && node->thunk.alias)
+      node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
+  for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+    if (vnode->alias_of)
+      vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
 }
 
 /* Given the decl DECL, return the prevailing decl with the same name. */
@@ -761,7 +789,8 @@ lto_symtab_prevailing_decl (tree decl)
   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;