lto-streamer.h (lto_global_var_decls): Remove.
authorRichard Biener <rguenther@suse.de>
Fri, 6 Sep 2013 09:06:25 +0000 (09:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 6 Sep 2013 09:06:25 +0000 (09:06 +0000)
2013-09-06  Richard Biener  <rguenther@suse.de>

* lto-streamer.h (lto_global_var_decls): Remove.
* Makefile.in (OBJS): Remove lto-symtab.o.
(lto-symtab.o): Remove.
(GTFILES): Remove lto-symtab.c
* lto-symtab.c: Move to lto/

lto/
* lto-symtab.c: Move from gcc/
* lto.h: Include vec.h.
(lto_global_var_decls): Declare.
* lto.c (lto_global_var_decls): Move definition here.
* Make-lang.in (LTO_OBJS): Add lto-symtab.o.
(lto-symtab.o): Add.
* config-lang.in (gtfiles): Add lto.h.

From-SVN: r202313

gcc/ChangeLog
gcc/Makefile.in
gcc/lto-streamer.h
gcc/lto-symtab.c [deleted file]
gcc/lto/ChangeLog
gcc/lto/Make-lang.in
gcc/lto/config-lang.in
gcc/lto/lto-symtab.c [new file with mode: 0644]
gcc/lto/lto.c
gcc/lto/lto.h

index 252b2611a4e135c55c3aeb0c4bf020ba4750f2f1..185c8655b944d49ff3bbde9d6ec48ef241a4df7a 100644 (file)
@@ -1,3 +1,11 @@
+2013-09-06  Richard Biener  <rguenther@suse.de>
+
+       * lto-streamer.h (lto_global_var_decls): Remove.
+       * Makefile.in (OBJS): Remove lto-symtab.o.
+       (lto-symtab.o): Remove.
+       (GTFILES): Remove lto-symtab.c
+       * lto-symtab.c: Move to lto/
+
 2013-09-06  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
        * config/s390/s390.md (UNSPEC_FPINT_FLOOR, UNSPEC_FPINT_BTRUNC)
index 87a09ba4d000ef455117706e037d4b7fac5bb695..4fdf5cbbda01520b650090436e594169eaaa8d53 100644 (file)
@@ -1320,7 +1320,6 @@ OBJS = \
        lto-streamer-out.o \
        lto-section-in.o \
        lto-section-out.o \
-       lto-symtab.o \
        lto-opts.o \
        lto-compress.o \
        mcf.o \
@@ -2220,9 +2219,6 @@ lto-section-out.o : lto-section-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(EXCEPT_H) pointer-set.h \
    $(BITMAP_H) langhooks.h $(LTO_STREAMER_H) lto-compress.h \
    $(DATA_STREAMER_H)
-lto-symtab.o: lto-symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   $(TREE_H) $(GIMPLE_H) $(GGC_H) $(HASHTAB_H) \
-   $(LTO_STREAMER_H) $(LINKER_PLUGIN_API_H)
 lto-opts.o: lto-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
    $(HASHTAB_H) $(GGC_H) $(BITMAP_H) $(FLAGS_H) $(OPTS_H) $(OPTIONS_H) \
    $(COMMON_TARGET_H) $(DIAGNOSTIC_H) $(LTO_STREAMER_H)
@@ -3839,7 +3835,6 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/cgraphclones.c \
   $(srcdir)/tree-ssa-propagate.c \
   $(srcdir)/tree-phinodes.c \
-  $(srcdir)/lto-symtab.c \
   $(srcdir)/tree-ssa-alias.h \
   $(srcdir)/ipa-prop.h \
   $(srcdir)/trans-mem.c \
index 4a2ea0b2993d659d0840b4e414fba1eb927173d1..13a9593a866597b920fb4cb6beb751f31cea0479 100644 (file)
@@ -903,7 +903,6 @@ lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
 extern void lto_symtab_merge_decls (void);
 extern void lto_symtab_merge_symbols (void);
 extern tree lto_symtab_prevailing_decl (tree decl);
-extern GTY(()) vec<tree, va_gc> *lto_global_var_decls;
 
 
 /* In lto-opts.c.  */
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
deleted file mode 100644 (file)
index 76e9440..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-/* LTO symbol table.
-   Copyright (C) 2009-2013 Free Software Foundation, Inc.
-   Contributed by CodeSourcery, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3.  If not see
-<http://www.gnu.org/licenses/>.  */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "diagnostic-core.h"
-#include "tree.h"
-#include "gimple.h"
-#include "ggc.h"
-#include "hashtab.h"
-#include "plugin-api.h"
-#include "lto-streamer.h"
-#include "ipa-utils.h"
-
-/* Vector to keep track of external variables we've seen so far.  */
-vec<tree, va_gc> *lto_global_var_decls;
-
-/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
-   all edges and removing the old node.  */
-
-static void
-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->symbol.order,
-              cgraph_node_name (prevailing_node),
-              prevailing_node->symbol.order,
-              IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name)
-                (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl)))));
-    }
-
-  /* Merge node flags.  */
-  if (node->symbol.force_output)
-    cgraph_mark_force_output_node (prevailing_node);
-  if (node->symbol.address_taken)
-    {
-      gcc_assert (!prevailing_node->global.inlined_to);
-      cgraph_mark_address_taken_node (prevailing_node);
-    }
-
-  /* Redirect all incoming edges.  */
-  compatible_p
-    = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->symbol.decl)),
-                         TREE_TYPE (TREE_TYPE (node->symbol.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_referring ((symtab_node)prevailing_node, &node->symbol.ref_list);
-
-  ipa_merge_profiles (prevailing_node, node);
-  lto_free_function_in_decl_state_for_node ((symtab_node)node);
-
-  if (node->symbol.decl != prevailing_node->symbol.decl)
-    cgraph_release_function_body (node);
-
-  /* Finally remove the replaced node.  */
-  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)
-{
-  gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition);
-  gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed);
-
-  ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
-
-  /* Be sure we can garbage collect the initializer.  */
-  if (DECL_INITIAL (vnode->symbol.decl)
-      && vnode->symbol.decl != prevailing_node->symbol.decl)
-    DECL_INITIAL (vnode->symbol.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.  */
-
-static bool
-lto_symtab_merge (symtab_node prevailing, symtab_node entry)
-{
-  tree prevailing_decl = prevailing->symbol.decl;
-  tree decl = entry->symbol.decl;
-  tree prevailing_type, type;
-
-  if (prevailing_decl == decl)
-    return true;
-
-  /* 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);
-
-  /* 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 (!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
-          whichever decl appears to be associated with the
-          definition.  If for some odd reason neither decl is, the
-          older one wins.  */
-       (void) 0;
-
-      return true;
-    }
-
-  /* Now we exclusively deal with VAR_DECLs.  */
-
-  /* Sharing a global symbol is a strong hint that two types are
-     compatible.  We could use this information to complete
-     incomplete pointed-to types more aggressively here, ignoring
-     mismatches in both field and tag names.  It's difficult though
-     to guarantee that this does not have side-effects on merging
-     more compatible types from other translation units though.  */
-
-  /* We can tolerate differences in type qualification, the
-     qualification of the prevailing definition will prevail.
-     ???  In principle we might want to only warn for structurally
-     incompatible types here, but unless we have protective measures
-     for TBAA in place that would hide useful information.  */
-  prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
-  type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
-
-  if (!types_compatible_p (prevailing_type, type))
-    {
-      if (COMPLETE_TYPE_P (type))
-       return false;
-
-      /* If type is incomplete then avoid warnings in the cases
-        that TBAA handles just fine.  */
-
-      if (TREE_CODE (prevailing_type) != TREE_CODE (type))
-       return false;
-
-      if (TREE_CODE (prevailing_type) == ARRAY_TYPE)
-       {
-         tree tem1 = TREE_TYPE (prevailing_type);
-         tree tem2 = TREE_TYPE (type);
-         while (TREE_CODE (tem1) == ARRAY_TYPE
-                && TREE_CODE (tem2) == ARRAY_TYPE)
-           {
-             tem1 = TREE_TYPE (tem1);
-             tem2 = TREE_TYPE (tem2);
-           }
-
-         if (TREE_CODE (tem1) != TREE_CODE (tem2))
-           return false;
-
-         if (!types_compatible_p (tem1, tem2))
-           return false;
-       }
-
-      /* Fallthru.  Compatible enough.  */
-    }
-
-  /* ???  We might want to emit a warning here if type qualification
-     differences were spotted.  Do not do this unconditionally though.  */
-
-  /* There is no point in comparing too many details of the decls here.
-     The type compatibility checks or the completing of types has properly
-     dealt with most issues.  */
-
-  /* The following should all not invoke fatal errors as in non-LTO
-     mode the linker wouldn't complain either.  Just emit warnings.  */
-
-  /* Report a warning if user-specified alignments do not match.  */
-  if ((DECL_USER_ALIGN (prevailing_decl) && DECL_USER_ALIGN (decl))
-      && DECL_ALIGN (prevailing_decl) < DECL_ALIGN (decl))
-    return false;
-
-  return true;
-}
-
-/* Return true if the symtab entry E can be replaced by another symtab
-   entry.  */
-
-static bool
-lto_symtab_resolve_replaceable_p (symtab_node e)
-{
-  if (DECL_EXTERNAL (e->symbol.decl)
-      || DECL_COMDAT (e->symbol.decl)
-      || DECL_ONE_ONLY (e->symbol.decl)
-      || DECL_WEAK (e->symbol.decl))
-    return true;
-
-  if (TREE_CODE (e->symbol.decl) == VAR_DECL)
-    return (DECL_COMMON (e->symbol.decl)
-           || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
-
-  return false;
-}
-
-/* Return true, if the symbol E should be resolved by lto-symtab.
-   Those are all external symbols and all real symbols that are not static (we
-   handle renaming of static later in partitioning).  */
-
-static bool
-lto_symtab_symbol_p (symtab_node e)
-{
-  if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl))
-    return false;
-  return symtab_real_symbol_p (e);
-}
-
-/* Return true if the symtab entry E can be the prevailing one.  */
-
-static bool
-lto_symtab_resolve_can_prevail_p (symtab_node e)
-{
-  if (!lto_symtab_symbol_p (e))
-    return false;
-
-  /* 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->symbol.decl))
-    return false;
-
-  return e->symbol.definition;
-}
-
-/* Resolve the symbol with the candidates in the chain *SLOT and store
-   their resolutions.  */
-
-static symtab_node
-lto_symtab_resolve_symbols (symtab_node first)
-{
-  symtab_node e;
-  symtab_node prevailing = NULL;
-
-  /* Always set e->node so that edges are updated to reflect decl merging. */
-  for (e = first; e; e = e->symbol.next_sharing_asm_name)
-    if (lto_symtab_symbol_p (e)
-       && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
-           || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
-           || e->symbol.resolution == LDPR_PREVAILING_DEF))
-      {
-       prevailing = e;
-       break;
-      }
-
-  /* If the chain is already resolved there is nothing else to do.  */
-  if (prevailing)
-    {
-      /* Assert it's the only one.  */
-      for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
-       if (lto_symtab_symbol_p (e)
-           && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
-               || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
-               || e->symbol.resolution == LDPR_PREVAILING_DEF))
-         fatal_error ("multiple prevailing defs for %qE",
-                      DECL_NAME (prevailing->symbol.decl));
-      return prevailing;
-    }
-
-  /* Find the single non-replaceable prevailing symbol and
-     diagnose ODR violations.  */
-  for (e = first; e; e = e->symbol.next_sharing_asm_name)
-    {
-      if (!lto_symtab_resolve_can_prevail_p (e))
-       continue;
-
-      /* If we have a non-replaceable definition it prevails.  */
-      if (!lto_symtab_resolve_replaceable_p (e))
-       {
-         if (prevailing)
-           {
-             error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
-                       "%qD has already been defined", e->symbol.decl);
-             inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
-                     "previously defined here");
-           }
-         prevailing = e;
-       }
-    }
-  if (prevailing)
-    return prevailing;
-
-  /* Do a second round choosing one from the replaceable prevailing decls.  */
-  for (e = first; e; e = e->symbol.next_sharing_asm_name)
-    {
-      if (!lto_symtab_resolve_can_prevail_p (e))
-       continue;
-
-      /* Choose the first function that can prevail as prevailing.  */
-      if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
-       {
-         prevailing = e;
-         break;
-       }
-
-      /* From variables that can prevail choose the largest one.  */
-      if (!prevailing
-         || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
-                             DECL_SIZE (e->symbol.decl))
-         /* When variables are equivalent try to chose one that has useful
-            DECL_INITIAL.  This makes sense for keyed vtables that are
-            DECL_EXTERNAL but initialized.  In units that do not need them
-            we replace the initializer by error_mark_node to conserve
-            memory.
-
-            We know that the vtable is keyed outside the LTO unit - otherwise
-            the keyed instance would prevail.  We still can preserve useful
-            info in the initializer.  */
-         || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
-             && (DECL_INITIAL (e->symbol.decl)
-                 && DECL_INITIAL (e->symbol.decl) != error_mark_node)
-             && (!DECL_INITIAL (prevailing->symbol.decl)
-                 || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
-       prevailing = e;
-    }
-
-  return prevailing;
-}
-
-/* Merge all decls in the symbol table chain to the prevailing decl and
-   issue diagnostics about type mismatches.  If DIAGNOSED_P is true
-   do not issue further diagnostics.*/
-
-static void
-lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
-{
-  symtab_node prevailing, e;
-  vec<tree> mismatches = vNULL;
-  unsigned i;
-  tree decl;
-
-  /* Nothing to do for a single entry.  */
-  prevailing = first;
-  if (!prevailing->symbol.next_sharing_asm_name)
-    return;
-
-  /* Try to merge each entry with the prevailing one.  */
-  for (e = prevailing->symbol.next_sharing_asm_name;
-       e; e = e->symbol.next_sharing_asm_name)
-    if (TREE_PUBLIC (e->symbol.decl))
-      {
-       if (!lto_symtab_merge (prevailing, e)
-           && !diagnosed_p)
-         mismatches.safe_push (e->symbol.decl);
-      }
-  if (mismatches.is_empty ())
-    return;
-
-  /* Diagnose all mismatched re-declarations.  */
-  FOR_EACH_VEC_ELT (mismatches, i, decl)
-    {
-      if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
-                              TREE_TYPE (decl)))
-       diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
-                                  "type of %qD does not match original "
-                                  "declaration", decl);
-
-      else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
-               && DECL_USER_ALIGN (decl))
-              && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
-       {
-         diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
-                                    "alignment of %qD is bigger than "
-                                    "original declaration", decl);
-       }
-    }
-  if (diagnosed_p)
-    inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
-           "previously declared here");
-
-  mismatches.release ();
-}
-
-/* Helper to process the decl chain for the symbol table entry *SLOT.  */
-
-static void
-lto_symtab_merge_decls_1 (symtab_node first)
-{
-  symtab_node e, prevailing;
-  bool diagnosed_p = false;
-
-  if (cgraph_dump_file)
-    {
-      fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n",
-              symtab_node_asm_name (first));
-      for (e = first; e; e = e->symbol.next_sharing_asm_name)
-       if (TREE_PUBLIC (e->symbol.decl))
-         dump_symtab_node (cgraph_dump_file, e);
-    }
-
-  /* Compute the symbol resolutions.  This is a no-op when using the
-     linker plugin and resolution was decided by the linker.  */
-  prevailing = lto_symtab_resolve_symbols (first);
-
-  /* If there's not a prevailing symbol yet it's an external reference.
-     Happens a lot during ltrans.  Choose the first symbol with a
-     cgraph or a varpool node.  */
-  if (!prevailing)
-    {
-      prevailing = first;
-      /* 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->symbol.decl) == VAR_DECL)
-       {
-         for (e = prevailing->symbol.next_sharing_asm_name;
-              e; e = e->symbol.next_sharing_asm_name)
-           if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
-               && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl))
-               && lto_symtab_symbol_p (e))
-             prevailing = e;
-       }
-      /* For variables prefer the non-builtin if one is available.  */
-      else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL)
-       {
-         for (e = first; e; e = e->symbol.next_sharing_asm_name)
-           if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL
-               && !DECL_BUILT_IN (e->symbol.decl)
-               && lto_symtab_symbol_p (e))
-             {
-               prevailing = e;
-               break;
-             }
-       }
-    }
-
-  symtab_prevail_in_asm_name_hash (prevailing);
-
-  /* Diagnose mismatched objects.  */
-  for (e = prevailing->symbol.next_sharing_asm_name;
-       e; e = e->symbol.next_sharing_asm_name)
-    {
-      if (TREE_CODE (prevailing->symbol.decl)
-         == TREE_CODE (e->symbol.decl))
-       continue;
-      if (!lto_symtab_symbol_p (e))
-       continue;
-
-      switch (TREE_CODE (prevailing->symbol.decl))
-       {
-       case VAR_DECL:
-         gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
-         error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
-                   "variable %qD redeclared as function",
-                   prevailing->symbol.decl);
-         break;
-
-       case FUNCTION_DECL:
-         gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
-         error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
-                   "function %qD redeclared as variable",
-                   prevailing->symbol.decl);
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-
-      diagnosed_p = true;
-    }
-  if (diagnosed_p)
-      inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
-             "previously declared here");
-
-  /* Merge the chain to the single prevailing decl and diagnose
-     mismatches.  */
-  lto_symtab_merge_decls_2 (prevailing, diagnosed_p);
-
-  if (cgraph_dump_file)
-    {
-      fprintf (cgraph_dump_file, "After resolution:\n");
-      for (e = prevailing; e; e = e->symbol.next_sharing_asm_name)
-       dump_symtab_node (cgraph_dump_file, e);
-    }
-}
-
-/* Resolve and merge all symbol table chains to a prevailing decl.  */
-
-void
-lto_symtab_merge_decls (void)
-{
-  symtab_node node;
-
-  /* Populate assembler name hash.   */
-  symtab_initialize_asm_name_hash ();
-
-  FOR_EACH_SYMBOL (node)
-    if (!node->symbol.previous_sharing_asm_name
-       && node->symbol.next_sharing_asm_name)
-      lto_symtab_merge_decls_1 (node);
-}
-
-/* Helper to process the decl chain for the symbol table entry *SLOT.  */
-
-static void
-lto_symtab_merge_symbols_1 (symtab_node prevailing)
-{
-  symtab_node e, next;
-
-  /* Replace the cgraph node of each entry with the prevailing one.  */
-  for (e = prevailing->symbol.next_sharing_asm_name; e;
-       e = next)
-    {
-      next = e->symbol.next_sharing_asm_name;
-
-      if (!lto_symtab_symbol_p (e))
-       continue;
-      cgraph_node *ce = dyn_cast <cgraph_node> (e);
-      if (ce && !DECL_BUILT_IN (e->symbol.decl))
-       lto_cgraph_replace_node (ce, cgraph (prevailing));
-      if (varpool_node *ve = dyn_cast <varpool_node> (e))
-       lto_varpool_replace_node (ve, varpool (prevailing));
-    }
-
-  return;
-}
-
-/* Merge cgraph nodes according to the symbol merging done by
-   lto_symtab_merge_decls.  */
-
-void
-lto_symtab_merge_symbols (void)
-{
-  symtab_node node;
-
-  if (!flag_ltrans)
-    {
-      symtab_initialize_asm_name_hash ();
-
-      /* Do the actual merging.  
-         At this point we invalidate hash translating decls into symtab nodes
-        because after removing one of duplicate decls the hash is not correcly
-        updated to the ohter dupliate.  */
-      FOR_EACH_SYMBOL (node)
-       if (lto_symtab_symbol_p (node)
-           && node->symbol.next_sharing_asm_name
-           && !node->symbol.previous_sharing_asm_name)
-         lto_symtab_merge_symbols_1 (node);
-
-      /* Resolve weakref aliases whose target are now in the compilation unit.  
-        also re-populate the hash translating decls into symtab nodes*/
-      FOR_EACH_SYMBOL (node)
-       {
-         cgraph_node *cnode, *cnode2;
-         varpool_node *vnode;
-         symtab_node node2;
-
-         if (!node->symbol.analyzed && node->symbol.alias_target)
-           {
-             symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target);
-             gcc_assert (node->symbol.weakref);
-             if (tgt)
-               symtab_resolve_alias (node, tgt);
-           }
-         node->symbol.aux = NULL;
-
-         if (!(cnode = dyn_cast <cgraph_node> (node))
-             || !cnode->clone_of
-             || cnode->clone_of->symbol.decl != cnode->symbol.decl)
-           {
-             /* Builtins are not merged via decl merging.  It is however
-                possible that tree merging unified the declaration.  We
-                do not want duplicate entries in symbol table.  */
-             if (cnode && DECL_BUILT_IN (node->symbol.decl)
-                 && (cnode2 = cgraph_get_node (node->symbol.decl))
-                 && cnode2 != cnode)
-               lto_cgraph_replace_node (cnode2, cnode);
-
-             /* The user defined assembler variables are also not unified by their
-                symbol name (since it is irrelevant), but we need to unify symbol
-                nodes if tree merging occured.  */
-             if ((vnode = dyn_cast <varpool_node> (node))
-                 && DECL_HARD_REGISTER (vnode->symbol.decl)
-                 && (node2 = symtab_get_node (vnode->symbol.decl))
-                 && node2 != node)
-               lto_varpool_replace_node (dyn_cast <varpool_node> (node2),
-                                         vnode);
-         
-
-             /* Abstract functions may have duplicated cgraph nodes attached;
-                remove them.  */
-             else if (cnode && DECL_ABSTRACT (cnode->symbol.decl)
-                      && (cnode2 = cgraph_get_node (node->symbol.decl))
-                      && cnode2 != cnode)
-               cgraph_remove_node (cnode2);
-
-             symtab_insert_node_to_hashtable ((symtab_node)node);
-           }
-       }
-    }
-}
-
-/* Given the decl DECL, return the prevailing decl with the same name. */
-
-tree
-lto_symtab_prevailing_decl (tree decl)
-{
-  symtab_node ret;
-
-  /* Builtins and local symbols are their own prevailing decl.  */
-  if ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) || is_builtin_fn (decl))
-    return decl;
-
-  /* DECL_ABSTRACTs are their own prevailng decl.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
-    return decl;
-
-  /* Likewise builtins are their own prevailing decl.  This preserves
-     non-builtin vs. builtin uses from compile-time.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
-    return decl;
-
-  /* Ensure DECL_ASSEMBLER_NAME will not set assembler name.  */
-  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-
-  /* Walk through the list of candidates and return the one we merged to.  */
-  ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
-  if (!ret)
-    return decl;
-
-  return ret->symbol.decl;
-}
index fe8e4638a504451200560ec6e4877e5631de3c66..8ac0f8d60a40845cb2d4b63bb1b31a6c67028a6b 100644 (file)
@@ -1,3 +1,13 @@
+2013-09-06  Richard Biener  <rguenther@suse.de>
+
+       * lto-symtab.c: Move from gcc/
+       * lto.h: Include vec.h.
+       (lto_global_var_decls): Declare.
+       * lto.c (lto_global_var_decls): Move definition here.
+       * Make-lang.in (LTO_OBJS): Add lto-symtab.o.
+       (lto-symtab.o): Add.
+       * config-lang.in (gtfiles): Add lto.h.
+
 2013-08-31  Jan Hubicka  <jh@suse.cz>
 
        * lto.c (mentions_vars_p_field_decl, lto_fixup_prevailing_decls): 
