diff gcc/varasm.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents 3bfb6c00c1e0
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/varasm.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/varasm.c	Fri Feb 12 23:39:51 2010 +0900
@@ -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  Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -42,7 +42,6 @@
 #include "output.h"
 #include "toplev.h"
 #include "hashtab.h"
-#include "c-pragma.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tm_p.h"
@@ -115,7 +114,6 @@
 static void output_addressed_constants (tree);
 static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
 static unsigned min_align (unsigned, unsigned);
-static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
 static void globalize_decl (tree);
 #ifdef BSS_SECTION_ASM_OP
 #ifdef ASM_OUTPUT_BSS
@@ -217,7 +215,7 @@
   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);
 
@@ -240,25 +238,29 @@
 default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
 {
   tree word_type_node, field, next_field;
-  
-  field = build_decl (FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
+
+  field = build_decl (UNKNOWN_LOCATION,
+		      FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
   DECL_CONTEXT (field) = type;
   next_field = field;
-    
-  field = build_decl (FIELD_DECL, get_identifier ("__offset"),
+
+  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 (FIELD_DECL, get_identifier ("__align"),
+  field = build_decl (UNKNOWN_LOCATION,
+		      FIELD_DECL, get_identifier ("__align"),
 		      word_type_node);
   DECL_CONTEXT (field) = type;
   TREE_CHAIN (field) = next_field;
   next_field = field;
-  
-  field = build_decl (FIELD_DECL, get_identifier ("__size"), word_type_node);
+
+  field = build_decl (UNKNOWN_LOCATION,
+		      FIELD_DECL, get_identifier ("__size"), word_type_node);
   DECL_CONTEXT (field) = type;
   TREE_CHAIN (field) = next_field;
 
@@ -282,7 +284,8 @@
   field = targetm.emutls.var_fields (type, &type_name);
   if (!type_name)
     type_name = get_identifier ("__emutls_object");
-  type_name = build_decl (TYPE_DECL, type_name, type);
+  type_name = build_decl (UNKNOWN_LOCATION,
+			  TYPE_DECL, type_name, type);
   TYPE_NAME (type) = type_name;
   TYPE_FIELDS (type) = field;
   layout_type (type);
@@ -297,7 +300,7 @@
 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;
@@ -311,7 +314,8 @@
       name = prefix_name (prefix, name);
     }
 
-  to = build_decl (VAR_DECL, name, TREE_TYPE (decl));
+  to = build_decl (DECL_SOURCE_LOCATION (decl),
+		   VAR_DECL, name, TREE_TYPE (decl));
   SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
   DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
   DECL_ARTIFICIAL (to) = 1;
@@ -320,11 +324,11 @@
   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))
     {
-      make_decl_one_only (to);
+      make_decl_one_only (to, DECL_ASSEMBLER_NAME (to));
       TREE_STATIC (to) = TREE_STATIC (decl);
       TREE_PUBLIC (to) = TREE_PUBLIC (decl);
       DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
@@ -371,7 +375,8 @@
     to = h->to;
   else
     {
-      to = build_decl (VAR_DECL, get_emutls_object_name (name),
+      to = build_decl (DECL_SOURCE_LOCATION (decl),
+		       VAR_DECL, get_emutls_object_name (name),
 		       get_emutls_object_type ());
 
       h = GGC_NEW (struct tree_map);
@@ -386,7 +391,7 @@
       TREE_READONLY (to) = 0;
       SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
       if (DECL_ONE_ONLY (decl))
-	make_decl_one_only (to);
+	make_decl_one_only (to, DECL_ASSEMBLER_NAME (to));
       DECL_CONTEXT (to) = DECL_CONTEXT (decl);
       if (targetm.emutls.var_align_fixed)
 	/* If we're not allowed to change the proxy object's
@@ -440,7 +445,7 @@
   args = tree_cons (NULL, x, args);
 
   x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
-  x = build_function_call_expr (x, args);
+  x = build_function_call_expr (UNKNOWN_LOCATION, x, args);
 
   append_to_statement_list (x, pstmts);
   return 1;
@@ -459,7 +464,7 @@
       htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
       if (body == NULL_TREE)
 	return;
-      
+
       cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
     }
 }
@@ -869,11 +874,18 @@
 
       if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
         {
-	  size_t len = strlen (name) + 3;
-	  char* rname = (char *) alloca (len);
+	  const char *dot;
+	  size_t len;
+	  char* rname;
+
+	  dot = strchr (name + 1, '.');
+	  if (!dot)
+	    dot = name;
+	  len = strlen (dot) + 8;
+	  rname = (char *) alloca (len);
 
 	  strcpy (rname, ".rodata");
-	  strcat (rname, name + 5);
+	  strcat (rname, dot);
 	  return get_section (rname, SECTION_LINKONCE, decl);
 	}
       /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo.  */
@@ -1156,11 +1168,17 @@
 static section *
 get_variable_section (tree decl, bool prefer_noswitch_p)
 {
+  addr_space_t as = ADDR_SPACE_GENERIC;
   int reloc;
 
-  /* If the decl has been given an explicit section name, then it
-     isn't common, and shouldn't be handled as such.  */
-  if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL)
+  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_THREAD_LOCAL_P (decl))
 	return tls_comm_section;
@@ -1184,7 +1202,8 @@
   if (IN_NAMED_SECTION (decl))
     return get_named_section (decl, NULL, reloc);
 
-  if (!DECL_THREAD_LOCAL_P (decl)
+  if (ADDR_SPACE_GENERIC_P (as)
+      && !DECL_THREAD_LOCAL_P (decl)
       && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
       && bss_initializer_p (decl))
     {
@@ -1428,7 +1447,15 @@
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
-    x = gen_rtx_SYMBOL_REF (Pmode, name);
+    {
+      enum machine_mode address_mode = Pmode;
+      if (TREE_TYPE (decl) != error_mark_node)
+	{
+	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+	  address_mode = targetm.addr_space.address_mode (as);
+	}
+      x = gen_rtx_SYMBOL_REF (address_mode, name);
+    }
   SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
   SET_SYMBOL_REF_DECL (x, decl);
 
@@ -1482,7 +1509,7 @@
 }
 
 /* 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);
@@ -1513,7 +1540,7 @@
   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);
@@ -1553,7 +1580,7 @@
   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);
@@ -1737,7 +1764,8 @@
   ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
 #endif
 
-  (*debug_hooks->begin_function) (decl);
+  if (!DECL_IGNORED_P (decl))
+    (*debug_hooks->begin_function) (decl);
 
   /* Make function name accessible from other files, if appropriate.  */
 
@@ -2004,27 +2032,27 @@
   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);
 }
 
@@ -2069,7 +2097,7 @@
 	     Without this, if the variable is placed in a
 	     section-anchored block, the template will only be marked
 	     when it's too late.  */
-	  record_references_in_initializer (to);
+	  record_references_in_initializer (to, false);
 	}
 
       decl = to;
@@ -2249,7 +2277,7 @@
 	return true;
 
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+      if (is_builtin_name (name))
 	return true;
     }
   return false;
@@ -2309,20 +2337,20 @@
   /* 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);
 
 #ifdef ASM_OUTPUT_EXTERNAL
-  pending_assemble_externals = tree_cons (0, decl,
-					  pending_assemble_externals);
+  if (value_member (decl, pending_assemble_externals) == NULL_TREE)
+    pending_assemble_externals = tree_cons (NULL, decl,
+					    pending_assemble_externals);
 #endif
 }
 
@@ -2494,7 +2522,6 @@
 
 static GTY(()) rtx initial_trampoline;
 
-#ifdef TRAMPOLINE_TEMPLATE
 rtx
 assemble_trampoline_template (void)
 {
@@ -2503,6 +2530,8 @@
   int align;
   rtx symbol;
 
+  gcc_assert (targetm.asm_out.trampoline_template != NULL);
+
   if (initial_trampoline)
     return initial_trampoline;
 
@@ -2517,12 +2546,10 @@
   /* Write the assembler code to define one.  */
   align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
   if (align > 0)
-    {
-      ASM_OUTPUT_ALIGN (asm_out_file, align);
-    }
+    ASM_OUTPUT_ALIGN (asm_out_file, align);
 
   targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
-  TRAMPOLINE_TEMPLATE (asm_out_file);
+  targetm.asm_out.trampoline_template (asm_out_file);
 
   /* Record the rtl to refer to it.  */
   ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
@@ -2530,12 +2557,12 @@
   symbol = gen_rtx_SYMBOL_REF (Pmode, name);
   SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
 
-  initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
+  initial_trampoline = gen_const_mem (BLKmode, symbol);
   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
+  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
 
   return initial_trampoline;
 }
