OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 7ed5905..229a370 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
-   Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1174,12 +1174,13 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
   if (TREE_TYPE (decl) != error_mark_node)
     as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
 
-  /* If the decl has been given an explicit section name, or it resides
-     in a non-generic address space, then it isn't common, and shouldn't
-     be handled as such.  */
-  if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL
-      && ADDR_SPACE_GENERIC_P (as))
+  if (DECL_COMMON (decl))
     {
+      /* If the decl has been given an explicit section name, or it resides
+        in a non-generic address space, then it isn't common, and shouldn't
+        be handled as such.  */
+      gcc_assert (DECL_SECTION_NAME (decl) == NULL
+                 && ADDR_SPACE_GENERIC_P (as));
       if (DECL_THREAD_LOCAL_P (decl))
        return tls_comm_section;
       /* This cannot be common bss for an emulated TLS object without
@@ -1434,6 +1435,10 @@ make_decl_rtl (tree decl)
 
   /* Specifying a section attribute on a variable forces it into a
      non-.bss section, and thus it cannot be common.  */
+  /* FIXME: In general this code should not be necessary because
+     visibility pass is doing the same work.  But notice_global_symbol
+     is called early and it needs to make DECL_RTL to get the name.
+     we take care of recomputing the DECL_RTL after visibility is changed.  */
   if (TREE_CODE (decl) == VAR_DECL
       && DECL_SECTION_NAME (decl) != NULL_TREE
       && DECL_INITIAL (decl) == NULL_TREE
@@ -1474,6 +1479,42 @@ make_decl_rtl (tree decl)
   if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
     mudflap_enqueue_decl (decl);
 }
+
+/* Like make_decl_rtl, but inhibit creation of new alias sets when
+   calling make_decl_rtl.  Also, reset DECL_RTL before returning the
+   rtl.  */
+
+rtx
+make_decl_rtl_for_debug (tree decl)
+{
+  unsigned int save_aliasing_flag, save_mudflap_flag;
+  rtx rtl;
+
+  if (DECL_RTL_SET_P (decl))
+    return DECL_RTL (decl);
+
+  /* Kludge alert!  Somewhere down the call chain, make_decl_rtl will
+     call new_alias_set.  If running with -fcompare-debug, sometimes
+     we do not want to create alias sets that will throw the alias
+     numbers off in the comparison dumps.  So... clearing
+     flag_strict_aliasing will keep new_alias_set() from creating a
+     new set.  It is undesirable to register decl with mudflap
+     in this case as well.  */
+  save_aliasing_flag = flag_strict_aliasing;
+  flag_strict_aliasing = 0;
+  save_mudflap_flag = flag_mudflap;
+  flag_mudflap = 0;
+
+  rtl = DECL_RTL (decl);
+  /* Reset DECL_RTL back, as various parts of the compiler expects
+     DECL_RTL set meaning it is actually going to be output.  */
+  SET_DECL_RTL (decl, NULL);
+
+  flag_strict_aliasing = save_aliasing_flag;
+  flag_mudflap = save_mudflap_flag;
+
+  return rtl;
+}
 \f
 /* Output a string of literal assembler code
    for an `asm' keyword used between functions.  */
@@ -4093,6 +4134,9 @@ constructor_static_from_elts_p (const_tree ctor)
          && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
 }
 
+static tree initializer_constant_valid_p_1 (tree value, tree endtype,
+                                           tree *cache);
+
 /* A subroutine of initializer_constant_valid_p.  VALUE is a MINUS_EXPR,
    PLUS_EXPR or POINTER_PLUS_EXPR.  This looks for cases of VALUE
    which are valid when ENDTYPE is an integer of any size; in
@@ -4102,7 +4146,7 @@ constructor_static_from_elts_p (const_tree ctor)
    returns NULL.  */
 
 static tree
-narrowing_initializer_constant_valid_p (tree value, tree endtype)
+narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
 {
   tree op0, op1;
 
@@ -4141,11 +4185,14 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
       op1 = inner;
     }
 
-  op0 = initializer_constant_valid_p (op0, endtype);
-  op1 = initializer_constant_valid_p (op1, endtype);
+  op0 = initializer_constant_valid_p_1 (op0, endtype, cache);
+  if (!op0)
+    return NULL_TREE;
 
+  op1 = initializer_constant_valid_p_1 (op1, endtype,
+                                       cache ? cache + 2 : NULL);
   /* Both initializers must be known.  */
