OSDN Git Service

* configure.ac (i[34567]86-*-*): Handle Solaris 2/x86 TLS support
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index b6ff4ae..ba4e612 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.
 
@@ -215,7 +215,7 @@ prefix_name (const char *prefix, tree name)
   unsigned plen = strlen (prefix);
   unsigned nlen = strlen (IDENTIFIER_POINTER (name));
   char *toname = (char *) alloca (plen + nlen + 1);
-  
+
   memcpy (toname, prefix, plen);
   memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1);
 
@@ -238,19 +238,19 @@ tree
 default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
 {
   tree word_type_node, field, next_field;
-  
+
   field = build_decl (UNKNOWN_LOCATION,
                      FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
   DECL_CONTEXT (field) = type;
   next_field = field;
-    
+
   field = build_decl (UNKNOWN_LOCATION,
                      FIELD_DECL, get_identifier ("__offset"),
                      ptr_type_node);
   DECL_CONTEXT (field) = type;
   TREE_CHAIN (field) = next_field;
   next_field = field;
-  
+
   word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
   field = build_decl (UNKNOWN_LOCATION,
                      FIELD_DECL, get_identifier ("__align"),
@@ -258,7 +258,7 @@ default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
   DECL_CONTEXT (field) = type;
   TREE_CHAIN (field) = next_field;
   next_field = field;
-  
+
   field = build_decl (UNKNOWN_LOCATION,
                      FIELD_DECL, get_identifier ("__size"), word_type_node);
   DECL_CONTEXT (field) = type;
@@ -300,7 +300,7 @@ static tree
 get_emutls_init_templ_addr (tree decl)
 {
   tree name, to;
-  
+
   if (targetm.emutls.register_common && !DECL_INITIAL (decl)
       && !DECL_SECTION_NAME (decl))
     return null_pointer_node;
@@ -324,7 +324,7 @@ get_emutls_init_templ_addr (tree decl)
   DECL_IGNORED_P (to) = 1;
   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
   DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl);
-  
+
   DECL_WEAK (to) = DECL_WEAK (decl);
   if (DECL_ONE_ONLY (decl))
     {
@@ -464,7 +464,7 @@ emutls_finish (void)
       htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
       if (body == NULL_TREE)
        return;
-      
+
       cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
     }
 }
@@ -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,15 +1435,16 @@ 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.  */
-  if (TREE_CODE (decl) == VAR_DECL
-      && DECL_SECTION_NAME (decl) != NULL_TREE
-      && DECL_INITIAL (decl) == NULL_TREE
-      && DECL_COMMON (decl))
-    DECL_COMMON (decl) = 0;
+  gcc_assert (!(TREE_CODE (decl) == VAR_DECL
+             && DECL_SECTION_NAME (decl) != NULL_TREE
+             && DECL_INITIAL (decl) == NULL_TREE
+             && DECL_COMMON (decl))
+             || !DECL_COMMON (decl));
 
   /* Variables can't be both common and weak.  */
-  if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl))
-    DECL_COMMON (decl) = 0;
+  gcc_assert (TREE_CODE (decl) != VAR_DECL
+             || !DECL_WEAK (decl)
+             || !DECL_COMMON (decl));
 
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
@@ -1474,6 +1476,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.  */
@@ -1509,7 +1547,7 @@ default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
 }
 
 /* Write the address of the entity given by SYMBOL to SEC.  */
-void 
+void
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
@@ -1540,7 +1578,7 @@ default_named_section_asm_out_destructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_PRIORITY)
-    sec = get_cdtor_priority_section (priority, 
+    sec = get_cdtor_priority_section (priority,
                                      /*constructor_p=*/false);
   else
     sec = get_section (".dtors", SECTION_WRITE, NULL);
@@ -1580,7 +1618,7 @@ default_named_section_asm_out_constructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_PRIORITY)
-    sec = get_cdtor_priority_section (priority, 
+    sec = get_cdtor_priority_section (priority,
                                      /*constructor_p=*/true);
   else
     sec = get_section (".ctors", SECTION_WRITE, NULL);
@@ -2032,27 +2070,27 @@ default_emutls_var_init (tree to, tree decl, tree proxy)
   constructor_elt *elt;
   tree type = TREE_TYPE (to);
   tree field = TYPE_FIELDS (type);
-  
+
   elt = VEC_quick_push (constructor_elt, v, NULL);
   elt->index = field;
   elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl));