-#endif
 
 /* A and B are either alignments or offsets.  Return the minimum alignment
    that may be assumed after adding the two together.  */
@@ -2630,7 +2657,7 @@
       enum machine_mode omode, imode;
       unsigned int subalign;
       unsigned int subsize, i;
-      unsigned char mclass;
+      enum mode_class mclass;
 
       subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
       subalign = MIN (align, subsize * BITS_PER_UNIT);
@@ -2706,8 +2733,7 @@
    Store them both in the structure *VALUE.
    EXP must be reducible.  */
 
-struct addr_const GTY(())
-{
+struct GTY(()) addr_const {
   rtx base;
   HOST_WIDE_INT offset;
 };
@@ -2771,23 +2797,6 @@
   value->offset = offset;
 }
 
-/* Uniquize all constants that appear in memory.
-   Each constant in memory thus far output is recorded
-   in `const_desc_table'.  */
-
-struct constant_descriptor_tree GTY(())
-{
-  /* A MEM for the constant.  */
-  rtx rtl;
-
-  /* The value of the constant.  */
-  tree value;
-
-  /* Hash of value.  Computing the hash from value each time
-     hashfn is called can't work properly, as that means recursive
-     use of the hash table during hash table expansion.  */
-  hashval_t hash;
-};
 
 static GTY((param_is (struct constant_descriptor_tree)))
      htab_t const_desc_htab;
@@ -2795,6 +2804,14 @@
 static struct constant_descriptor_tree * build_constant_desc (tree);
 static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
 
+/* Constant pool accessor function.  */
+
+htab_t
+constant_pool_htab (void)
+{
+  return const_desc_htab;
+}
+
 /* Compute a hash code for a constant expression.  */
 
 static hashval_t
@@ -3198,6 +3215,10 @@
   set_mem_alias_set (rtl, 0);
   set_mem_alias_set (rtl, const_alias_set);
 
+  /* We cannot share RTX'es in pool entries.
+     Mark this piece of RTL as required for unsharing.  */
+  RTX_FLAG (rtl, used) = 1;
+
   /* Set flags or add text to the name to record information, such as
      that it is a local symbol.  If the name is changed, the macro
      ASM_OUTPUT_LABELREF will have to know how to strip this
@@ -3361,8 +3382,7 @@
    can use one per-file pool.  Should add a targetm bit to tell the
    difference.  */
 
