OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 8d55548..bb835bc 100644 (file)
@@ -1,7 +1,7 @@
 /* Output variables, constants and external declarations, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011  Free Software Foundation, Inc.
+   2010, 2011, 2012  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "pointer-set.h"
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
@@ -314,11 +315,16 @@ get_section (const char *name, unsigned int flags, tree decl)
          if (decl == 0)
            decl = sect->named.decl;
          gcc_assert (decl);
-         error ("%+D causes a section type conflict with %D", 
-                       decl, sect->named.decl);
-         if (decl != sect->named.decl)
-            inform (DECL_SOURCE_LOCATION (sect->named.decl), 
-                   "%qD was declared here", sect->named.decl);
+         if (sect->named.decl == NULL)
+           error ("%+D causes a section type conflict", decl);
+         else
+           {
+             error ("%+D causes a section type conflict with %D",
+                    decl, sect->named.decl);
+             if (decl != sect->named.decl)
+               inform (DECL_SOURCE_LOCATION (sect->named.decl),
+                       "%qD was declared here", sect->named.decl);
+           }
          /* Make sure we don't error about one section multiple times.  */
          sect->common.flags |= SECTION_OVERRIDE;
        }
@@ -2099,6 +2105,19 @@ contains_pointers_p (tree type)
    it all the way to final.  See PR 17982 for further discussion.  */
 static GTY(()) tree pending_assemble_externals;
 
+/* FIXME: Trunk is at GCC 4.8 now and the above problem still hasn't been
+   addressed properly.  This caused PR 52640 due to O(external_decls**2)
+   lookups in the pending_assemble_externals TREE_LIST in assemble_external.
+   Paper over with this pointer set, which we use to see if we have already
+   added a decl to pending_assemble_externals without first traversing
+   the entire pending_assemble_externals list.  See assemble_external().  */
+static struct pointer_set_t *pending_assemble_externals_set;
+
+/* Some targets delay some output to final using TARGET_ASM_FILE_END.
+   As a result, assemble_external can be called after the list of externals
+   is processed and the pointer set destroyed.  */
+static bool pending_assemble_externals_processed;
+
 #ifdef ASM_OUTPUT_EXTERNAL
 /* True if DECL is a function decl for which no out-of-line copy exists.
    It is assumed that DECL's assembler name has been set.  */
@@ -2151,6 +2170,8 @@ process_pending_assemble_externals (void)
     assemble_external_real (TREE_VALUE (list));
 
   pending_assemble_externals = 0;
+  pending_assemble_externals_processed = true;
+  pointer_set_destroy (pending_assemble_externals_set);
 #endif
 }
 
@@ -2191,7 +2212,13 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
     weak_decls = tree_cons (NULL, decl, weak_decls);
 
 #ifdef ASM_OUTPUT_EXTERNAL
-  if (value_member (decl, pending_assemble_externals) == NULL_TREE)
+  if (pending_assemble_externals_processed)
+    {
+      assemble_external_real (decl);
+      return;
+    }
+
+  if (! pointer_set_insert (pending_assemble_externals_set, decl))
     pending_assemble_externals = tree_cons (NULL, decl,
                                            pending_assemble_externals);
 #endif
@@ -3926,6 +3953,13 @@ compute_reloc_for_constant (tree exp)
           tem = TREE_OPERAND (tem, 0))
        ;
 
+      if (TREE_CODE (tem) == MEM_REF
+         && TREE_CODE (TREE_OPERAND (tem, 0)) == ADDR_EXPR)
+       {
+         reloc = compute_reloc_for_constant (TREE_OPERAND (tem, 0));
+         break;
+       }
+
       if (TREE_PUBLIC (tem))
        reloc |= 2;
       else
@@ -3994,6 +4028,9 @@ output_addressed_constants (tree exp)
 
       if (CONSTANT_CLASS_P (tem) || TREE_CODE (tem) == CONSTRUCTOR)
        output_constant_def (tem, 0);
+
+      if (TREE_CODE (tem) == MEM_REF)
+       output_addressed_constants (TREE_OPERAND (tem, 0));
       break;
 
     case PLUS_EXPR:
@@ -5794,14 +5831,11 @@ void
 assemble_alias (tree decl, tree target)
 {
   tree target_decl;
-  bool is_weakref = false;
 
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
     {
       tree alias = DECL_ASSEMBLER_NAME (decl);
 
-      is_weakref = true;
-
       ultimate_transparent_alias_target (&target);
 
       if (alias == target)
@@ -5839,12 +5873,6 @@ assemble_alias (tree decl, tree target)
     }
   TREE_USED (decl) = 1;
 
-  /* A quirk of the initial implementation of aliases required that the user
-     add "extern" to all of them.  Which is silly, but now historical.  Do
-     note that the symbol is in fact locally defined.  */
-  if (! is_weakref)
-    DECL_EXTERNAL (decl) = 0;
-
   /* Allow aliases to aliases.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
     cgraph_get_create_node (decl)->alias = true;
@@ -6186,6 +6214,10 @@ init_varasm_once (void)
 
   if (readonly_data_section == NULL)
     readonly_data_section = text_section;
+
+#ifdef ASM_OUTPUT_EXTERNAL
+  pending_assemble_externals_set = pointer_set_create ();
+#endif
 }
 
 enum tls_model
@@ -6920,11 +6952,14 @@ default_binds_local_p_1 (const_tree exp, int shlib)
   /* A non-decl is an entry in the constant pool.  */
   if (!DECL_P (exp))
     local_p = true;
-  /* Weakrefs may not bind locally, even though the weakref itself is
-     always static and therefore local.
-     FIXME: We can resolve this more curefuly by looking at the weakref
-     alias.  */
-  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp)))
+  /* Weakrefs may not bind locally, even though the weakref itself is always
+     static and therefore local.  Similarly, the resolver for ifunc functions
+     might resolve to a non-local function.
+     FIXME: We can resolve the weakref case more curefuly by looking at the
+     weakref alias.  */
+  else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
+          || (TREE_CODE (exp) == FUNCTION_DECL
+              && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
     local_p = false;
   /* Static variables are always local.  */
   else if (! TREE_PUBLIC (exp))
@@ -7664,7 +7699,7 @@ get_elf_initfini_array_priority_section (int priority,
       sprintf (buf, "%s.%.5u", 
               constructor_p ? ".init_array" : ".fini_array",
               priority);
-      sec = get_section (buf, SECTION_WRITE, NULL_TREE);
+      sec = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
     }
   else
     {
@@ -7672,16 +7707,16 @@ get_elf_initfini_array_priority_section (int priority,
        {
          if (elf_init_array_section == NULL)
            elf_init_array_section
-             = get_unnamed_section (0, output_section_asm_op,
-                                    "\t.section\t.init_array");
+             = get_section (".init_array",
+                            SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
          sec = elf_init_array_section;
        }
       else
        {
          if (elf_fini_array_section == NULL)
            elf_fini_array_section
-             = get_unnamed_section (0, output_section_asm_op,
-                                    "\t.section\t.fini_array");
+             = get_section (".fini_array",
+                            SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
          sec = elf_fini_array_section;
        }
     }