-  
+
   elt = VEC_quick_push (constructor_elt, v, NULL);
   field = TREE_CHAIN (field);
   elt->index = field;
   elt->value = build_int_cst (TREE_TYPE (field),
                              DECL_ALIGN_UNIT (decl));
-  
+
   elt = VEC_quick_push (constructor_elt, v, NULL);
   field = TREE_CHAIN (field);
   elt->index = field;
   elt->value = null_pointer_node;
-  
+
   elt = VEC_quick_push (constructor_elt, v, NULL);
   field = TREE_CHAIN (field);
   elt->index = field;
   elt->value = proxy;
-  
+
   return build_constructor (type, v);
 }
 
@@ -2337,13 +2375,15 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
   /* We want to output annotation for weak and external symbols at
      very last to check if they are references or not.  */
 
-  if (SUPPORTS_WEAK && DECL_WEAK (decl)
+  if (SUPPORTS_WEAK
+      && DECL_WEAK (decl)
       /* TREE_STATIC is a weird and abused creature which is not
         generally the right test for whether an entity has been
         locally emitted, inlined or otherwise not-really-extern, but
         for declarations that can be weak, it happens to be
         match.  */
       && !TREE_STATIC (decl)
+      && lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
       && value_member (decl, weak_decls) == NULL_TREE)
     weak_decls = tree_cons (NULL, decl, weak_decls);
 
@@ -2806,7 +2846,7 @@ static void maybe_output_constant_def_contents (struct constant_descriptor_tree
 
 /* Constant pool accessor function.  */
 
-htab_t 
+htab_t
 constant_pool_htab (void)
 {
   return const_desc_htab;
@@ -4091,6 +4131,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
@@ -4100,7 +4143,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;
 
@@ -4139,11 +4182,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
@@ -4164,7 +4210,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.
 
@@ -4172,10 +4219,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;
 
@@ -4188,18 +4237,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;
        }
 
@@ -4239,7 +4303,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:
       {
@@ -4254,13 +4319,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:
@@ -4275,18 +4340,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;
@@ -4295,7 +4360,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.  */
@@ -4309,79 +4374,119 @@ 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;
 
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
+      /* Any valid floating-point constants will have been folded by now;
+        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)
-            >= int_or_pointer_precision (TREE_TYPE (value)))
+         || 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)
-            >= int_or_pointer_precision (TREE_TYPE (value)))
+         || 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
@@ -4492,7 +4597,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
       else if (TREE_CODE (exp) == INTEGER_CST)
        exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
                                  TREE_INT_CST_HIGH (exp));
-      
+
     }
 
   /* Eliminate any conversions since we'll be outputting the underlying
@@ -4560,8 +4665,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case REAL_TYPE:
       if (TREE_CODE (exp) != REAL_CST)
        error ("initializer for floating value is not a floating constant");
-
-      assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
+      else
+       assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
       break;
 
     case COMPLEX_TYPE:
@@ -4716,7 +4821,7 @@ output_constructor_array_range (oc_local_state *local)
 
   unsigned int align2
     = min_align (local->align, fieldsize * BITS_PER_UNIT);
-  
+
   for (index = lo_index; index <= hi_index; index++)
     {
       /* Output the element's initial value.  */
@@ -4724,7 +4829,7 @@ output_constructor_array_range (oc_local_state *local)
        assemble_zeros (fieldsize);
       else
        output_constant (local->val, fieldsize, align2);
-      
+
       /* Count its size.  */
       local->total_bytes += fieldsize;
     }
@@ -4745,12 +4850,12 @@ output_constructor_regular_field (oc_local_state *local)
 
   if (local->index != NULL_TREE)
     fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
-               * ((tree_low_cst (local->index, 0) 
+               * ((tree_low_cst (local->index, 0)
                    - tree_low_cst (local->min_index, 0))));
-  else if (local->field != NULL_TREE) 
+  else if (local->field != NULL_TREE)
     fieldpos = int_byte_position (local->field);
   else
-    fieldpos = 0; 
+    fieldpos = 0;
 
   /* Output any buffered-up bit-fields preceding this element.  */
   if (local->byte_buffer_in_use)
@@ -4759,7 +4864,7 @@ output_constructor_regular_field (oc_local_state *local)
       local->total_bytes++;
       local->byte_buffer_in_use = false;
     }
-  
+
   /* Advance to offset of this element.
      Note no alignment needed in an array, since that is guaranteed
      if each element has the proper size.  */
@@ -4770,7 +4875,7 @@ output_constructor_regular_field (oc_local_state *local)
       assemble_zeros (fieldpos - local->total_bytes);
       local->total_bytes = fieldpos;
     }
-  
+
   /* Find the alignment of this element.  */
   align2 = min_align (local->align, BITS_PER_UNIT * fieldpos);
 
@@ -4778,7 +4883,7 @@ output_constructor_regular_field (oc_local_state *local)
   if (local->field)
     {
       fieldsize = 0;
-      
+
       /* If this is an array with an unspecified upper bound,
         the initializer determines the size.  */
       /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
@@ -4803,7 +4908,7 @@ output_constructor_regular_field (oc_local_state *local)
     }
   else
     fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
-  
+
   /* Output the element's initial value.  */
   if (local->val == NULL_TREE)
     assemble_zeros (fieldsize);
@@ -4830,38 +4935,38 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
   HOST_WIDE_INT relative_index
     = (!local->field
        ? (local->index
-         ? (tree_low_cst (local->index, 0) 
+         ? (tree_low_cst (local->index, 0)
             - tree_low_cst (local->min_index, 0))
          : local->last_relative_index + 1)
        : 0);
-  
+
   /* Bit position of this element from the start of the containing
      constructor.  */
   HOST_WIDE_INT constructor_relative_ebitpos
       = (local->field
-        ? int_bit_position (local->field) 
+        ? int_bit_position (local->field)
         : ebitsize * relative_index);
-  
+
   /* Bit position of this element from the start of a possibly ongoing
      outer byte buffer.  */
   HOST_WIDE_INT byte_relative_ebitpos
       = ((outer ? outer->bit_offset : 0) + constructor_relative_ebitpos);
 
-  /* From the start of a possibly ongoing outer byte buffer, offsets to 
+  /* From the start of a possibly ongoing outer byte buffer, offsets to
      the first bit of this element and to the first bit past the end of
      this element.  */
   HOST_WIDE_INT next_offset = byte_relative_ebitpos;
   HOST_WIDE_INT end_offset = byte_relative_ebitpos + ebitsize;
-  
+
   local->last_relative_index = relative_index;
-  
+
   if (local->val == NULL_TREE)
     local->val = integer_zero_node;
-  
+
   while (TREE_CODE (local->val) == VIEW_CONVERT_EXPR
         || TREE_CODE (local->val) == NON_LVALUE_EXPR)
     local->val = TREE_OPERAND (local->val, 0);
-    
+
   if (TREE_CODE (local->val) != INTEGER_CST
       && TREE_CODE (local->val) != CONSTRUCTOR)
     {
@@ -4880,7 +4985,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes++;
          local->byte_buffer_in_use = false;
        }
-      
+
       /* If still not at proper byte, advance to there.  */
       if (next_offset / BITS_PER_UNIT != local->total_bytes)
        {
@@ -4889,7 +4994,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes = next_offset / BITS_PER_UNIT;
        }
     }
-  
+
   /* Set up the buffer if necessary.  */
   if (!local->byte_buffer_in_use)
     {
@@ -4897,7 +5002,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       if (ebitsize > 0)
        local->byte_buffer_in_use = true;
     }
-  
+
   /* If this is nested constructor, recurse passing the bit offset and the
      pending data, then retrieve the new pending data afterwards.  */
   if (TREE_CODE (local->val) == CONSTRUCTOR)
@@ -4911,10 +5016,10 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       local->byte = output_state.byte;
       return;
     }