-struct rtx_constant_pool GTY(())
-{
+struct GTY(()) rtx_constant_pool {
   /* Pointers to first and last constant in pool, as ordered by offset.  */
   struct constant_descriptor_rtx *first;
   struct constant_descriptor_rtx *last;
@@ -3378,8 +3398,7 @@
   HOST_WIDE_INT offset;
 };
 
-struct constant_descriptor_rtx GTY((chain_next ("%h.next")))
-{
+struct GTY((chain_next ("%h.next"))) constant_descriptor_rtx {
   struct constant_descriptor_rtx *next;
   rtx mem;
   rtx sym;
@@ -3437,7 +3456,7 @@
       hwi = INTVAL (x);
     fold_hwi:
       {
-	const int shift = sizeof (hashval_t) * CHAR_BIT;
+	int shift = sizeof (hashval_t) * CHAR_BIT;
 	const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
 	int i;
 
@@ -4072,9 +4091,6 @@
 	  && !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
@@ -4084,7 +4100,7 @@
    returns NULL.  */
 
 static tree
-narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
+narrowing_initializer_constant_valid_p (tree value, tree endtype)
 {
   tree op0, op1;
 
@@ -4123,14 +4139,11 @@
       op1 = inner;
     }
 
-  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);
+  op0 = initializer_constant_valid_p (op0, endtype);
+  op1 = initializer_constant_valid_p (op1, endtype);
+
   /* Both initializers must be known.  */
-  if (op1)
+  if (op0 && op1)
     {
       if (op0 == op1
 	  && (op0 == null_pointer_node
@@ -4151,8 +4164,7 @@
   return NULL_TREE;
 }
 
-/* Helper function of initializer_constant_valid_p.
-   Return nonzero if VALUE is a valid constant-valued expression
+/* 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.
 
@@ -4160,12 +4172,10 @@
    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.
-
-   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)
+   arithmetic-combinations of integers.  */
+
+tree
+initializer_constant_valid_p (tree value, tree endtype)
 {
   tree ret;
 
@@ -4178,33 +4188,18 @@
 	  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_1 (elt, TREE_TYPE (elt),
-						      NULL);
+	      reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
 	      if (!reloc)
-		{
-		  if (cache)
-		    {
-		      cache[0] = value;
-		      cache[1] = NULL_TREE;
-		    }
-		  return 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;
 	}
 
@@ -4232,8 +4227,7 @@
 	    /* Taking the address of a nested function involves a trampoline,
 	       unless we don't need or want one.  */
 	    if (TREE_CODE (op0) == FUNCTION_DECL
-		&& decl_function_context (op0)
-		&& !DECL_NO_STATIC_CHAIN (op0)
+		&& DECL_STATIC_CHAIN (op0)
 		&& !TREE_NO_TRAMPOLINE (value))
 	      return NULL_TREE;
 	    /* "&{...}" requires a temporary to hold the constructed
@@ -4245,8 +4239,7 @@
       }
 
     case NON_LVALUE_EXPR:
-      return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
-					     endtype, cache);
+      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
 
     case VIEW_CONVERT_EXPR:
       {
@@ -4261,13 +4254,13 @@
 	if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type))
 	  {
 	    if (TYPE_MODE (endtype) == TYPE_MODE (dest_type))
-	      return initializer_constant_valid_p_1 (src, endtype, cache);
+	      return initializer_constant_valid_p (src, endtype);
 	    else
 	      return NULL_TREE;
 	  }
 
 	/* Allow all other kinds of view-conversion.  */
-	return initializer_constant_valid_p_1 (src, endtype, cache);
+	return initializer_constant_valid_p (src, endtype);
       }
 
     CASE_CONVERT:
@@ -4282,18 +4275,18 @@
 	    || (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_1 (src, endtype, cache);
+	  return initializer_constant_valid_p (src, endtype);
 
 	/* 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_1 (src, endtype, cache);
+	  return initializer_constant_valid_p (src, endtype);
 
 	/* 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_1 (src, endtype, cache);
+	    tree inner = initializer_constant_valid_p (src, endtype);
 	    if (inner == null_pointer_node)
 	      return null_pointer_node;
 	    break;
@@ -4302,7 +4295,7 @@
 	/* 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_1 (src, endtype, cache);
+	  return initializer_constant_valid_p (src, endtype);
 
 	/* Likewise conversions from int to pointers, but also allow
 	   conversions from 0.  */
@@ -4316,14 +4309,14 @@
 	    if (integer_zerop (src))
 	      return null_pointer_node;
 	    else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
-	      return initializer_constant_valid_p_1 (src, endtype, cache);
+	      return initializer_constant_valid_p (src, endtype);
 	  }
 
 	/* 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_1 (src, endtype, cache);
+	  return initializer_constant_valid_p (src, endtype);
       }
       break;
 
@@ -4333,104 +4326,117 @@
 	 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) >= POINTER_SIZE)
+	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
 	{
-	  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);
+	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+						      endtype);
+	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+						      endtype);
 	  /* If either term is absolute, use the other term's relocation.  */
 	  if (valid0 == null_pointer_node)
-	    ret = valid1;
-	  else if (valid1 == null_pointer_node)
-	    ret = valid0;
-	  /* Support narrowing pointer differences.  */
-	  else
-	    ret = narrowing_initializer_constant_valid_p (value, endtype,
-							  ncache);
+	    return valid1;
+	  if (valid1 == null_pointer_node)
+	    return valid0;
 	}
-      else
+
       /* Support narrowing pointer differences.  */
-	ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
-      if (cache)
-	{
-	  cache[0] = value;
-	  cache[1] = ret;
-	}
-      return ret;
+      ret = narrowing_initializer_constant_valid_p (value, endtype);
+      if (ret != NULL_TREE)
+	return ret;
+
+      break;
 
     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) >= POINTER_SIZE)
+	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
 	{
-	  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);
+	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
+						      endtype);
+	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
+						      endtype);
 	  /* Win if second argument is absolute.  */
 	  if (valid1 == null_pointer_node)
-	    ret = valid0;
+	    return valid0;
 	  /* Win if both arguments have the same relocation.
 	     Then the value is absolute.  */