-  if (op0 && op1)
+  if (op1)
     {
       if (op0 == op1
          && (op0 == null_pointer_node
@@ -4166,7 +4213,8 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
   return NULL_TREE;
 }
 
-/* Return nonzero if VALUE is a valid constant-valued expression
+/* Helper function of initializer_constant_valid_p.
+   Return nonzero if VALUE is a valid constant-valued expression
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
 
@@ -4174,10 +4222,12 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
    if it is relocatable, return the variable that determines the relocation.
    We assume that VALUE has been folded as much as possible;
    therefore, we do not need to check for such things as
-   arithmetic-combinations of integers.  */
+   arithmetic-combinations of integers.
 
-tree
-initializer_constant_valid_p (tree value, tree endtype)
+   Use CACHE (pointer to 2 tree values) for caching if non-NULL.  */
+
+static tree
+initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
 {
   tree ret;
 
@@ -4190,18 +4240,33 @@ initializer_constant_valid_p (tree value, tree endtype)
          tree elt;
          bool absolute = true;
 
+         if (cache && cache[0] == value)
+           return cache[1];
          FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
            {
              tree reloc;
-             reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
+             reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
+                                                     NULL);
              if (!reloc)
-               return NULL_TREE;
+               {
+                 if (cache)
+                   {
+                     cache[0] = value;
+                     cache[1] = NULL_TREE;
+                   }
+                 return NULL_TREE;
+               }
              if (reloc != null_pointer_node)
                absolute = false;
            }
          /* For a non-absolute relocation, there is no single
             variable that can be "the variable that determines the
             relocation."  */
+         if (cache)
+           {
+             cache[0] = value;
+             cache[1] = absolute ? null_pointer_node : error_mark_node;
+           }
          return absolute ? null_pointer_node : error_mark_node;
        }
 
@@ -4241,7 +4306,8 @@ initializer_constant_valid_p (tree value, tree endtype)
       }
 
     case NON_LVALUE_EXPR:
-      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+      return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+                                            endtype, cache);
 
     case VIEW_CONVERT_EXPR:
       {
@@ -4256,13 +4322,13 @@ initializer_constant_valid_p (tree value, tree endtype)
        if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type))
          {
            if (TYPE_MODE (endtype) == TYPE_MODE (dest_type))
-             return initializer_constant_valid_p (src, endtype);
+             return initializer_constant_valid_p_1 (src, endtype, cache);
            else
              return NULL_TREE;
          }
 
        /* Allow all other kinds of view-conversion.  */
-       return initializer_constant_valid_p (src, endtype);
+       return initializer_constant_valid_p_1 (src, endtype, cache);
       }
 
     CASE_CONVERT:
@@ -4277,18 +4343,18 @@ initializer_constant_valid_p (tree value, tree endtype)
            || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
            || (TREE_CODE (dest_type) == OFFSET_TYPE
                && TREE_CODE (src_type) == OFFSET_TYPE))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Allow length-preserving conversions between integer types.  */
        if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
            && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Allow conversions between other integer types only if
           explicit value.  */
        if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
          {
-           tree inner = initializer_constant_valid_p (src, endtype);
+           tree inner = initializer_constant_valid_p_1 (src, endtype, cache);
            if (inner == null_pointer_node)
              return null_pointer_node;
            break;
@@ -4297,7 +4363,7 @@ initializer_constant_valid_p (tree value, tree endtype)
        /* Allow (int) &foo provided int is as wide as a pointer.  */
        if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
            && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Likewise conversions from int to pointers, but also allow
           conversions from 0.  */
@@ -4311,14 +4377,14 @@ initializer_constant_valid_p (tree value, tree endtype)
            if (integer_zerop (src))
              return null_pointer_node;
            else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
-             return initializer_constant_valid_p (src, endtype);
+             return initializer_constant_valid_p_1 (src, endtype, cache);
          }
 
        /* Allow conversions to struct or union types if the value
           inside is okay.  */
        if (TREE_CODE (dest_type) == RECORD_TYPE
            || TREE_CODE (dest_type) == UNION_TYPE)
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
       }
       break;
 
@@ -4328,66 +4394,102 @@ initializer_constant_valid_p (tree value, tree endtype)
         with -frounding-math we hit this with addition of two constants.  */
       if (TREE_CODE (endtype) == REAL_TYPE)
        return NULL_TREE;
+      if (cache && cache[0] == value)
+       return cache[1];
       if (! INTEGRAL_TYPE_P (endtype)
          || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
        {
-         tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                     endtype);
-         tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
-                                                     endtype);
+         tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
+         tree valid0
+           = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+                                             endtype, ncache);
+         tree valid1
+           = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
+                                             endtype, ncache + 2);
          /* If either term is absolute, use the other term's relocation.  */
          if (valid0 == null_pointer_node)
-           return valid1;
-         if (valid1 == null_pointer_node)
-           return valid0;
+           ret = valid1;
+         else if (valid1 == null_pointer_node)
+           ret = valid0;
+         /* Support narrowing pointer differences.  */
+         else
+           ret = narrowing_initializer_constant_valid_p (value, endtype,
+                                                         ncache);
        }
-
+      else
       /* Support narrowing pointer differences.  */
