OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 34cc509..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;
        }
@@ -1198,16 +1204,23 @@ make_decl_rtl (tree decl)
   else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
     {
       const char *asmspec = name+1;
+      enum machine_mode mode = DECL_MODE (decl);
       reg_number = decode_reg_name (asmspec);
       /* First detect errors in declaring global registers.  */
       if (reg_number == -1)
        error ("register name not specified for %q+D", decl);
       else if (reg_number < 0)
        error ("invalid register name for %q+D", decl);
-      else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+      else if (mode == BLKmode)
        error ("data type of %q+D isn%'t suitable for a register",
               decl);
-      else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
+      else if (!in_hard_reg_set_p (accessible_reg_set, mode, reg_number))
+       error ("the register specified for %q+D cannot be accessed"
+              " by the current target", decl);
+      else if (!in_hard_reg_set_p (operand_reg_set, mode, reg_number))
+       error ("the register specified for %q+D is not general enough"
+              " to be used as a register variable", decl);
+      else if (!HARD_REGNO_MODE_OK (reg_number, mode))
        error ("register specified for %q+D isn%'t suitable for data type",
                decl);
       /* Now handle properly declared static register variables.  */
@@ -1230,7 +1243,7 @@ make_decl_rtl (tree decl)
             confused with that register and be eliminated.  This usage is
             somewhat suspect...  */
 
-         SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number));
+         SET_DECL_RTL (decl, gen_rtx_raw_REG (mode, reg_number));
          ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
          REG_USERVAR_P (DECL_RTL (decl)) = 1;
 
@@ -1242,7 +1255,7 @@ make_decl_rtl (tree decl)
              name = IDENTIFIER_POINTER (DECL_NAME (decl));
              ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
 #endif
-             nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)];
+             nregs = hard_regno_nregs[reg_number][mode];
              while (nregs > 0)
                globalize_reg (decl, reg_number + --nregs);
            }
@@ -2092,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.  */
@@ -2109,7 +2135,9 @@ incorporeal_function_p (tree decl)
        return true;
 
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      if (is_builtin_name (name))
+      /* Atomic or sync builtins which have survived this far will be
+        resolved externally and therefore are not incorporeal.  */
+      if (strncmp (name, "__builtin_", 10) == 0)
        return true;
     }
   return false;
@@ -2142,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
 }
 
@@ -2182,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
@@ -3917,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
@@ -3985,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:
@@ -5785,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)
@@ -5830,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;
@@ -5961,7 +5998,7 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
 
       if (!switched)
        {
-         switch_to_section (get_named_section (NULL, ".tm_clone_table", 3));
+         switch_to_section (targetm.asm_out.tm_clone_table_section ());
          assemble_align (POINTER_SIZE);
          switched = true;
        }
@@ -5973,6 +6010,14 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs)
     }
 }
 
+/* Provide a default for the tm_clone_table section.  */
+
+section *
+default_clone_table_section (void)
+{
+  return get_named_section (NULL, ".tm_clone_table", 3);
+}
+
 /* Helper comparison function for qsorting by the DECL_UID stored in
    alias_pair->emitted_diags.  */
 
@@ -6169,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
@@ -6903,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))
@@ -7633,19 +7685,6 @@ default_elf_asm_output_ascii (FILE *f, const char *s, unsigned int len)
 }
 #endif
 
-/* Default TARGET_ASM_INTERNAL_LABEL for ELF targets.  */
-
-void
-default_elf_internal_label (FILE *f, const char *prefix,
-                           unsigned long labelno)
-{
-  putc ('.', f);
-  fputs (prefix, f);
-  fprint_ul (f, labelno);
-  putc (':', f);
-  putc ('\n', f);
-}
-
 static GTY(()) section *elf_init_array_section;
 static GTY(()) section *elf_fini_array_section;
 
@@ -7660,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
     {
@@ -7668,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;
        }
     }