-	  else if (valid0 == valid1 && valid0 != 0)
-	    ret = null_pointer_node;
+	  if (valid0 == valid1 && valid0 != 0)
+	    return 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.  */
-	  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);
+	  if (valid0 && TREE_CODE (valid0) == STRING_CST
+	      && valid1 && TREE_CODE (valid1) == STRING_CST
+	      && operand_equal_p (valid0, valid1, 1))
+	    return null_pointer_node;
 	}
-      else
-	/* Support narrowing differences.  */
-	ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
-      if (cache)
-	{
-	  cache[0] = value;
-	  cache[1] = ret;
-	}
-      return ret;
+
+      /* Support narrowing differences.  */
+      ret = narrowing_initializer_constant_valid_p (value, endtype);
+      if (ret != NULL_TREE)
+	return ret;
+
+      break;
 
     default:
       break;
     }
 
-  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);
+  return 0;
 }
 
+/* Return true if VALUE is a valid constant-valued expression
+   for use in initializing a static bit-field; one that can be
+   an element of a "constant" initializer.  */
+
+bool
+initializer_constant_valid_for_bitfield_p (tree value)
+{
+  /* For bitfields we support integer constants or possibly nested aggregates
+     of such.  */
+  switch (TREE_CODE (value))
+    {
+    case CONSTRUCTOR:
+      {
+	unsigned HOST_WIDE_INT idx;
+	tree elt;
+
+	FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
+	  if (!initializer_constant_valid_for_bitfield_p (elt))
+	    return false;
+	return true;
+      }
+
+    case INTEGER_CST:
+      return true;
+
+    case VIEW_CONVERT_EXPR:
+    case NON_LVALUE_EXPR:
+      return
+	initializer_constant_valid_for_bitfield_p (TREE_OPERAND (value, 0));
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
+/* output_constructor outer state of relevance in recursive calls, typically
+   for nested aggregate bitfields.  */
+
+typedef struct {
+  unsigned int bit_offset;  /* current position in ...  */
+  int byte;                 /* ... the outer byte buffer.  */
+} oc_outer_state;
+
+static unsigned HOST_WIDE_INT
+  output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int,
+		      oc_outer_state *);
+
 /* Output assembler code for constant EXP to FILE, with no label.
    This includes the pseudo-op such as ".int" or ".byte", and a newline.
    Assumes output_addressed_constants has been done on EXP already.
@@ -4466,7 +4472,9 @@
      resolving it.  */
   if (TREE_CODE (exp) == NOP_EXPR
       && POINTER_TYPE_P (TREE_TYPE (exp))
-      && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
+      && targetm.addr_space.valid_pointer_mode
+	   (TYPE_MODE (TREE_TYPE (exp)),
+	    TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
     {
       tree saved_type = TREE_TYPE (exp);
 
@@ -4474,7 +4482,9 @@
 	 pointer modes.  */
       while (TREE_CODE (exp) == NOP_EXPR
 	     && POINTER_TYPE_P (TREE_TYPE (exp))
-	     && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
+	     && targetm.addr_space.valid_pointer_mode
+		  (TYPE_MODE (TREE_TYPE (exp)),
+		   TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
 	exp = TREE_OPERAND (exp, 0);
 
       /* If what we're left with is the address of something, we can
@@ -4486,7 +4496,7 @@
       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
@@ -4569,7 +4579,7 @@
       switch (TREE_CODE (exp))
 	{
 	case CONSTRUCTOR:
-	  output_constructor (exp, size, align);
+	    output_constructor (exp, size, align, NULL);
 	  return;
 	case STRING_CST:
 	  thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
@@ -4607,7 +4617,7 @@
     case RECORD_TYPE:
     case UNION_TYPE:
       gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
-      output_constructor (exp, size, align);
+      output_constructor (exp, size, align, NULL);
       return;
 
     case ERROR_MARK:
@@ -4663,316 +4673,462 @@
   return tree_low_cst (i, 1);
 }
 
-/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
-   Generate at least SIZE bytes, padding if necessary.  */
+/* Other datastructures + helpers for output_constructor.  */
+
+/* output_constructor local state to support interaction with helpers.  */
+
+typedef struct {
+
+  /* Received arguments.  */
+  tree exp;                     /* Constructor expression.  */
+  unsigned HOST_WIDE_INT size;  /* # bytes to output - pad if necessary.  */
+  unsigned int align;           /* Known initial alignment.  */
+
+  /* Constructor expression data.  */
+  tree type;       /* Expression type.  */
+  tree field;      /* Current field decl in a record.  */
+  tree min_index;  /* Lower bound if specified for an array.  */
+
+  /* Output processing state.  */
+  HOST_WIDE_INT total_bytes;  /* # bytes output so far / current position.  */
+  bool byte_buffer_in_use;    /* Whether byte ...  */
+  int byte;                   /* ... contains part of a bitfield byte yet to
+			         be output.  */
+
+  int last_relative_index;    /* Implicit or explicit index of the last
+				 array element output within a bitfield.  */
+  /* Current element.  */
+  tree val;    /* Current element value.  */
+  tree index;  /* Current element index.  */
+
+} oc_local_state;
+
+/* Helper for output_constructor.  From the current LOCAL state, output a
+   RANGE_EXPR element.  */
+
+static void
+output_constructor_array_range (oc_local_state *local)
+{
+  unsigned HOST_WIDE_INT fieldsize
+    = int_size_in_bytes (TREE_TYPE (local->type));
+
+  HOST_WIDE_INT lo_index
+    = tree_low_cst (TREE_OPERAND (local->index, 0), 0);
+  HOST_WIDE_INT hi_index
+    = tree_low_cst (TREE_OPERAND (local->index, 1), 0);
+  HOST_WIDE_INT index;
+
+  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.  */
+      if (local->val == NULL_TREE)
+	assemble_zeros (fieldsize);
+      else
+	output_constant (local->val, fieldsize, align2);
+
+      /* Count its size.  */
+      local->total_bytes += fieldsize;
+    }
+}
+
+/* Helper for output_constructor.  From the current LOCAL state, output a
+   field element that is not true bitfield or part of an outer one.  */
+
+static void
+output_constructor_regular_field (oc_local_state *local)
+{
+  /* Field size and position.  Since this structure is static, we know the
+     positions are constant.  */
+  unsigned HOST_WIDE_INT fieldsize;
+  HOST_WIDE_INT fieldpos;
+
+  unsigned int align2;
+
+  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->min_index, 0))));
+  else if (local->field != NULL_TREE)
+    fieldpos = int_byte_position (local->field);
+  else
+    fieldpos = 0;
+
+  /* Output any buffered-up bit-fields preceding this element.  */
+  if (local->byte_buffer_in_use)
+    {
+      assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+      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.  */
+  if ((local->field != NULL_TREE || local->index != NULL_TREE)
+      && fieldpos != local->total_bytes)
+    {
+      gcc_assert (fieldpos >= local->total_bytes);
+      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);
+
+  /* Determine size this element should occupy.  */
+  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,
+	 but we cannot do this until the deprecated support for
+	 initializing zero-length array members is removed.  */
+      if (TREE_CODE (TREE_TYPE (local->field)) == ARRAY_TYPE
+	  && TYPE_DOMAIN (TREE_TYPE (local->field))
+	  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field))))
+	{
+	  fieldsize = array_size_for_constructor (local->val);
+	  /* Given a non-empty initialization, this field had
+	     better be last.  */
+	  gcc_assert (!fieldsize || !TREE_CHAIN (local->field));
+	}
+      else if (DECL_SIZE_UNIT (local->field))
+	{
+	  /* ??? This can't be right.  If the decl size overflows
+	     a host integer we will silently emit no data.  */
+	  if (host_integerp (DECL_SIZE_UNIT (local->field), 1))
+	    fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
+	}
+    }
+  else
+    fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
+
+  /* Output the element's initial value.  */
+  if (local->val == NULL_TREE)
+    assemble_zeros (fieldsize);
+  else
+    output_constant (local->val, fieldsize, align2);
+
+  /* Count its size.  */
+  local->total_bytes += fieldsize;
+}
+
+/* Helper for output_constructor.  From the current LOCAL and OUTER states,
+   output an element that is a true bitfield or part of an outer one.  */
 
 static void