-      ret = narrowing_initializer_constant_valid_p (value, endtype);
-      if (ret != NULL_TREE)
-       return ret;
-
-      break;
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
+       {
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
     case MINUS_EXPR:
       if (TREE_CODE (endtype) == REAL_TYPE)
        return NULL_TREE;
+      if (cache && cache[0] == value)
+       return cache[1];
       if (! INTEGRAL_TYPE_P (endtype)
          || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
        {
-         tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
-                                                     endtype);
-         tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
-                                                     endtype);
+         tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
+         tree valid0
+           = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+                                             endtype, ncache);
+         tree valid1
+           = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
+                                             endtype, ncache + 2);
          /* Win if second argument is absolute.  */
          if (valid1 == null_pointer_node)
-           return valid0;
+           ret = valid0;
          /* Win if both arguments have the same relocation.
             Then the value is absolute.  */
-         if (valid0 == valid1 && valid0 != 0)
-           return null_pointer_node;
-
+         else if (valid0 == valid1 && valid0 != 0)
+           ret = null_pointer_node;
          /* Since GCC guarantees that string constants are unique in the
             generated code, a subtraction between two copies of the same
             constant string is absolute.  */
-         if (valid0 && TREE_CODE (valid0) == STRING_CST
-             && valid1 && TREE_CODE (valid1) == STRING_CST
-             && operand_equal_p (valid0, valid1, 1))
-           return null_pointer_node;
+         else if (valid0 && TREE_CODE (valid0) == STRING_CST
+                  && valid1 && TREE_CODE (valid1) == STRING_CST
+                  && operand_equal_p (valid0, valid1, 1))
+           ret = null_pointer_node;
+         /* Support narrowing differences.  */
+         else
+           ret = narrowing_initializer_constant_valid_p (value, endtype,
+                                                         ncache);
        }
-
-      /* Support narrowing differences.  */
-      ret = narrowing_initializer_constant_valid_p (value, endtype);
-      if (ret != NULL_TREE)
-       return ret;
-
-      break;
+      else
+       /* Support narrowing differences.  */
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
+       {
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
     default:
       break;
     }
 
-  return 0;
+  return NULL_TREE;
+}
+
+/* Return nonzero if VALUE is a valid constant-valued expression
+   for use in initializing a static variable; one that can be an
+   element of a "constant" initializer.
+
+   Return null_pointer_node if the value is absolute;
+   if it is relocatable, return the variable that determines the relocation.
+   We assume that VALUE has been folded as much as possible;
+   therefore, we do not need to check for such things as
+   arithmetic-combinations of integers.  */
+tree
+initializer_constant_valid_p (tree value, tree endtype)
+{
+  return initializer_constant_valid_p_1 (value, endtype, NULL);
 }
 \f
 /* Return true if VALUE is a valid constant-valued expression
@@ -5446,6 +5548,10 @@ do_assemble_alias (tree decl, tree target)
   if (TREE_ASM_WRITTEN (decl))
     return;
 
+  /* We must force creation of DECL_RTL for debug info generation, even though
+     we don't use it here.  */
+  make_decl_rtl (decl);
+
   TREE_ASM_WRITTEN (decl) = 1;
   TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
 
@@ -5663,10 +5769,6 @@ assemble_alias (tree decl, tree target)
 # endif
 #endif
     }
-
-  /* We must force creation of DECL_RTL for debug info generation, even though
-     we don't use it here.  */
-  make_decl_rtl (decl);
   TREE_USED (decl) = 1;
 
   /* A quirk of the initial implementation of aliases required that the user
@@ -5701,8 +5803,10 @@ assemble_alias (tree decl, tree target)
    the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
 
 void
-default_assemble_visibility (tree decl, int vis)
+default_assemble_visibility (tree decl ATTRIBUTE_UNUSED, 
+                            int vis ATTRIBUTE_UNUSED)
 {
+#ifdef HAVE_GAS_HIDDEN
   static const char * const visibility_types[] = {
     NULL, "protected", "hidden", "internal"
   };
@@ -5712,7 +5816,6 @@ default_assemble_visibility (tree decl, int vis)
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   type = visibility_types[vis];
 
-#ifdef HAVE_GAS_HIDDEN
   fprintf (asm_out_file, "\t.%s\t", type);
   assemble_name (asm_out_file, name);
   fprintf (asm_out_file, "\n");
@@ -5968,6 +6071,10 @@ default_no_named_section (const char *name ATTRIBUTE_UNUSED,
   gcc_unreachable ();
 }
 
+#ifndef TLS_SECTION_ASM_FLAG
+#define TLS_SECTION_ASM_FLAG 'T'
+#endif
+
 void
 default_elf_asm_named_section (const char *name, unsigned int flags,
                               tree decl ATTRIBUTE_UNUSED)
@@ -5998,7 +6105,7 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
   if (flags & SECTION_STRINGS)
     *f++ = 'S';
   if (flags & SECTION_TLS)
-    *f++ = 'T';
+    *f++ = TLS_SECTION_ASM_FLAG;
   if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
     *f++ = 'G';
   *f = '\0';