OSDN Git Service

2010-09-09 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / lto-symtab.c
index 2758751..bdfbd7d 100644 (file)
@@ -21,10 +21,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "tree.h"
 #include "gimple.h"
-#include "ggc.h"       /* lambda.h needs this */
+#include "ggc.h"
 #include "lambda.h"    /* gcd */
 #include "hashtab.h"
 #include "plugin-api.h"
@@ -41,6 +42,12 @@ struct GTY(()) lto_symtab_entry_def
   tree id;
   /* The symbol table entry, a DECL.  */
   tree decl;
+  /* 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;
@@ -59,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
@@ -66,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
@@ -83,7 +99,7 @@ lto_symtab_entry_eq (const void *p1, const void *p2)
 }
 
 /* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
-   to be marked for GC.  */ 
+   to be marked for GC.  */
 
 static int
 lto_symtab_entry_marked_p (const void *p)
@@ -91,9 +107,10 @@ lto_symtab_entry_marked_p (const void *p)
   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.  */
@@ -136,7 +153,7 @@ 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 = ggc_alloc_cleared_lto_symtab_entry_def ();
   new_entry->id = DECL_ASSEMBLER_NAME (decl);
   new_entry->decl = decl;
   new_entry->resolution = resolution;
@@ -190,6 +207,24 @@ lto_cgraph_replace_node (struct cgraph_node *node,
                         struct cgraph_node *prevailing_node)
 {
   struct cgraph_edge *e, *next;
+  bool no_aliases_please = false;
+
+  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 (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)
@@ -208,18 +243,88 @@ lto_cgraph_replace_node (struct cgraph_node *node,
       next = e->next_caller;
       cgraph_redirect_edge_callee (e, prevailing_node);
     }
+  /* Redirect incomming references.  */
+  ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
-  /* 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)
+  /* If we have aliases, redirect them to the prevailing node.  */
+  if (!node->same_body_alias && node->same_body)
     {
-      next = e->next_callee;
-      cgraph_remove_edge (e);
+      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)
+       {
+         last = alias;
+         gcc_assert (alias->same_body_alias);
+         alias->same_body = prevailing_node;
+         alias->thunk.alias = prevailing_node->decl;
+       }
+      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
+   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.
@@ -232,24 +337,19 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
   tree prevailing_decl = prevailing->decl;
   tree decl = entry->decl;
   tree prevailing_type, type;
-  struct cgraph_node *node;
 
   /* Merge decl state in both directions, we may still end up using
      the new decl.  */
   TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
   TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl);
 
-  /* Replace a cgraph node of entry with the prevailing one.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && (node = cgraph_get_node (decl)) != NULL)
-    lto_cgraph_replace_node (node, cgraph_get_node (prevailing_decl));
-
   /* The linker may ask us to combine two incompatible symbols.
      Detect this case and notify the caller of required diagnostics.  */
 
   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
@@ -282,7 +382,7 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
      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;
@@ -307,7 +407,9 @@ 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 (!gimple_types_compatible_p (gimple_register_type (tem1),
+                                         gimple_register_type (tem2),
+                                         GTC_DIAG))
            return false;
        }
 
@@ -355,23 +457,27 @@ lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
 static bool
 lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
 {
-  struct cgraph_node *node;
-
-  if (!TREE_STATIC (e->decl))
+  /* The C++ frontend ends up neither setting TREE_STATIC nor
+     DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
+     So do not reject !TREE_STATIC here but only DECL_EXTERNAL.  */
+  if (DECL_EXTERNAL (e->decl))
     return false;
 
   /* For functions we need a non-discarded body.  */
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
-    return ((node = cgraph_get_node (e->decl))
-           && 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)
-    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 ();
 }