+output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
+{
+  /* Bit size of this element.  */
+  HOST_WIDE_INT ebitsize
+    = (local->field
+       ? tree_low_cst (DECL_SIZE (local->field), 1)
+       : tree_low_cst (TYPE_SIZE (TREE_TYPE (local->type)), 1));
+
+  /* Relative index of this element if this is an array component.  */
+  HOST_WIDE_INT relative_index
+    = (!local->field
+       ? (local->index
+	  ? (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)
+	 : 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
+     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)
+    {
+      error ("invalid initial value for member %qE", DECL_NAME (local->field));
+      return;
+    }
+
+  /* If this field does not start in this (or, next) byte,
+     skip some bytes.  */
+  if (next_offset / BITS_PER_UNIT != local->total_bytes)
+    {
+      /* Output remnant of any bit field in previous bytes.  */
+      if (local->byte_buffer_in_use)
+	{
+	  assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+	  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)
+	{
+	  gcc_assert (next_offset / BITS_PER_UNIT >= local->total_bytes);
+	  assemble_zeros (next_offset / BITS_PER_UNIT - local->total_bytes);
+	  local->total_bytes = next_offset / BITS_PER_UNIT;
+	}
+    }
+
+  /* Set up the buffer if necessary.  */
+  if (!local->byte_buffer_in_use)
+    {
+      local->byte = 0;
+      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)
+    {
+      oc_outer_state output_state;
+
+      output_state.bit_offset = next_offset % BITS_PER_UNIT;
+      output_state.byte = local->byte;
+      local->total_bytes
+	  += output_constructor (local->val, 0, 0, &output_state);
+      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.  */
+  while (next_offset < end_offset)
+    {
+      int this_time;
+      int shift;
+      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)
+	{
+	  assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+	  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,
+		       BITS_PER_UNIT - next_bit);
+      if (BYTES_BIG_ENDIAN)
+	{
+	  /* On big-endian machine, take the most significant bits
+	     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
+	     not from both.  */
+	  if (shift < HOST_BITS_PER_WIDE_INT
+	      && shift + this_time > HOST_BITS_PER_WIDE_INT)
+	    {
+	      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);
+	  else
+	    {
+	      gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+	      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))
+			  << (BITS_PER_UNIT - this_time - next_bit));
+	}
+      else
+	{
+	  /* On little-endian machines,
+	     take first the least significant bits of the value
+	     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
+	     not from both.  */
+	  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);
+	  else
+	    {
+	      gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+	      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;
+    }
+}
+
+/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
+   Generate at least SIZE bytes, padding if necessary.  OUTER designates the
+   caller output state of relevance in recursive invocations.  */
+
+static unsigned HOST_WIDE_INT
 output_constructor (tree exp, unsigned HOST_WIDE_INT size,
-		    unsigned int align)
-{
-  tree type = TREE_TYPE (exp);
-  tree field = 0;
-  tree min_index = 0;
-  /* Number of bytes output or skipped so far.
-     In other words, current position within the constructor.  */
-  HOST_WIDE_INT total_bytes = 0;
-  /* Nonzero means BYTE contains part of a byte, to be output.  */
-  int byte_buffer_in_use = 0;
-  int byte = 0;
+		    unsigned int align, oc_outer_state * outer)
+{
   unsigned HOST_WIDE_INT cnt;
   constructor_elt *ce;
 
+  oc_local_state local;
+
+  /* Setup our local state to communicate with helpers.  */
+  local.exp = exp;
+  local.size = size;
+  local.align = align;
+
+  local.total_bytes = 0;
+  local.byte_buffer_in_use = outer != NULL;
+  local.byte = outer ? outer->byte : 0;
+
+  local.type = TREE_TYPE (exp);
+
+  local.last_relative_index = -1;
+
+  local.min_index = NULL_TREE;
+  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);
 