index 1acd176dd892e297181d2bb249e4254c3df37d6b..c67c58e7f8342f3d50b69f68e3de847e4cd9d3fa 100644 (file)
@@ -22,7 +22,7 @@
 # The name of the LTO compiler.
 LTO_EXE = lto1$(exeext)
 # The LTO-specific object files inclued in $(LTO_EXE).
-LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o
+LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o
 LTO_H = lto/lto.h $(HASHTAB_H)
 LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
 LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
@@ -95,6 +95,9 @@ lto/lto-partition.o: lto/lto-partition.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 lto/lto-object.o: lto/lto-object.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
        $(DIAGNOSTIC_CORE_H) $(LTO_H) $(TM_H) $(LTO_STREAMER_H) \
        ../include/simple-object.h
+lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+       $(TREE_H) $(GIMPLE_H) $(GGC_H) $(HASHTAB_H) \
+       $(LTO_STREAMER_H) $(LINKER_PLUGIN_API_H)
 
 # LTO testing is done as part of C/C++/Fortran etc. testing.
 check-lto:
index 266446de6d2067382ce79f734ebf30d0c0df770d..9217c5dfbaad864be97a3fa0e398f581a4f92fa5 100644 (file)
@@ -21,7 +21,7 @@ language="lto"
 compilers="lto1\$(exeext)"
 stagestuff="lto1\$(exeext)"
 
-gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c"
+gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c \$(srcdir)/lto/lto.h"
 
 # LTO is a special front end.  From a user's perspective it is not
 # really a language, but a middle end feature.  However, the GIMPLE
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
new file mode 100644 (file)
index 0000000..b1b7731
--- /dev/null
@@ -0,0 +1,663 @@
+/* LTO symbol table.
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+   Contributed by CodeSourcery, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "tree.h"
+#include "gimple.h"
+#include "ggc.h"
+#include "hashtab.h"
+#include "plugin-api.h"
+#include "lto-streamer.h"
+#include "ipa-utils.h"
+
+/* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
+   all edges and removing the old node.  */
+
+static void
+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->symbol.order,
+              cgraph_node_name (prevailing_node),
+              prevailing_node->symbol.order,
+              IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name)
+                (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl)))));
+    }
+
+  /* Merge node flags.  */
+  if (node->symbol.force_output)
+    cgraph_mark_force_output_node (prevailing_node);
+  if (node->symbol.address_taken)
+    {
+      gcc_assert (!prevailing_node->global.inlined_to);
+      cgraph_mark_address_taken_node (prevailing_node);
+    }
+
+  /* Redirect all incoming edges.  */
+  compatible_p
+    = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->symbol.decl)),
+                         TREE_TYPE (TREE_TYPE (node->symbol.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_referring ((symtab_node)prevailing_node, &node->symbol.ref_list);
+
+  ipa_merge_profiles (prevailing_node, node);
+  lto_free_function_in_decl_state_for_node ((symtab_node)node);
+
+  if (node->symbol.decl != prevailing_node->symbol.decl)
+    cgraph_release_function_body (node);
+
+  /* Finally remove the replaced node.  */
+  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)
+{
+  gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition);
+  gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed);
+
+  ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
+
+  /* Be sure we can garbage collect the initializer.  */
+  if (DECL_INITIAL (vnode->symbol.decl)
+      && vnode->symbol.decl != prevailing_node->symbol.decl)
+    DECL_INITIAL (vnode->symbol.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.  */
+
+static bool
+lto_symtab_merge (symtab_node prevailing, symtab_node entry)
+{
+  tree prevailing_decl = prevailing->symbol.decl;
+  tree decl = entry->symbol.decl;
+  tree prevailing_type, type;
+
+  if (prevailing_decl == decl)
+    return true;
+
+  /* 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);
+
+  /* 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 (!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
+          whichever decl appears to be associated with the
+          definition.  If for some odd reason neither decl is, the
+          older one wins.  */
+       (void) 0;
+
+      return true;
+    }
+
+  /* Now we exclusively deal with VAR_DECLs.  */
+
+  /* Sharing a global symbol is a strong hint that two types are
+     compatible.  We could use this information to complete
+     incomplete pointed-to types more aggressively here, ignoring
+     mismatches in both field and tag names.  It's difficult though
+     to guarantee that this does not have side-effects on merging
+     more compatible types from other translation units though.  */
+
+  /* We can tolerate differences in type qualification, the
+     qualification of the prevailing definition will prevail.
+     ???  In principle we might want to only warn for structurally
+     incompatible types here, but unless we have protective measures
+     for TBAA in place that would hide useful information.  */
+  prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
+  type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
+
+  if (!types_compatible_p (prevailing_type, type))
+    {
+      if (COMPLETE_TYPE_P (type))
+       return false;
+
+      /* If type is incomplete then avoid warnings in the cases
+        that TBAA handles just fine.  */
+
+      if (TREE_CODE (prevailing_type) != TREE_CODE (type))
+       return false;
+
+      if (TREE_CODE (prevailing_type) == ARRAY_TYPE)
+       {
+         tree tem1 = TREE_TYPE (prevailing_type);
+         tree tem2 = TREE_TYPE (type);
+         while (TREE_CODE (tem1) == ARRAY_TYPE
+                && TREE_CODE (tem2) == ARRAY_TYPE)
+           {
+             tem1 = TREE_TYPE (tem1);
+             tem2 = TREE_TYPE (tem2);
+           }
+
+         if (TREE_CODE (tem1) != TREE_CODE (tem2))
+           return false;
+
+         if (!types_compatible_p (tem1, tem2))
+           return false;
+       }
+
+      /* Fallthru.  Compatible enough.  */
+    }
+
+  /* ???  We might want to emit a warning here if type qualification
+     differences were spotted.  Do not do this unconditionally though.  */
+
+  /* There is no point in comparing too many details of the decls here.
+     The type compatibility checks or the completing of types has properly
+     dealt with most issues.  */
+
+  /* The following should all not invoke fatal errors as in non-LTO
+     mode the linker wouldn't complain either.  Just emit warnings.  */
+
+  /* Report a warning if user-specified alignments do not match.  */
+  if ((DECL_USER_ALIGN (prevailing_decl) && DECL_USER_ALIGN (decl))
+      && DECL_ALIGN (prevailing_decl) < DECL_ALIGN (decl))
+    return false;
+
+  return true;
+}
+
+/* Return true if the symtab entry E can be replaced by another symtab
+   entry.  */
+
+static bool
+lto_symtab_resolve_replaceable_p (symtab_node e)
+{
+  if (DECL_EXTERNAL (e->symbol.decl)
+      || DECL_COMDAT (e->symbol.decl)
+      || DECL_ONE_ONLY (e->symbol.decl)
+      || DECL_WEAK (e->symbol.decl))
+    return true;
+
+  if (TREE_CODE (e->symbol.decl) == VAR_DECL)
+    return (DECL_COMMON (e->symbol.decl)
+           || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
+
+  return false;
+}
+
+/* Return true, if the symbol E should be resolved by lto-symtab.
+   Those are all external symbols and all real symbols that are not static (we
+   handle renaming of static later in partitioning).  */
+
+static bool
+lto_symtab_symbol_p (symtab_node e)
+{
+  if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl))
+    return false;
+  return symtab_real_symbol_p (e);
+}
+
+/* Return true if the symtab entry E can be the prevailing one.  */
+
+static bool
+lto_symtab_resolve_can_prevail_p (symtab_node e)
+{
+  if (!lto_symtab_symbol_p (e))
+    return false;
+
+  /* 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->symbol.decl))
+    return false;
+
+  return e->symbol.definition;
+}
+
+/* Resolve the symbol with the candidates in the chain *SLOT and store
+   their resolutions.  */
+
+static symtab_node
+lto_symtab_resolve_symbols (symtab_node first)
+{
+  symtab_node e;
+  symtab_node prevailing = NULL;
+
+  /* Always set e->node so that edges are updated to reflect decl merging. */
+  for (e = first; e; e = e->symbol.next_sharing_asm_name)
+    if (lto_symtab_symbol_p (e)
+       && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
+           || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+           || e->symbol.resolution == LDPR_PREVAILING_DEF))
+      {
+       prevailing = e;
+       break;
+      }
+
+  /* If the chain is already resolved there is nothing else to do.  */
+  if (prevailing)
+    {
+      /* Assert it's the only one.  */
+      for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
+       if (lto_symtab_symbol_p (e)
+           && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
+               || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
+               || e->symbol.resolution == LDPR_PREVAILING_DEF))
+         fatal_error ("multiple prevailing defs for %qE",
+                      DECL_NAME (prevailing->symbol.decl));
+      return prevailing;
+    }
+
+  /* Find the single non-replaceable prevailing symbol and
+     diagnose ODR violations.  */
+  for (e = first; e; e = e->symbol.next_sharing_asm_name)
+    {
+      if (!lto_symtab_resolve_can_prevail_p (e))
+       continue;
+
+      /* If we have a non-replaceable definition it prevails.  */
+      if (!lto_symtab_resolve_replaceable_p (e))
+       {
+         if (prevailing)
+           {
+             error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+                       "%qD has already been defined", e->symbol.decl);
+             inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+                     "previously defined here");
+           }
+         prevailing = e;
+       }
+    }
+  if (prevailing)
+    return prevailing;
+
+  /* Do a second round choosing one from the replaceable prevailing decls.  */
+  for (e = first; e; e = e->symbol.next_sharing_asm_name)
+    {
+      if (!lto_symtab_resolve_can_prevail_p (e))
+       continue;
+
+      /* Choose the first function that can prevail as prevailing.  */
+      if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
+       {
+         prevailing = e;
+         break;
+       }
+
+      /* From variables that can prevail choose the largest one.  */
+      if (!prevailing
+         || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
+                             DECL_SIZE (e->symbol.decl))
+         /* When variables are equivalent try to chose one that has useful
+            DECL_INITIAL.  This makes sense for keyed vtables that are
+            DECL_EXTERNAL but initialized.  In units that do not need them
+            we replace the initializer by error_mark_node to conserve
+            memory.
+
+            We know that the vtable is keyed outside the LTO unit - otherwise
+            the keyed instance would prevail.  We still can preserve useful
+            info in the initializer.  */
+         || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
+             && (DECL_INITIAL (e->symbol.decl)
+                 && DECL_INITIAL (e->symbol.decl) != error_mark_node)
+             && (!DECL_INITIAL (prevailing->symbol.decl)
+                 || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
+       prevailing = e;
+    }
+
+  return prevailing;
+}
+
+/* Merge all decls in the symbol table chain to the prevailing decl and
+   issue diagnostics about type mismatches.  If DIAGNOSED_P is true
+   do not issue further diagnostics.*/
+
+static void
+lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
+{
+  symtab_node prevailing, e;
+  vec<tree> mismatches = vNULL;
+  unsigned i;
+  tree decl;
+
+  /* Nothing to do for a single entry.  */
+  prevailing = first;
+  if (!prevailing->symbol.next_sharing_asm_name)
+    return;
+
+  /* Try to merge each entry with the prevailing one.  */
+  for (e = prevailing->symbol.next_sharing_asm_name;
+       e; e = e->symbol.next_sharing_asm_name)
+    if (TREE_PUBLIC (e->symbol.decl))
+      {
+       if (!lto_symtab_merge (prevailing, e)
+           && !diagnosed_p)
+         mismatches.safe_push (e->symbol.decl);
+      }
+  if (mismatches.is_empty ())
+    return;
+
+  /* Diagnose all mismatched re-declarations.  */
+  FOR_EACH_VEC_ELT (mismatches, i, decl)
+    {
+      if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
+                              TREE_TYPE (decl)))
+       diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
+                                  "type of %qD does not match original "
+                                  "declaration", decl);
+
+      else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
+               && DECL_USER_ALIGN (decl))
+              && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
+       {
+         diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
+                                    "alignment of %qD is bigger than "
+                                    "original declaration", decl);
+       }
+    }
+  if (diagnosed_p)
+    inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+           "previously declared here");
+
+  mismatches.release ();
+}
+
+/* Helper to process the decl chain for the symbol table entry *SLOT.  */
+
+static void
+lto_symtab_merge_decls_1 (symtab_node first)
+{
+  symtab_node e, prevailing;
+  bool diagnosed_p = false;
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n",
+              symtab_node_asm_name (first));
+      for (e = first; e; e = e->symbol.next_sharing_asm_name)
+       if (TREE_PUBLIC (e->symbol.decl))
+         dump_symtab_node (cgraph_dump_file, e);
+    }
+
+  /* Compute the symbol resolutions.  This is a no-op when using the
+     linker plugin and resolution was decided by the linker.  */
+  prevailing = lto_symtab_resolve_symbols (first);
+
+  /* If there's not a prevailing symbol yet it's an external reference.
+     Happens a lot during ltrans.  Choose the first symbol with a
+     cgraph or a varpool node.  */
+  if (!prevailing)
+    {
+      prevailing = first;
+      /* 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->symbol.decl) == VAR_DECL)
+       {
+         for (e = prevailing->symbol.next_sharing_asm_name;
+              e; e = e->symbol.next_sharing_asm_name)
+           if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
+               && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl))
+               && lto_symtab_symbol_p (e))
+             prevailing = e;
+       }
+      /* For variables prefer the non-builtin if one is available.  */
+      else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL)
+       {
+         for (e = first; e; e = e->symbol.next_sharing_asm_name)
+           if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL
+               && !DECL_BUILT_IN (e->symbol.decl)
+               && lto_symtab_symbol_p (e))
+             {
+               prevailing = e;
+               break;
+             }
+       }
+    }
+
+  symtab_prevail_in_asm_name_hash (prevailing);
+
+  /* Diagnose mismatched objects.  */
+  for (e = prevailing->symbol.next_sharing_asm_name;
+       e; e = e->symbol.next_sharing_asm_name)
+    {
+      if (TREE_CODE (prevailing->symbol.decl)
+         == TREE_CODE (e->symbol.decl))
+       continue;
+      if (!lto_symtab_symbol_p (e))
+       continue;
+
+      switch (TREE_CODE (prevailing->symbol.decl))
+       {
+       case VAR_DECL:
+         gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
+         error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+                   "variable %qD redeclared as function",
+                   prevailing->symbol.decl);
+         break;
+
+       case FUNCTION_DECL:
+         gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
+         error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
+                   "function %qD redeclared as variable",
+                   prevailing->symbol.decl);
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      diagnosed_p = true;
+    }
+  if (diagnosed_p)
+      inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
+             "previously declared here");
+
+  /* Merge the chain to the single prevailing decl and diagnose
+     mismatches.  */
+  lto_symtab_merge_decls_2 (prevailing, diagnosed_p);
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "After resolution:\n");
+      for (e = prevailing; e; e = e->symbol.next_sharing_asm_name)
+       dump_symtab_node (cgraph_dump_file, e);
+    }
+}
+
+/* Resolve and merge all symbol table chains to a prevailing decl.  */
+
+void
+lto_symtab_merge_decls (void)
+{
+  symtab_node node;
+
+  /* Populate assembler name hash.   */
+  symtab_initialize_asm_name_hash ();
+
+  FOR_EACH_SYMBOL (node)
+    if (!node->symbol.previous_sharing_asm_name
+       && node->symbol.next_sharing_asm_name)
+      lto_symtab_merge_decls_1 (node);
+}
+
+/* Helper to process the decl chain for the symbol table entry *SLOT.  */
+
+static void
+lto_symtab_merge_symbols_1 (symtab_node prevailing)
+{
+  symtab_node e, next;
+
+  /* Replace the cgraph node of each entry with the prevailing one.  */
+  for (e = prevailing->symbol.next_sharing_asm_name; e;
+       e = next)
+    {
+      next = e->symbol.next_sharing_asm_name;
+
+      if (!lto_symtab_symbol_p (e))
+       continue;
+      cgraph_node *ce = dyn_cast <cgraph_node> (e);
+      if (ce && !DECL_BUILT_IN (e->symbol.decl))
+       lto_cgraph_replace_node (ce, cgraph (prevailing));
+      if (varpool_node *ve = dyn_cast <varpool_node> (e))
+       lto_varpool_replace_node (ve, varpool (prevailing));
+    }
+
+  return;
+}
+
+/* Merge cgraph nodes according to the symbol merging done by
+   lto_symtab_merge_decls.  */
+
+void
+lto_symtab_merge_symbols (void)
+{
+  symtab_node node;
+
+  if (!flag_ltrans)
+    {
+      symtab_initialize_asm_name_hash ();
+
+      /* Do the actual merging.  
+         At this point we invalidate hash translating decls into symtab nodes
+        because after removing one of duplicate decls the hash is not correcly
+        updated to the ohter dupliate.  */
+      FOR_EACH_SYMBOL (node)
+       if (lto_symtab_symbol_p (node)
+           && node->symbol.next_sharing_asm_name
+           && !node->symbol.previous_sharing_asm_name)
+         lto_symtab_merge_symbols_1 (node);
+
+      /* Resolve weakref aliases whose target are now in the compilation unit.  
+        also re-populate the hash translating decls into symtab nodes*/
+      FOR_EACH_SYMBOL (node)
+       {
+         cgraph_node *cnode, *cnode2;
+         varpool_node *vnode;
+         symtab_node node2;
+
+         if (!node->symbol.analyzed && node->symbol.alias_target)
+           {
+             symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target);
+             gcc_assert (node->symbol.weakref);
+             if (tgt)
+               symtab_resolve_alias (node, tgt);
+           }
+         node->symbol.aux = NULL;
+
+         if (!(cnode = dyn_cast <cgraph_node> (node))
+             || !cnode->clone_of
+             || cnode->clone_of->symbol.decl != cnode->symbol.decl)
+           {
+             /* Builtins are not merged via decl merging.  It is however
+                possible that tree merging unified the declaration.  We
+                do not want duplicate entries in symbol table.  */
+             if (cnode && DECL_BUILT_IN (node->symbol.decl)
+                 && (cnode2 = cgraph_get_node (node->symbol.decl))
+                 && cnode2 != cnode)
+               lto_cgraph_replace_node (cnode2, cnode);
+
+             /* The user defined assembler variables are also not unified by their
+                symbol name (since it is irrelevant), but we need to unify symbol
+                nodes if tree merging occured.  */
+             if ((vnode = dyn_cast <varpool_node> (node))
+                 && DECL_HARD_REGISTER (vnode->symbol.decl)
+                 && (node2 = symtab_get_node (vnode->symbol.decl))
+                 && node2 != node)
+               lto_varpool_replace_node (dyn_cast <varpool_node> (node2),
+                                         vnode);
+         
+
+             /* Abstract functions may have duplicated cgraph nodes attached;
+                remove them.  */
+             else if (cnode && DECL_ABSTRACT (cnode->symbol.decl)
+                      && (cnode2 = cgraph_get_node (node->symbol.decl))
+                      && cnode2 != cnode)
+               cgraph_remove_node (cnode2);
+
+             symtab_insert_node_to_hashtable ((symtab_node)node);
+           }
+       }
+    }
+}
+
+/* Given the decl DECL, return the prevailing decl with the same name. */
+
+tree
+lto_symtab_prevailing_decl (tree decl)
+{
+  symtab_node ret;
+
+  /* Builtins and local symbols are their own prevailing decl.  */
+  if ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) || is_builtin_fn (decl))
+    return decl;
+
+  /* DECL_ABSTRACTs are their own prevailng decl.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
+    return decl;
+
+  /* Likewise builtins are their own prevailing decl.  This preserves
+     non-builtin vs. builtin uses from compile-time.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+    return decl;
+
+  /* Ensure DECL_ASSEMBLER_NAME will not set assembler name.  */
+  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
+
+  /* Walk through the list of candidates and return the one we merged to.  */
+  ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
+  if (!ret)
+    return decl;
+
+  return ret->symbol.decl;
+}
index 0cea778f7d61fcfa51ea75490be59f7fc54f9c42..470f3c1d7a7ed2b1fb64c6baf1916fdb9dd75740 100644 (file)
@@ -49,6 +49,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "pass_manager.h"
 
+/* Vector to keep track of external variables we've seen so far.  */
+vec<tree, va_gc> *lto_global_var_decls;
+
 static GTY(()) tree first_personality_decl;
 
 /* Returns a hash code for P.  */
index 2699459dc188cf16c234d2be0cdcf3ffe4fa4ca9..1734fe5def1d1ef97db2b23022cc766601a9f42a 100644 (file)
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define LTO_H
 
 #include "hashtab.h"
+#include "vec.h"
 
 /* A file.  */
 typedef struct lto_file_struct
@@ -40,6 +41,9 @@ extern tree lto_eh_personality (void);
 extern void lto_main (void);
 extern void lto_read_all_file_options (void);
 
+/* In lto-symtab.c  */
+extern GTY(()) vec<tree, va_gc> *lto_global_var_decls;
+
 /* In lto-elf.c or lto-coff.c  */
 extern lto_file *lto_obj_file_open (const char *filename, bool writable);
 extern void lto_obj_file_close (lto_file *file);