-  
+
   /* Otherwise, we must split the element into pieces that fall within
      separate bytes, and combine each byte with previous or following
-     bit-fields.  */  
+     bit-fields.  */
   while (next_offset < end_offset)
     {
       int this_time;
@@ -4922,7 +5027,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       HOST_WIDE_INT value;
       HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
       HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
-      
+
       /* Advance from byte to byte
         within this element when necessary.  */
       while (next_byte != local->total_bytes)
@@ -4931,7 +5036,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes++;
          local->byte = 0;
        }
-      
+
       /* Number of bits we can process at once
         (all part of the same byte).  */
       this_time = MIN (end_offset - next_offset,
@@ -4942,7 +5047,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
             first (of the bits that are significant)
             and put them into bytes from the most significant end.  */
          shift = end_offset - next_offset - this_time;
-         
+
          /* Don't try to take a bunch of bits that cross
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
@@ -4953,7 +5058,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
              shift = HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Now get the bits from the appropriate constant word.  */
          if (shift < HOST_BITS_PER_WIDE_INT)
            value = TREE_INT_CST_LOW (local->val);
@@ -4963,7 +5068,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              value = TREE_INT_CST_HIGH (local->val);
              shift -= HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
          local->byte |= (((value >> shift)
@@ -4977,7 +5082,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
             and pack them starting at the least significant
             bits of the bytes.  */
          shift = next_offset - byte_relative_ebitpos;
-         
+
          /* Don't try to take a bunch of bits that cross
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
@@ -4985,7 +5090,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          if (shift < HOST_BITS_PER_WIDE_INT
              && shift + this_time > HOST_BITS_PER_WIDE_INT)
            this_time = (HOST_BITS_PER_WIDE_INT - shift);
-         
+
          /* Now get the bits from the appropriate constant word.  */
          if (shift < HOST_BITS_PER_WIDE_INT)
            value = TREE_INT_CST_LOW (local->val);
@@ -4995,14 +5100,14 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              value = TREE_INT_CST_HIGH (local->val);
              shift -= HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
          local->byte |= (((value >> shift)
                           & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
                          << next_bit);
        }
-      
+
       next_offset += this_time;
       local->byte_buffer_in_use = true;
     }
@@ -5038,7 +5143,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
   if (TREE_CODE (local.type) == ARRAY_TYPE
       && TYPE_DOMAIN (local.type) != NULL_TREE)
     local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
-  
+
   gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
 
   /* As CE goes through the elements of the constant, FIELD goes through the
@@ -5099,7 +5204,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
               && (local.field == NULL_TREE
                   || !CONSTRUCTOR_BITFIELD_P (local.field)))
        output_constructor_regular_field (&local);
-      
+
       /* For a true bitfield or part of an outer one.  */
       else
        output_constructor_bitfield (&local, outer);
@@ -5123,7 +5228,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
          local.total_bytes = local.size;
        }
     }
-      
+
   return local.total_bytes;
 }
 
@@ -5223,6 +5328,9 @@ declare_weak (tree decl)
     warning (0, "weak declaration of %q+D not supported", decl);
 
   mark_weak (decl);
+  if (!lookup_attribute ("weak", DECL_ATTRIBUTES (decl)))
+    DECL_ATTRIBUTES (decl)
+      = tree_cons (get_identifier ("weak"), NULL, DECL_ATTRIBUTES (decl));
 }
 
 static void
@@ -5437,6 +5545,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;
 
@@ -5654,10 +5766,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
@@ -5959,6 +6067,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)
@@ -5989,7 +6101,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';
@@ -6341,7 +6453,7 @@ default_unique_section (tree decl, int reloc)
   /* If we're using one_only, then there needs to be a .gnu.linkonce
      prefix to the section name.  */
   linkonce = one_only ? ".gnu.linkonce" : "";
-  
+
   string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
   DECL_SECTION_NAME (decl) = build_string (strlen (string), string);