-  if (TREE_CODE (type) == RECORD_TYPE)
-    field = TYPE_FIELDS (type);
-
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type) != 0)
-    min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
-
-  /* As LINK goes through the elements of the constant,
-     FIELD goes through the structure fields, if the constant is a structure.
-     if the constant is a union, then we override this,
-     by getting the field from the TREE_LIST element.
+  /* As CE goes through the elements of the constant, FIELD goes through the
+     structure fields if the constant is a structure.  If the constant is a
+     union, we override this by getting the field from the TREE_LIST element.
      But the constant could also be an array.  Then FIELD is zero.
 
      There is always a maximum of one element in the chain LINK for unions
      (even if the initializer in a source program incorrectly contains
      more one).  */
+
+  local.field = NULL_TREE;
+  if (TREE_CODE (local.type) == RECORD_TYPE)
+    local.field = TYPE_FIELDS (local.type);
+
   for (cnt = 0;
        VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
-       cnt++, field = field ? TREE_CHAIN (field) : 0)
+       cnt++, local.field = local.field ? TREE_CHAIN (local.field) : 0)
     {
-      tree val = ce->value;
-      tree index = 0;
+      local.val = ce->value;
+      local.index = NULL_TREE;
 
       /* The element in a union constructor specifies the proper field
 	 or index.  */
-      if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
-	   || TREE_CODE (type) == QUAL_UNION_TYPE)
-	  && ce->index != 0)
-	field = ce->index;
-
-      else if (TREE_CODE (type) == ARRAY_TYPE)
-	index = ce->index;
+      if ((TREE_CODE (local.type) == RECORD_TYPE
+	   || TREE_CODE (local.type) == UNION_TYPE
+	   || TREE_CODE (local.type) == QUAL_UNION_TYPE)
+	  && ce->index != NULL_TREE)
+	local.field = ce->index;
+
+      else if (TREE_CODE (local.type) == ARRAY_TYPE)
+	local.index = ce->index;
 
 #ifdef ASM_COMMENT_START
-      if (field && flag_verbose_asm)
+      if (local.field && flag_verbose_asm)
 	fprintf (asm_out_file, "%s %s:\n",
 		 ASM_COMMENT_START,
-		 DECL_NAME (field)
-		 ? IDENTIFIER_POINTER (DECL_NAME (field))
+		 DECL_NAME (local.field)
+		 ? IDENTIFIER_POINTER (DECL_NAME (local.field))
 		 : "<anonymous>");
 #endif
 
       /* Eliminate the marker that makes a cast not be an lvalue.  */