@@ -382,16 +488,27 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
 static void
 lto_symtab_resolve_symbols (void **slot)
 {
-  lto_symtab_entry_t e = (lto_symtab_entry_t) *slot;
+  lto_symtab_entry_t e;
   lto_symtab_entry_t prevailing = NULL;
 
-  /* If the chain is already resolved there is nothing to do.  */
+  /* Always set e->node so that edges are updated to reflect decl merging. */
+  for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+    {
+      if (TREE_CODE (e->decl) == FUNCTION_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);
+    }
+
+  e = (lto_symtab_entry_t) *slot;
+
+  /* If the chain is already resolved there is nothing else to do.  */
   if (e->resolution != LDPR_UNKNOWN)
     return;
 
   /* Find the single non-replaceable prevailing symbol and
      diagnose ODR violations.  */
-  for (; e; e = e->next)
+  for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
     {
       if (!lto_symtab_resolve_can_prevail_p (e))
        {
@@ -441,11 +558,20 @@ 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;
 }
 
 /* Merge all decls in the symbol table chain to the prevailing decl and
@@ -475,9 +601,10 @@ lto_symtab_merge_decls_2 (void **slot)
     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);
@@ -520,8 +647,12 @@ 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)
+         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
@@ -531,20 +662,25 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
       prevailing = (lto_symtab_entry_t) *slot;
       /* For functions choose one with a cgraph node.  */
       if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
-       while (!cgraph_get_node (prevailing->decl)
+       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.  */
@@ -600,8 +736,31 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
   lto_symtab_merge_decls_2 (slot);
 
   /* Drop all but the prevailing decl from the symtab.  */
-  prevailing->next = NULL;
-
+  if (TREE_CODE (prevailing->decl) != FUNCTION_DECL
+      && TREE_CODE (prevailing->decl) != VAR_DECL)
+    prevailing->next = NULL;
+
+  /* Set used_from_object_file flags.  */
+  if (prevailing->resolution == LDPR_PREVAILING_DEF
+      || prevailing->resolution == LDPR_PREEMPTED_REG
+      || prevailing->resolution == LDPR_RESOLVED_EXEC
+      || prevailing->resolution == LDPR_RESOLVED_DYN)
+    {
+      if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
+       {
+         if (prevailing->node->same_body_alias)
+           prevailing->node->same_body->local.used_from_object_file = true;
+         else
+           prevailing->node->local.used_from_object_file = true;
+       }
+      else
+       {
+         if (prevailing->vnode->alias)
+           prevailing->vnode->extra_name->used_from_object_file = true;
+         else
+           prevailing->vnode->used_from_object_file = true;
+       }
+    }
   return 1;
 }
 
@@ -614,6 +773,40 @@ lto_symtab_merge_decls (void)
   htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
 }
 
+/* Helper to process the decl chain for the symbol table entry *SLOT.  */
+
+static int
+lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+  lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
+
+  if (!prevailing->next)
+    return 1;
+
+  /* Replace the cgraph node of each entry with the prevailing one.  */
+  for (e = prevailing->next; e; e = e->next)
+    {
+      if (e->node != NULL)
+       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.  */
+  prevailing->next = NULL;
+
+  return 1;
+}
+
+/* Merge cgraph nodes according to the symbol merging done by
+   lto_symtab_merge_decls.  */
+
+void
+lto_symtab_merge_cgraph_nodes (void)
+{
+  lto_symtab_maybe_init_hash_table ();
+  htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+}
 
 /* Given the decl DECL, return the prevailing decl with the same name. */
 
@@ -641,53 +834,4 @@ lto_symtab_prevailing_decl (tree decl)
   return ret->decl;
 }
 
-/* Remove any storage used to store resolution of DECL.  */
-
-void
-lto_symtab_clear_resolution (tree decl)
-{
-  struct lto_symtab_entry_def temp;
-  lto_symtab_entry_t head;
-  void **slot;
-
-  if (!TREE_PUBLIC (decl))
-    return;
-
-  /* LTO FIXME: There should be no DECL_ABSTRACT in the middle end. */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
-    return;
-
-  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-
-  lto_symtab_maybe_init_hash_table ();
-  temp.id = DECL_ASSEMBLER_NAME (decl);
-  slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
-  if (!*slot)
-    return;
-
-  head = (lto_symtab_entry_t) *slot;
-  if (head->decl == decl)
-    {
-      if (head->next)
-       {
-         *slot = head->next;
-         head->next = NULL;
-       }
-      else
-       htab_remove_elt (lto_symtab_identifiers, &temp);
-    }
-  else
-    {
-      lto_symtab_entry_t e;
-      while (head->next && head->next->decl != decl)
-       head = head->next;
-      if (head->next)
-       {
-         e = head->next;
-         head->next = e->next;
-         e->next = NULL;
-       }
-    }
-}
-
 #include "gt-lto-symtab.h"