-      if (val != 0)
-	STRIP_NOPS (val);
-
-      if (index && TREE_CODE (index) == RANGE_EXPR)
-	{
-	  unsigned HOST_WIDE_INT fieldsize
-	    = int_size_in_bytes (TREE_TYPE (type));
-	  HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
-	  HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
-	  HOST_WIDE_INT index;
-	  unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
-
-	  for (index = lo_index; index <= hi_index; index++)
-	    {
-	      /* Output the element's initial value.  */
-	      if (val == 0)
-		assemble_zeros (fieldsize);
-	      else
-		output_constant (val, fieldsize, align2);
-
-	      /* Count its size.  */
-	      total_bytes += fieldsize;
-	    }
-	}
-      else if (field == 0 || !DECL_BIT_FIELD (field))
-	{
-	  /* An element that is not a bit-field.  */
-
-	  unsigned HOST_WIDE_INT fieldsize;
-	  /* Since this structure is static,
-	     we know the positions are constant.  */
-	  HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
-	  unsigned int align2;
-
-	  if (index != 0)
-	    pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
-		   * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
-
-	  /* Output any buffered-up bit-fields preceding this element.  */
-	  if (byte_buffer_in_use)
-	    {
-	      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-	      total_bytes++;
-	      byte_buffer_in_use = 0;
-	    }
-
-	  /* Advance to offset of this element.
-	     Note no alignment needed in an array, since that is guaranteed
-	     if each element has the proper size.  */
-	  if ((field != 0 || index != 0) && pos != total_bytes)
-	    {
-	      gcc_assert (pos >= total_bytes);
-	      assemble_zeros (pos - total_bytes);
-	      total_bytes = pos;
-	    }
-
-	  /* Find the alignment of this element.  */
-	  align2 = min_align (align, BITS_PER_UNIT * pos);
-
-	  /* Determine size this element should occupy.  */
-	  if (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,
-		 but we cannot do this until the deprecated support for
-		 initializing zero-length array members is removed.  */
-	      if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
-		  && TYPE_DOMAIN (TREE_TYPE (field))
-		  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
-		{
-		  fieldsize = array_size_for_constructor (val);
-		  /* Given a non-empty initialization, this field had
-		     better be last.  */
-		  gcc_assert (!fieldsize || !TREE_CHAIN (field));
-		}
-	      else if (DECL_SIZE_UNIT (field))
-		{
-		  /* ??? This can't be right.  If the decl size overflows
-		     a host integer we will silently emit no data.  */
-		  if (host_integerp (DECL_SIZE_UNIT (field), 1))
-		    fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
-		}
-	    }
-	  else
-	    fieldsize = int_size_in_bytes (TREE_TYPE (type));
-
-	  /* Output the element's initial value.  */
-	  if (val == 0)
-	    assemble_zeros (fieldsize);
-	  else
-	    output_constant (val, fieldsize, align2);
-
-	  /* Count its size.  */
-	  total_bytes += fieldsize;
-	}
-      else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
-	error ("invalid initial value for member %qs",
-	       IDENTIFIER_POINTER (DECL_NAME (field)));
+      if (local.val != NULL_TREE)
+	STRIP_NOPS (local.val);
+
+      /* Output the current element, using the appropriate helper ...  */
+
+      /* For an array slice not part of an outer bitfield.  */
+      if (!outer
+	  && local.index != NULL_TREE
+	  && TREE_CODE (local.index) == RANGE_EXPR)
+	output_constructor_array_range (&local);
+
+      /* For a field that is neither a true bitfield nor part of an outer one,
+	 known to be at least byte aligned and multiple-of-bytes long.  */
+      else if (!outer
+	       && (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);
+    }
+
+  /* If we are not at toplevel, save the pending data for our caller.
+     Otherwise output the pending data and padding zeros as needed. */
+  if (outer)
+    outer->byte = local.byte;
+  else
+    {
+      if (local.byte_buffer_in_use)
 	{
-	  /* Element that is a bit-field.  */
-
-	  HOST_WIDE_INT next_offset = int_bit_position (field);
-	  HOST_WIDE_INT end_offset
-	    = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
-
-	  if (val == 0)
-	    val = integer_zero_node;
-
-	  /* If this field does not start in this (or, next) byte,
-	     skip some bytes.  */
-	  if (next_offset / BITS_PER_UNIT != total_bytes)
-	    {
-	      /* Output remnant of any bit field in previous bytes.  */
-	      if (byte_buffer_in_use)
-		{
-		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-		  total_bytes++;
-		  byte_buffer_in_use = 0;
-		}
-
-	      /* If still not at proper byte, advance to there.  */
-	      if (next_offset / BITS_PER_UNIT != total_bytes)
-		{
-		  gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes);
-		  assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
-		  total_bytes = next_offset / BITS_PER_UNIT;
-		}
-	    }
-
-	  if (! byte_buffer_in_use)
-	    byte = 0;
-
-	  /* We must split the element into pieces that fall within
-	     separate bytes, and combine each byte with previous or
-	     following bit-fields.  */
-
-	  /* next_offset is the offset n fbits from the beginning of
-	     the structure to the next bit of this element to be processed.
-	     end_offset is the offset of the first bit past the end of
-	     this element.  */
-	  while (next_offset < end_offset)
-	    {
-	      int this_time;
-	      int shift;
-	      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 != total_bytes)
-		{
-		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-		  total_bytes++;
-		  byte = 0;
-		}
-
-	      /* Number of bits we can process at once
-		 (all part of the same byte).  */
-	      this_time = MIN (end_offset - next_offset,
-			       BITS_PER_UNIT - next_bit);
-	      if (BYTES_BIG_ENDIAN)
-		{
-		  /* On big-endian machine, take the most significant bits
-		     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
-		     not from both.  */
-		  if (shift < HOST_BITS_PER_WIDE_INT
-		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
-		    {
-		      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 (val);
-		  else
-		    {
-		      gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
-		      value = TREE_INT_CST_HIGH (val);
-		      shift -= HOST_BITS_PER_WIDE_INT;
-		    }
-
-		  /* Get the result. This works only when:
-		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-		  byte |= (((value >> shift)
-			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-			   << (BITS_PER_UNIT - this_time - next_bit));
-		}
-	      else
-		{
-		  /* On little-endian machines,
-		     take first the least significant bits of the value
-		     and pack them starting at the least significant
-		     bits of the bytes.  */
-		  shift = next_offset - int_bit_position (field);
-
-		  /* 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
-		     not from both.  */
-		  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 (val);
-		  else
-		    {
-		      gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
-		      value = TREE_INT_CST_HIGH (val);
-		      shift -= HOST_BITS_PER_WIDE_INT;
-		    }
-
-		  /* Get the result. This works only when:
-		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-		  byte |= (((value >> shift)
-			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-			   << next_bit);
-		}
-
-	      next_offset += this_time;
-	      byte_buffer_in_use = 1;
-	    }
+	  assemble_integer (GEN_INT (local.byte), 1, BITS_PER_UNIT, 1);
+	  local.total_bytes++;
+	}
+
+      if ((unsigned HOST_WIDE_INT)local.total_bytes < local.size)
+	{
+	  assemble_zeros (local.size - local.total_bytes);
+	  local.total_bytes = local.size;
 	}
     }
 
-  if (byte_buffer_in_use)
-    {
-      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-      total_bytes++;
-    }
-
-  if ((unsigned HOST_WIDE_INT)total_bytes < size)
-    assemble_zeros (size - total_bytes);
+  return local.total_bytes;
 }
 
 /* Mark DECL as weak.  */
@@ -5071,9 +5227,6 @@
     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
@@ -5143,7 +5296,8 @@
 
 	  if (! decl)
 	    {
-	      decl = build_decl (TREE_CODE (alias_decl), target,
+	      decl = build_decl (DECL_SOURCE_LOCATION (alias_decl),
+				 TREE_CODE (alias_decl), target,
 				 TREE_TYPE (alias_decl));
 
 	      DECL_EXTERNAL (decl) = 1;
@@ -5239,21 +5393,7 @@
   targetm.asm_out.globalize_decl_name (asm_out_file, decl);
 }
 
-/* We have to be able to tell cgraph about the needed-ness of the target
-   of an alias.  This requires that the decl have been defined.  Aliases
-   that precede their definition have to be queued for later processing.  */
-
-typedef struct alias_pair GTY(())
-{
-  tree decl;
-  tree target;
-} alias_pair;
-
-/* Define gc'd vector type.  */
-DEF_VEC_O(alias_pair);
-DEF_VEC_ALLOC_O(alias_pair,gc);
-
-static GTY(()) VEC(alias_pair,gc) *alias_pairs;
+VEC(alias_pair,gc) *alias_pairs;
 
 /* Given an assembly name, find the decl it is associated with.  At the
    same time, mark it needed for cgraph.  */
@@ -5279,13 +5419,7 @@
 
   if (fnode)
     {
-      /* We can't mark function nodes as used after cgraph global info
-	 is finished.  This wouldn't generally be necessary, but C++
-	 virtual table thunks are introduced late in the game and
-	 might seem like they need marking, although in fact they
-	 don't.  */
-      if (! cgraph_global_info_ready)
-	cgraph_mark_needed_node (fnode);
+      cgraph_mark_needed_node (fnode);
       return fnode->decl;
     }
   else if (vnode)
@@ -5332,7 +5466,8 @@
 #else
       if (!SUPPORTS_WEAK)
 	{
-	  error ("%Jweakref is not supported in this configuration", decl);
+	  error_at (DECL_SOURCE_LOCATION (decl),
+		    "weakref is not supported in this configuration");
 	  return;
 	}
 #endif
@@ -5396,6 +5531,39 @@
 #endif
 }
 
+
+/* Remove the alias pairing for functions that are no longer in the call
+   graph.  */
+
+void
+remove_unreachable_alias_pairs (void)
+{
+  unsigned i;
+  alias_pair *p;
+
+  if (alias_pairs == NULL)
+    return;
+
+  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); )
+    {
+      if (!DECL_EXTERNAL (p->decl))
+	{
+	  struct cgraph_node *fnode = NULL;
+	  struct varpool_node *vnode = NULL;
+	  fnode = cgraph_node_for_asm (p->target);
+	  vnode = (fnode == NULL) ? varpool_node_for_asm (p->target) : NULL;
+	  if (fnode == NULL && vnode == NULL)
+	    {
+	      VEC_unordered_remove (alias_pair, alias_pairs, i);
+	      continue;
+	    }
+	}
+
+      i++;
+    }
+}
+
+
 /* First pass of completing pending aliases.  Make sure that cgraph knows
    which symbols will be required.  */
 
@@ -5413,13 +5581,18 @@
       if (target_decl == NULL)
 	{
 	  if (! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
-	    error ("%q+D aliased to undefined symbol %qs",
-		   p->decl, IDENTIFIER_POINTER (p->target));
+	    error ("%q+D aliased to undefined symbol %qE",
+		   p->decl, p->target);
 	}
       else if (DECL_EXTERNAL (target_decl)
+ 	       /* We use local aliases for C++ thunks to force the tailcall
+ 		  to bind locally.  Of course this is a hack - to keep it
+ 		  working do the following (which is not strictly correct).  */
+ 	       && (! TREE_CODE (target_decl) == FUNCTION_DECL
+ 		   || ! DECL_VIRTUAL_P (target_decl))
 	       && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
-	error ("%q+D aliased to external symbol %qs",
-	       p->decl, IDENTIFIER_POINTER (p->target));
+	error ("%q+D aliased to external symbol %qE",
+	       p->decl, p->target);
     }
 }
 
@@ -5472,12 +5645,14 @@
     {
 #if !defined (ASM_OUTPUT_DEF)
 # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
-      error ("%Jalias definitions not supported in this configuration", decl);
+      error_at (DECL_SOURCE_LOCATION (decl),
+		"alias definitions not supported in this configuration");
       return;
 # else
       if (!DECL_WEAK (decl))
 	{
-	  error ("%Jonly weak aliases are supported in this configuration", decl);
+	  error_at (DECL_SOURCE_LOCATION (decl),
+		    "only weak aliases are supported in this configuration");
 	  return;
 	}
 # endif
@@ -5575,7 +5750,7 @@
    translation units without generating a linker error.  */
 
 void
-make_decl_one_only (tree decl)
+make_decl_one_only (tree decl, tree comdat_group)
 {
   gcc_assert (TREE_CODE (decl) == VAR_DECL
 	      || TREE_CODE (decl) == FUNCTION_DECL);
@@ -5587,7 +5762,7 @@
 #ifdef MAKE_DECL_ONE_ONLY
       MAKE_DECL_ONE_ONLY (decl);
 #endif
-      DECL_ONE_ONLY (decl) = 1;
+      DECL_COMDAT_GROUP (decl) = comdat_group;
     }
   else if (TREE_CODE (decl) == VAR_DECL
       && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
@@ -5847,8 +6022,13 @@
       if (flags & SECTION_ENTSIZE)
 	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
       if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
-	fprintf (asm_out_file, ",%s,comdat",
-		 lang_hooks.decls.comdat_group (decl));
+	{
+	  if (TREE_CODE (decl) == IDENTIFIER_NODE)
+	    fprintf (asm_out_file, ",%s,comdat", IDENTIFIER_POINTER (decl));
+	  else
+	    fprintf (asm_out_file, ",%s,comdat",
+		     IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl)));
+	}
     }
 
   putc ('\n', asm_out_file);
@@ -6165,7 +6345,7 @@
   /* 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);
@@ -6265,8 +6445,8 @@
     flags |= SYMBOL_FLAG_FUNCTION;
   if (targetm.binds_local_p (decl))
     flags |= SYMBOL_FLAG_LOCAL;
-  if (targetm.have_tls && TREE_CODE (decl) == VAR_DECL
-      && DECL_THREAD_LOCAL_P (decl))
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)
+      && DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED)
     flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
   else if (targetm.in_small_data_p (decl))
     flags |= SYMBOL_FLAG_SMALL;
@@ -6400,14 +6580,6 @@
   return local_p;
 }
 
-/* Determine whether or not a pointer mode is valid. Assume defaults
-   of ptr_mode or Pmode - can be overridden.  */
-bool
-default_valid_pointer_mode (enum machine_mode mode)
-{
-  return (mode == ptr_mode || mode == Pmode);
-}
-
 /* Default function to output code that will globalize a label.  A
    target must define GLOBAL_ASM_OP or provide its own function to
    globalize a label.  */