OSDN Git Service

2010-04-06 Matthias Klose <doko@ubuntu.com>
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 511bf89..af9adff 100644 (file)
@@ -1,13 +1,13 @@
 /* Output variables, constants and external declarations, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
 /* 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
-   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.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file handles generation of all the assembler code
 
 
 /* This file handles generation of all the assembler code
@@ -43,12 +42,12 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "output.h"
 #include "toplev.h"
 #include "hashtab.h"
 #include "output.h"
 #include "toplev.h"
 #include "hashtab.h"
-#include "c-pragma.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tm_p.h"
 #include "debug.h"
 #include "target.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tm_p.h"
 #include "debug.h"
 #include "target.h"
+#include "targhooks.h"
 #include "tree-mudflap.h"
 #include "cgraph.h"
 #include "cfglayout.h"
 #include "tree-mudflap.h"
 #include "cgraph.h"
 #include "cfglayout.h"
@@ -71,17 +70,7 @@ struct addr_const;
 struct constant_descriptor_rtx;
 struct rtx_constant_pool;
 
 struct constant_descriptor_rtx;
 struct rtx_constant_pool;
 
-struct varasm_status GTY(())
-{
-  /* If we're using a per-function constant pool, this is it.  */
-  struct rtx_constant_pool *pool;
-
-  /* Number of tree-constants deferred during the expansion of this
-     function.  */
-  unsigned int deferred_constants;
-};
-
-#define n_deferred_constants (cfun->varasm->deferred_constants)
+#define n_deferred_constants (crtl->varasm.deferred_constants)
 
 /* Number for making the label on the next
    constant that is stored in memory.  */
 
 /* Number for making the label on the next
    constant that is stored in memory.  */
@@ -108,7 +97,7 @@ bool first_function_block_is_cold;
 /* We give all constants their own alias set.  Perhaps redundant with
    MEM_READONLY_P, but pre-dates it.  */
 
 /* We give all constants their own alias set.  Perhaps redundant with
    MEM_READONLY_P, but pre-dates it.  */
 
-static HOST_WIDE_INT const_alias_set;
+static alias_set_type const_alias_set;
 
 static const char *strip_reg_name (const char *);
 static int contains_pointers_p (tree);
 
 static const char *strip_reg_name (const char *);
 static int contains_pointers_p (tree);
@@ -125,7 +114,6 @@ static void output_constant_def_contents (rtx);
 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_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
 static void globalize_decl (tree);
 #ifdef BSS_SECTION_ASM_OP
 #ifdef ASM_OUTPUT_BSS
@@ -205,68 +193,100 @@ static GTY(()) struct rtx_constant_pool *shared_constant_pool;
 static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
      htab_t emutls_htab;
 static GTY (()) tree emutls_object_type;
 static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
      htab_t emutls_htab;
 static GTY (()) tree emutls_object_type;
-
-#ifndef NO_DOT_IN_LABEL
-# define EMUTLS_VAR_PREFIX     "__emutls_v."
-# define EMUTLS_TMPL_PREFIX    "__emutls_t."
-#elif !defined NO_DOLLAR_IN_LABEL
-# define EMUTLS_VAR_PREFIX     "__emutls_v$"
-# define EMUTLS_TMPL_PREFIX    "__emutls_t$"
+/* Emulated TLS objects have the TLS model TLS_MODEL_EMULATED.  This
+   macro can be used on them to distinguish the control variable from
+   the initialization template.  */
+#define DECL_EMUTLS_VAR_P(D)  (TREE_TYPE (D) == emutls_object_type)
+
+#if !defined (NO_DOT_IN_LABEL)
+# define EMUTLS_SEPARATOR      "."
+#elif !defined (NO_DOLLAR_IN_LABEL)
+# define EMUTLS_SEPARATOR      "$"
 #else
 #else
-# define EMUTLS_VAR_PREFIX     "__emutls_v_"
-# define EMUTLS_TMPL_PREFIX    "__emutls_t_"
+# define EMUTLS_SEPARATOR      "_"
 #endif
 
 #endif
 
-/* Create an identifier for the struct __emutls_object, given an identifier
-   of the DECL_ASSEMBLY_NAME of the original object.  */
+/* Create an IDENTIFIER_NODE by prefixing PREFIX to the
+   IDENTIFIER_NODE NAME's name.  */
 
 static tree
 
 static tree
-get_emutls_object_name (tree name)
+prefix_name (const char *prefix, tree name)
 {
 {
-  char *toname = alloca (strlen (IDENTIFIER_POINTER (name))
-                        + sizeof (EMUTLS_VAR_PREFIX));
-  strcpy (toname, EMUTLS_VAR_PREFIX);
-  strcpy (toname + sizeof (EMUTLS_VAR_PREFIX) - 1, IDENTIFIER_POINTER (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);
 
   return get_identifier (toname);
 }
 
 
   return get_identifier (toname);
 }
 
-/* Create the structure for struct __emutls_object.  This should match the
-   structure at the top of emutls.c, modulo the union there.  */
+/* Create an identifier for the struct __emutls_object, given an identifier
+   of the DECL_ASSEMBLY_NAME of the original object.  */
 
 static tree
 
 static tree
-get_emutls_object_type (void)
+get_emutls_object_name (tree name)
 {
 {
-  tree type, type_name, field, next_field, word_type_node;
-
-  type = emutls_object_type;
-  if (type)
-    return type;
+  const char *prefix = (targetm.emutls.var_prefix
+                       ? targetm.emutls.var_prefix
+                       : "__emutls_v" EMUTLS_SEPARATOR);
+  return prefix_name (prefix, name);
+}
 
 
-  emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE);
-  type_name = get_identifier ("__emutls_object");
-  type_name = build_decl (TYPE_DECL, type_name, type);
-  TYPE_NAME (type) = type_name;
+tree
+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;
 
   DECL_CONTEXT (field) = type;
   next_field = field;
 
-  field = build_decl (FIELD_DECL, get_identifier ("__offset"), ptr_type_node);
+  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);
   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"), word_type_node);
+  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;
 
   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;
 
   DECL_CONTEXT (field) = type;
   TREE_CHAIN (field) = next_field;
 
+  return field;
+}
+
+/* Create the structure for struct __emutls_object.  This should match the
+   structure at the top of emutls.c, modulo the union there.  */
+
+static tree
+get_emutls_object_type (void)
+{
+  tree type, type_name, field;
+
+  type = emutls_object_type;
+  if (type)
+    return type;
+
+  emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE);
+  type_name = NULL;
+  field = targetm.emutls.var_fields (type, &type_name);
+  if (!type_name)
+    type_name = get_identifier ("__emutls_object");
+  type_name = build_decl (UNKNOWN_LOCATION,
+                         TYPE_DECL, type_name, type);
+  TYPE_NAME (type) = type_name;
   TYPE_FIELDS (type) = field;
   layout_type (type);
 
   TYPE_FIELDS (type) = field;
   layout_type (type);
 
@@ -280,30 +300,35 @@ static tree
 get_emutls_init_templ_addr (tree decl)
 {
   tree name, to;
 get_emutls_init_templ_addr (tree decl)
 {
   tree name, to;
-  char *toname;
 
 
-  if (!DECL_INITIAL (decl))
+  if (targetm.emutls.register_common && !DECL_INITIAL (decl)
+      && !DECL_SECTION_NAME (decl))
     return null_pointer_node;
 
   name = DECL_ASSEMBLER_NAME (decl);
     return null_pointer_node;
 
   name = DECL_ASSEMBLER_NAME (decl);
-  toname = alloca (strlen (IDENTIFIER_POINTER (name))
-                  + sizeof (EMUTLS_TMPL_PREFIX));
-  strcpy (toname, EMUTLS_TMPL_PREFIX);
-  strcpy (toname + sizeof (EMUTLS_TMPL_PREFIX) - 1, IDENTIFIER_POINTER (name));
-  name = get_identifier (toname);
+  if (!targetm.emutls.tmpl_prefix || targetm.emutls.tmpl_prefix[0])
+    {
+      const char *prefix = (targetm.emutls.tmpl_prefix
+                           ? targetm.emutls.tmpl_prefix
+                           : "__emutls_t" EMUTLS_SEPARATOR);
+      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));
   SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
-
+  DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
   DECL_ARTIFICIAL (to) = 1;
   TREE_USED (to) = TREE_USED (decl);
   TREE_READONLY (to) = 1;
   DECL_IGNORED_P (to) = 1;
   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
   DECL_ARTIFICIAL (to) = 1;
   TREE_USED (to) = TREE_USED (decl);
   TREE_READONLY (to) = 1;
   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))
     {
   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);
       TREE_STATIC (to) = TREE_STATIC (decl);
       TREE_PUBLIC (to) = TREE_PUBLIC (decl);
       DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
@@ -345,28 +370,33 @@ emutls_decl (tree decl)
   in.hash = htab_hash_string (IDENTIFIER_POINTER (name));
   in.base.from = decl;
   loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT);
   in.hash = htab_hash_string (IDENTIFIER_POINTER (name));
   in.base.from = decl;
   loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT);
-  h = *loc;
+  h = (struct tree_map *) *loc;
   if (h != NULL)
     to = h->to;
   else
     {
   if (h != NULL)
     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 ());
 
                       get_emutls_object_type ());
 
-      h = ggc_alloc (sizeof (struct tree_map));
+      h = GGC_NEW (struct tree_map);
       h->hash = in.hash;
       h->base.from = decl;
       h->to = to;
       *(struct tree_map **) loc = h;
 
       h->hash = in.hash;
       h->base.from = decl;
       h->to = to;
       *(struct tree_map **) loc = h;
 
+      DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
       DECL_ARTIFICIAL (to) = 1;
       DECL_IGNORED_P (to) = 1;
       TREE_READONLY (to) = 0;
       DECL_ARTIFICIAL (to) = 1;
       DECL_IGNORED_P (to) = 1;
       TREE_READONLY (to) = 0;
-
       SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
       if (DECL_ONE_ONLY (decl))
       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);
       DECL_CONTEXT (to) = DECL_CONTEXT (decl);
+      if (targetm.emutls.var_align_fixed)
+       /* If we're not allowed to change the proxy object's
+          alignment, pretend it's been set by the user.  */
+       DECL_USER_ALIGN (to) = 1;
     }
 
   /* Note that these fields may need to be updated from time to time from
     }
 
   /* Note that these fields may need to be updated from time to time from
@@ -415,7 +445,7 @@ emutls_common_1 (void **loc, void *xstmts)
   args = tree_cons (NULL, x, args);
 
   x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
   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;
 
   append_to_statement_list (x, pstmts);
   return 1;
@@ -424,16 +454,19 @@ emutls_common_1 (void **loc, void *xstmts)
 void
 emutls_finish (void)
 {
 void
 emutls_finish (void)
 {
-  tree body = NULL_TREE;
+  if (targetm.emutls.register_common)
+    {
+      tree body = NULL_TREE;
 
 
-  if (emutls_htab == NULL)
-    return;
+      if (emutls_htab == NULL)
+       return;
 
 
-  htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
-  if (body == NULL_TREE)
-    return;
+      htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
+      if (body == NULL_TREE)
+       return;
 
 
-  cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
+      cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
+    }
 }
 
 /* Helper routines for maintaining section_htab.  */
 }
 
 /* Helper routines for maintaining section_htab.  */
@@ -441,16 +474,16 @@ emutls_finish (void)
 static int
 section_entry_eq (const void *p1, const void *p2)
 {
 static int
 section_entry_eq (const void *p1, const void *p2)
 {
-  const section *old = p1;
-  const char *new = p2;
+  const section *old = (const section *) p1;
+  const char *new_name = (const char *) p2;
 
 
-  return strcmp (old->named.name, new) == 0;
+  return strcmp (old->named.name, new_name) == 0;
 }
 
 static hashval_t
 section_entry_hash (const void *p)
 {
 }
 
 static hashval_t
 section_entry_hash (const void *p)
 {
-  const section *old = p;
+  const section *old = (const section *) p;
   return htab_hash_string (old->named.name);
 }
 
   return htab_hash_string (old->named.name);
 }
 
@@ -469,16 +502,16 @@ hash_section (section *sect)
 static int
 object_block_entry_eq (const void *p1, const void *p2)
 {
 static int
 object_block_entry_eq (const void *p1, const void *p2)
 {
-  const struct object_block *old = p1;
-  const section *new = p2;
+  const struct object_block *old = (const struct object_block *) p1;
+  const section *new_section = (const section *) p2;
 
 
-  return old->sect == new;
+  return old->sect == new_section;
 }
 
 static hashval_t
 object_block_entry_hash (const void *p)
 {
 }
 
 static hashval_t
 object_block_entry_hash (const void *p)
 {
-  const struct object_block *old = p;
+  const struct object_block *old = (const struct object_block *) p;
   return hash_section (old->sect);
 }
 
   return hash_section (old->sect);
 }
 
@@ -490,7 +523,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
 {
   section *sect;
 
 {
   section *sect;
 
-  sect = ggc_alloc (sizeof (struct unnamed_section));
+  sect = GGC_NEW (section);
   sect->unnamed.common.flags = flags | SECTION_UNNAMED;
   sect->unnamed.callback = callback;
   sect->unnamed.data = data;
   sect->unnamed.common.flags = flags | SECTION_UNNAMED;
   sect->unnamed.callback = callback;
   sect->unnamed.data = data;
@@ -507,7 +540,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
 {
   section *sect;
 
 {
   section *sect;
 
-  sect = ggc_alloc (sizeof (struct unnamed_section));
+  sect = GGC_NEW (section);
   sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
   sect->noswitch.callback = callback;
 
   sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
   sect->noswitch.callback = callback;
 
@@ -528,7 +561,7 @@ get_section (const char *name, unsigned int flags, tree decl)
   flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
   flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
-      sect = ggc_alloc (sizeof (struct named_section));
+      sect = GGC_NEW (section);
       sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
       sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
@@ -598,7 +631,7 @@ create_block_symbol (const char *label, struct object_block *block,
 
   /* Create the extended SYMBOL_REF.  */
   size = RTX_HDR_SIZE + sizeof (struct block_symbol);
 
   /* Create the extended SYMBOL_REF.  */
   size = RTX_HDR_SIZE + sizeof (struct block_symbol);
-  symbol = ggc_alloc_zone (size, &rtl_zone);
+  symbol = (rtx) ggc_alloc_zone (size, &rtl_zone);
 
   /* Initialize the normal SYMBOL_REF fields.  */
   memset (symbol, 0, size);
 
   /* Initialize the normal SYMBOL_REF fields.  */
   memset (symbol, 0, size);
@@ -622,22 +655,22 @@ initialize_cold_section_name (void)
   tree dsn;
 
   gcc_assert (cfun && current_function_decl);
   tree dsn;
 
   gcc_assert (cfun && current_function_decl);
-  if (cfun->unlikely_text_section_name)
+  if (crtl->subsections.unlikely_text_section_name)
     return;
 
   dsn = DECL_SECTION_NAME (current_function_decl);
   if (flag_function_sections && dsn)
     {
     return;
 
   dsn = DECL_SECTION_NAME (current_function_decl);
   if (flag_function_sections && dsn)
     {
-      name = alloca (TREE_STRING_LENGTH (dsn) + 1);
+      name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
       memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1);
 
       stripped_name = targetm.strip_name_encoding (name);
 
       buffer = ACONCAT ((stripped_name, "_unlikely", NULL));
       memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1);
 
       stripped_name = targetm.strip_name_encoding (name);
 
       buffer = ACONCAT ((stripped_name, "_unlikely", NULL));
-      cfun->unlikely_text_section_name = ggc_strdup (buffer);
+      crtl->subsections.unlikely_text_section_name = ggc_strdup (buffer);
     }
   else
     }
   else
-    cfun->unlikely_text_section_name =  UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
+    crtl->subsections.unlikely_text_section_name =  UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
 }
 
 /* Tell assembler to switch to unlikely-to-be-executed text section.  */
 }
 
 /* Tell assembler to switch to unlikely-to-be-executed text section.  */
@@ -647,10 +680,10 @@ unlikely_text_section (void)
 {
   if (cfun)
     {
 {
   if (cfun)
     {
-      if (!cfun->unlikely_text_section_name)
+      if (!crtl->subsections.unlikely_text_section_name)
        initialize_cold_section_name ();
 
        initialize_cold_section_name ();
 
-      return get_named_section (NULL, cfun->unlikely_text_section_name, 0);
+      return get_named_section (NULL, crtl->subsections.unlikely_text_section_name, 0);
     }
   else
     return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
     }
   else
     return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
@@ -667,7 +700,7 @@ unlikely_text_section_p (section *sect)
   const char *name;
 
   if (cfun)
   const char *name;
 
   if (cfun)
-    name = cfun->unlikely_text_section_name;
+    name = crtl->subsections.unlikely_text_section_name;
   else
     name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
 
   else
     name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
 
@@ -841,11 +874,18 @@ default_function_rodata_section (tree decl)
 
       if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
         {
 
       if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
         {
-         size_t len = strlen (name) + 3;
-         char* rname = 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");
 
          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.  */
          return get_section (rname, SECTION_LINKONCE, decl);
        }
       /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo.  */
@@ -853,7 +893,7 @@ default_function_rodata_section (tree decl)
               && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
        {
          size_t len = strlen (name) + 1;
               && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
        {
          size_t len = strlen (name) + 1;
-         char *rname = alloca (len);
+         char *rname = (char *) alloca (len);
 
          memcpy (rname, name, len);
          rname[14] = 'r';
 
          memcpy (rname, name, len);
          rname[14] = 'r';
@@ -864,7 +904,7 @@ default_function_rodata_section (tree decl)
               && strncmp (name, ".text.", 6) == 0)
        {
          size_t len = strlen (name) + 1;
               && strncmp (name, ".text.", 6) == 0)
        {
          size_t len = strlen (name) + 1;
-         char *rname = alloca (len + 2);
+         char *rname = (char *) alloca (len + 2);
 
          memcpy (rname, ".rodata", 7);
          memcpy (rname + 7, name + 5, len - 5);
 
          memcpy (rname, ".rodata", 7);
          memcpy (rname + 7, name + 5, len - 5);
@@ -987,7 +1027,7 @@ strip_reg_name (const char *name)
 void
 set_user_assembler_name (tree decl, const char *name)
 {
 void
 set_user_assembler_name (tree decl, const char *name)
 {
-  char *starred = alloca (strlen (name) + 2);
+  char *starred = (char *) alloca (strlen (name) + 2);
   starred[0] = '*';
   strcpy (starred + 1, name);
   change_decl_assembler_name (decl, get_identifier (starred));
   starred[0] = '*';
   strcpy (starred + 1, name);
   change_decl_assembler_name (decl, get_identifier (starred));
@@ -1057,7 +1097,7 @@ decode_reg_name (const char *asmspec)
 /* Return true if DECL's initializer is suitable for a BSS section.  */
 
 static bool
 /* Return true if DECL's initializer is suitable for a BSS section.  */
 
 static bool
-bss_initializer_p (tree decl)
+bss_initializer_p (const_tree decl)
 {
   return (DECL_INITIAL (decl) == NULL
          || DECL_INITIAL (decl) == error_mark_node
 {
   return (DECL_INITIAL (decl) == NULL
          || DECL_INITIAL (decl) == error_mark_node
@@ -1128,15 +1168,27 @@ align_variable (tree decl, bool dont_output_data)
 static section *
 get_variable_section (tree decl, bool prefer_noswitch_p)
 {
 static section *
 get_variable_section (tree decl, bool prefer_noswitch_p)
 {
+  addr_space_t as = ADDR_SPACE_GENERIC;
   int reloc;
 
   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 (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;
       if (DECL_THREAD_LOCAL_P (decl))
        return tls_comm_section;
-      if (TREE_PUBLIC (decl) && bss_initializer_p (decl))
+      /* This cannot be common bss for an emulated TLS object without
+        a register_common hook.  */
+      else if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED
+              && !targetm.emutls.register_common)
+       ;
+      else if (TREE_PUBLIC (decl) && bss_initializer_p (decl))
        return comm_section;
     }
 
        return comm_section;
     }
 
@@ -1151,7 +1203,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
   if (IN_NAMED_SECTION (decl))
     return get_named_section (decl, NULL, reloc);
 
   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))
     {
       && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
       && bss_initializer_p (decl))
     {
@@ -1382,6 +1435,10 @@ make_decl_rtl (tree decl)
 
   /* Specifying a section attribute on a variable forces it into a
      non-.bss section, and thus it cannot be common.  */
 
   /* Specifying a section attribute on a variable forces it into a
      non-.bss section, and thus it cannot be common.  */
+  /* FIXME: In general this code should not be necessary because
+     visibility pass is doing the same work.  But notice_global_symbol
+     is called early and it needs to make DECL_RTL to get the name.
+     we take care of recomputing the DECL_RTL after visibility is changed.  */
   if (TREE_CODE (decl) == VAR_DECL
       && DECL_SECTION_NAME (decl) != NULL_TREE
       && DECL_INITIAL (decl) == NULL_TREE
   if (TREE_CODE (decl) == VAR_DECL
       && DECL_SECTION_NAME (decl) != NULL_TREE
       && DECL_INITIAL (decl) == NULL_TREE
@@ -1395,7 +1452,15 @@ make_decl_rtl (tree decl)
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
   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);
 
   SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
   SET_SYMBOL_REF_DECL (x, decl);
 
@@ -1414,6 +1479,42 @@ make_decl_rtl (tree decl)
   if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
     mudflap_enqueue_decl (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.  */
 \f
 /* Output a string of literal assembler code
    for an `asm' keyword used between functions.  */
@@ -1449,7 +1550,7 @@ default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
 }
 
 /* Write the address of the entity given by SYMBOL to SEC.  */
 }
 
 /* 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);
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
@@ -1480,7 +1581,7 @@ default_named_section_asm_out_destructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_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);
                                      /*constructor_p=*/false);
   else
     sec = get_section (".dtors", SECTION_WRITE, NULL);
@@ -1520,7 +1621,7 @@ default_named_section_asm_out_constructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_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);
                                      /*constructor_p=*/true);
   else
     sec = get_section (".ctors", SECTION_WRITE, NULL);
@@ -1598,27 +1699,27 @@ assemble_start_function (tree decl, const char *fnname)
   char tmp_label[100];
   bool hot_label_written = false;
 
   char tmp_label[100];
   bool hot_label_written = false;
 
-  cfun->unlikely_text_section_name = NULL;
+  crtl->subsections.unlikely_text_section_name = NULL;
 
   first_function_block_is_cold = false;
   if (flag_reorder_blocks_and_partition)
     {
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno);
 
   first_function_block_is_cold = false;
   if (flag_reorder_blocks_and_partition)
     {
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno);
-      cfun->hot_section_label = ggc_strdup (tmp_label);
+      crtl->subsections.hot_section_label = ggc_strdup (tmp_label);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDB", const_labelno);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDB", const_labelno);
-      cfun->cold_section_label = ggc_strdup (tmp_label);
+      crtl->subsections.cold_section_label = ggc_strdup (tmp_label);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTE", const_labelno);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTE", const_labelno);
-      cfun->hot_section_end_label = ggc_strdup (tmp_label);
+      crtl->subsections.hot_section_end_label = ggc_strdup (tmp_label);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDE", const_labelno);
       ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDE", const_labelno);
-      cfun->cold_section_end_label = ggc_strdup (tmp_label);
+      crtl->subsections.cold_section_end_label = ggc_strdup (tmp_label);
       const_labelno++;
     }
   else
     {
       const_labelno++;
     }
   else
     {
-      cfun->hot_section_label = NULL;
-      cfun->cold_section_label = NULL;
-      cfun->hot_section_end_label = NULL;
-      cfun->cold_section_end_label = NULL;
+      crtl->subsections.hot_section_label = NULL;
+      crtl->subsections.cold_section_label = NULL;
+      crtl->subsections.hot_section_end_label = NULL;
+      crtl->subsections.cold_section_end_label = NULL;
     }
 
   /* The following code does not need preprocessing in the assembler.  */
     }
 
   /* The following code does not need preprocessing in the assembler.  */
@@ -1638,18 +1739,18 @@ assemble_start_function (tree decl, const char *fnname)
   if (flag_reorder_blocks_and_partition)
     {
       switch_to_section (unlikely_text_section ());
   if (flag_reorder_blocks_and_partition)
     {
       switch_to_section (unlikely_text_section ());
-      assemble_align (FUNCTION_BOUNDARY);
-      ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_label);
+      assemble_align (DECL_ALIGN (decl));
+      ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_label);
 
       /* When the function starts with a cold section, we need to explicitly
         align the hot section and write out the hot section label.
         But if the current function is a thunk, we do not have a CFG.  */
 
       /* When the function starts with a cold section, we need to explicitly
         align the hot section and write out the hot section label.
         But if the current function is a thunk, we do not have a CFG.  */
-      if (!current_function_is_thunk
+      if (!cfun->is_thunk
          && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
        {
          switch_to_section (text_section);
          && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
        {
          switch_to_section (text_section);
-         assemble_align (FUNCTION_BOUNDARY);
-         ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
+         assemble_align (DECL_ALIGN (decl));
+         ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label);
          hot_label_written = true;
          first_function_block_is_cold = true;
        }
          hot_label_written = true;
          first_function_block_is_cold = true;
        }
@@ -1663,9 +1764,9 @@ assemble_start_function (tree decl, const char *fnname)
 
       initialize_cold_section_name ();
 
 
       initialize_cold_section_name ();
 
-      if (cfun->unlikely_text_section_name
+      if (crtl->subsections.unlikely_text_section_name
          && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
          && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
-                    cfun->unlikely_text_section_name) == 0)
+                    crtl->subsections.unlikely_text_section_name) == 0)
        first_function_block_is_cold = true;
     }
 
        first_function_block_is_cold = true;
     }
 
@@ -1676,22 +1777,21 @@ assemble_start_function (tree decl, const char *fnname)
   switch_to_section (function_section (decl));
   if (flag_reorder_blocks_and_partition
       && !hot_label_written)
   switch_to_section (function_section (decl));
   if (flag_reorder_blocks_and_partition
       && !hot_label_written)
-    ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
+    ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label);
 
   /* Tell assembler to move to target machine's alignment for functions.  */
 
   /* Tell assembler to move to target machine's alignment for functions.  */
-  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
-  if (align < force_align_functions_log)
-    align = force_align_functions_log;
+  align = floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT);
   if (align > 0)
     {
       ASM_OUTPUT_ALIGN (asm_out_file, align);
     }
 
   /* Handle a user-specified function alignment.
   if (align > 0)
     {
       ASM_OUTPUT_ALIGN (asm_out_file, align);
     }
 
   /* Handle a user-specified function alignment.
-     Note that we still need to align to FUNCTION_BOUNDARY, as above,
+     Note that we still need to align to DECL_ALIGN, as above,
      because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all.  */
      because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all.  */
-  if (align_functions_log > align
-      && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+  if (! DECL_USER_ALIGN (decl)
+      && align_functions_log > align
+      && optimize_function_for_speed_p (cfun))
     {
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
       ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
     {
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
       ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
@@ -1705,7 +1805,8 @@ assemble_start_function (tree decl, const char *fnname)
   ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
 #endif
 
   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.  */
 
 
   /* Make function name accessible from other files, if appropriate.  */
 
@@ -1755,12 +1856,12 @@ assemble_end_function (tree decl, const char *fnname ATTRIBUTE_UNUSED)
 
       save_text_section = in_section;
       switch_to_section (unlikely_text_section ());
 
       save_text_section = in_section;
       switch_to_section (unlikely_text_section ());
-      ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_end_label);
+      ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_end_label);
       if (first_function_block_is_cold)
        switch_to_section (text_section);
       else
        switch_to_section (function_section (decl));
       if (first_function_block_is_cold)
        switch_to_section (text_section);
       else
        switch_to_section (function_section (decl));
-      ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_end_label);
+      ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_end_label);
       switch_to_section (save_text_section);
     }
 }
       switch_to_section (save_text_section);
     }
 }
@@ -1962,6 +2063,40 @@ assemble_variable_contents (tree decl, const char *name,
     }
 }
 
     }
 }
 
+/* Initialize emulated tls object TO, which refers to TLS variable
+   DECL and is initialized by PROXY.  */
+
+tree
+default_emutls_var_init (tree to, tree decl, tree proxy)
+{
+  VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4);
+  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);
+}
+
 /* Assemble everything that is needed for a variable or function declaration.
    Not used for automatic variables, and not used for function definitions.
    Should not be called for variables of incomplete structure type.
 /* Assemble everything that is needed for a variable or function declaration.
    Not used for automatic variables, and not used for function definitions.
    Should not be called for variables of incomplete structure type.
@@ -1996,38 +2131,14 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
              || (DECL_INITIAL (decl)
                  && DECL_INITIAL (decl) != error_mark_node)))
        {
              || (DECL_INITIAL (decl)
                  && DECL_INITIAL (decl) != error_mark_node)))
        {
-         VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4);
-         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 = get_emutls_init_templ_addr (decl);
-
-         DECL_INITIAL (to) = build_constructor (type, v);
+         DECL_INITIAL (to) = targetm.emutls.var_init
+           (to, decl, get_emutls_init_templ_addr (decl));
 
          /* Make sure the template is marked as needed early enough.
             Without this, if the variable is placed in a
             section-anchored block, the template will only be marked
             when it's too late.  */
 
          /* Make sure the template is marked as needed early enough.
             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;
        }
 
       decl = to;
@@ -2119,7 +2230,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   /* First make the assembler name(s) global if appropriate.  */
   sect = get_variable_section (decl, false);
   if (TREE_PUBLIC (decl)
   /* First make the assembler name(s) global if appropriate.  */
   sect = get_variable_section (decl, false);
   if (TREE_PUBLIC (decl)
-      && DECL_NAME (decl)
       && (sect->common.flags & SECTION_COMMON) == 0)
     globalize_decl (decl);
 
       && (sect->common.flags & SECTION_COMMON) == 0)
     globalize_decl (decl);
 
@@ -2186,7 +2296,7 @@ contains_pointers_p (tree type)
     }
 }
 
     }
 }
 
-/* In unit-at-a-time mode, we delay assemble_external processing until
+/* We delay assemble_external processing until
    the compilation unit is finalized.  This is the best we can do for
    right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay
    it all the way to final.  See PR 17982 for further discussion.  */
    the compilation unit is finalized.  This is the best we can do for
    right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay
    it all the way to final.  See PR 17982 for further discussion.  */
@@ -2208,7 +2318,7 @@ incorporeal_function_p (tree decl)
        return true;
 
       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
        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;
        return true;
     }
   return false;
@@ -2244,9 +2354,14 @@ process_pending_assemble_externals (void)
 #endif
 }
 
 #endif
 }
 
-/* Output something to declare an external symbol to the assembler.
-   (Most assemblers don't need this, so we normally output nothing.)
-   Do nothing if DECL is not external.  */
+/* This TREE_LIST contains any weak symbol declarations waiting
+   to be emitted.  */
+static GTY(()) tree weak_decls;
+
+/* Output something to declare an external symbol to the assembler,
+   and qualifiers such as weakness.  (Most assemblers don't need
+   extern declaration, so we normally output nothing.)  Do nothing if
+   DECL is not external.  */
 
 void
 assemble_external (tree decl ATTRIBUTE_UNUSED)
 
 void
 assemble_external (tree decl ATTRIBUTE_UNUSED)
@@ -2257,14 +2372,28 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
      open.  If it's not, we should not be calling this function.  */
   gcc_assert (asm_out_file);
 
      open.  If it's not, we should not be calling this function.  */
   gcc_assert (asm_out_file);
 
-#ifdef ASM_OUTPUT_EXTERNAL
   if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
     return;
 
   if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
     return;
 
-  /* We want to output external symbols at very last to check if they
-     are references or not.  */
-  pending_assemble_externals = tree_cons (0, decl,
-                                         pending_assemble_externals);
+  /* 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)
+      /* 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
+  if (value_member (decl, pending_assemble_externals) == NULL_TREE)
+    pending_assemble_externals = tree_cons (NULL, decl,
+                                           pending_assemble_externals);
 #endif
 }
 
 #endif
 }
 
@@ -2436,7 +2565,6 @@ assemble_static_space (unsigned HOST_WIDE_INT size)
 
 static GTY(()) rtx initial_trampoline;
 
 
 static GTY(()) rtx initial_trampoline;
 
-#ifdef TRAMPOLINE_TEMPLATE
 rtx
 assemble_trampoline_template (void)
 {
 rtx
 assemble_trampoline_template (void)
 {
@@ -2445,6 +2573,8 @@ assemble_trampoline_template (void)
   int align;
   rtx symbol;
 
   int align;
   rtx symbol;
 
+  gcc_assert (targetm.asm_out.trampoline_template != NULL);
+
   if (initial_trampoline)
     return initial_trampoline;
 
   if (initial_trampoline)
     return initial_trampoline;
 
@@ -2459,12 +2589,10 @@ assemble_trampoline_template (void)
   /* Write the assembler code to define one.  */
   align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
   if (align > 0)
   /* 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);
 
   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);
 
   /* Record the rtl to refer to it.  */
   ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
@@ -2472,12 +2600,12 @@ assemble_trampoline_template (void)
   symbol = gen_rtx_SYMBOL_REF (Pmode, name);
   SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
 
   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_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
+  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
 
   return initial_trampoline;
 }
 
   return initial_trampoline;
 }
-#endif
 \f
 /* A and B are either alignments or offsets.  Return the minimum alignment
    that may be assumed after adding the two together.  */
 \f
 /* A and B are either alignments or offsets.  Return the minimum alignment
    that may be assumed after adding the two together.  */
@@ -2572,11 +2700,17 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
       enum machine_mode omode, imode;
       unsigned int subalign;
       unsigned int subsize, i;
       enum machine_mode omode, imode;
       unsigned int subalign;
       unsigned int subsize, i;
+      enum mode_class mclass;
 
       subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
       subalign = MIN (align, subsize * BITS_PER_UNIT);
 
       subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
       subalign = MIN (align, subsize * BITS_PER_UNIT);
-      omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0);
-      imode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+      if (GET_CODE (x) == CONST_FIXED)
+       mclass = GET_MODE_CLASS (GET_MODE (x));
+      else
+       mclass = MODE_INT;
+
+      omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0);
+      imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0);
 
       for (i = 0; i < size; i += subsize)
        {
 
       for (i = 0; i < size; i += subsize)
        {
@@ -2642,8 +2776,7 @@ assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
    Store them both in the structure *VALUE.
    EXP must be reducible.  */
 
    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;
 };
   rtx base;
   HOST_WIDE_INT offset;
 };
@@ -2688,6 +2821,7 @@ decode_addr_const (tree exp, struct addr_const *value)
       break;
 
     case REAL_CST:
       break;
 
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
     case COMPLEX_CST:
     case CONSTRUCTOR:
     case STRING_CST:
     case COMPLEX_CST:
     case CONSTRUCTOR:
@@ -2706,23 +2840,6 @@ decode_addr_const (tree exp, struct addr_const *value)
   value->offset = offset;
 }
 \f
   value->offset = offset;
 }
 \f
-/* 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;
 
 static GTY((param_is (struct constant_descriptor_tree)))
      htab_t const_desc_htab;
@@ -2730,12 +2847,20 @@ static GTY((param_is (struct constant_descriptor_tree)))
 static struct constant_descriptor_tree * build_constant_desc (tree);
 static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
 
 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
 const_desc_hash (const void *ptr)
 {
 /* Compute a hash code for a constant expression.  */
 
 static hashval_t
 const_desc_hash (const void *ptr)
 {
-  return ((struct constant_descriptor_tree *)ptr)->hash;
+  return ((const struct constant_descriptor_tree *)ptr)->hash;
 }
 
 static hashval_t
 }
 
 static hashval_t
@@ -2759,6 +2884,9 @@ const_hash_1 (const tree exp)
     case REAL_CST:
       return real_hash (TREE_REAL_CST_PTR (exp));
 
     case REAL_CST:
       return real_hash (TREE_REAL_CST_PTR (exp));
 
+    case FIXED_CST:
+      return fixed_hash (TREE_FIXED_CST_PTR (exp));
+
     case STRING_CST:
       p = TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
     case STRING_CST:
       p = TREE_STRING_POINTER (exp);
       len = TREE_STRING_LENGTH (exp);
@@ -2815,9 +2943,7 @@ const_hash_1 (const tree exp)
       return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
              + const_hash_1 (TREE_OPERAND (exp, 1)));
 
       return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
              + const_hash_1 (TREE_OPERAND (exp, 1)));
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
+    CASE_CONVERT:
       return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
 
     default:
       return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
 
     default:
@@ -2837,8 +2963,10 @@ const_hash_1 (const tree exp)
 static int
 const_desc_eq (const void *p1, const void *p2)
 {
 static int
 const_desc_eq (const void *p1, const void *p2)
 {
-  const struct constant_descriptor_tree *c1 = p1;
-  const struct constant_descriptor_tree *c2 = p2;
+  const struct constant_descriptor_tree *const c1
+    = (const struct constant_descriptor_tree *) p1;
+  const struct constant_descriptor_tree *const c2
+    = (const struct constant_descriptor_tree *) p2;
   if (c1->hash != c2->hash)
     return 0;
   return compare_constant (c1->value, c2->value);
   if (c1->hash != c2->hash)
     return 0;
   return compare_constant (c1->value, c2->value);
@@ -2877,6 +3005,13 @@ compare_constant (const tree t1, const tree t2)
 
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
 
       return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
 
+    case FIXED_CST:
+      /* Fixed constants are the same only if the same width of type.  */
+      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
+       return 0;
+
+      return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
+
     case STRING_CST:
       if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
        return 0;
     case STRING_CST:
       if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
        return 0;
@@ -2963,22 +3098,12 @@ compare_constant (const tree t1, const tree t2)
       return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
              && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
 
       return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
              && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
+    CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
       return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     default:
     case VIEW_CONVERT_EXPR:
       return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
 
     default:
-      {
-       tree nt1, nt2;
-       nt1 = lang_hooks.expand_constant (t1);
-       nt2 = lang_hooks.expand_constant (t2);
-       if (nt1 != t1 || nt2 != t2)
-         return compare_constant (nt1, nt2);
-       else
-         return 0;
-      }
+      return 0;
     }
 
   gcc_unreachable ();
     }
 
   gcc_unreachable ();
@@ -3003,6 +3128,7 @@ copy_constant (tree exp)
 
     case INTEGER_CST:
     case REAL_CST:
 
     case INTEGER_CST:
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
       return copy_node (exp);
 
     case STRING_CST:
       return copy_node (exp);
 
@@ -3018,9 +3144,7 @@ copy_constant (tree exp)
                     copy_constant (TREE_OPERAND (exp, 0)),
                     copy_constant (TREE_OPERAND (exp, 1)));
 
                     copy_constant (TREE_OPERAND (exp, 0)),
                     copy_constant (TREE_OPERAND (exp, 1)));
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
+    CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
       return build1 (TREE_CODE (exp), TREE_TYPE (exp),
                     copy_constant (TREE_OPERAND (exp, 0)));
     case VIEW_CONVERT_EXPR:
       return build1 (TREE_CODE (exp), TREE_TYPE (exp),
                     copy_constant (TREE_OPERAND (exp, 0)));
@@ -3045,12 +3169,7 @@ copy_constant (tree exp)
       }
 
     default:
       }
 
     default:
-      {
-       tree t = lang_hooks.expand_constant (exp);
-
-       gcc_assert (t != exp);
-       return copy_constant (t);
-      }
+      gcc_unreachable ();
     }
 }
 \f
     }
 }
 \f
@@ -3110,7 +3229,7 @@ build_constant_desc (tree exp)
   int labelno;
   struct constant_descriptor_tree *desc;
 
   int labelno;
   struct constant_descriptor_tree *desc;
 
-  desc = ggc_alloc (sizeof (*desc));
+  desc = GGC_NEW (struct constant_descriptor_tree);
   desc->value = copy_constant (exp);
 
   /* Propagate marked-ness to copied constant.  */
   desc->value = copy_constant (exp);
 
   /* Propagate marked-ness to copied constant.  */
@@ -3139,6 +3258,10 @@ build_constant_desc (tree exp)
   set_mem_alias_set (rtl, 0);
   set_mem_alias_set (rtl, const_alias_set);
 
   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
   /* 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
@@ -3178,7 +3301,7 @@ output_constant_def (tree exp, int defer)
   key.hash = const_hash_1 (exp);
   loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
 
   key.hash = const_hash_1 (exp);
   loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
 
-  desc = *loc;
+  desc = (struct constant_descriptor_tree *) *loc;
   if (desc == 0)
     {
       desc = build_constant_desc (exp);
   if (desc == 0)
     {
       desc = build_constant_desc (exp);
@@ -3289,7 +3412,8 @@ lookup_constant_def (tree exp)
 
   key.value = exp;
   key.hash = const_hash_1 (exp);
 
   key.value = exp;
   key.hash = const_hash_1 (exp);
-  desc = htab_find_with_hash (const_desc_htab, &key, key.hash);
+  desc = (struct constant_descriptor_tree *)
+    htab_find_with_hash (const_desc_htab, &key, key.hash);
 
   return (desc ? desc->rtl : NULL_RTX);
 }
 
   return (desc ? desc->rtl : NULL_RTX);
 }
@@ -3301,8 +3425,7 @@ lookup_constant_def (tree exp)
    can use one per-file pool.  Should add a targetm bit to tell the
    difference.  */
 
    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;
   /* Pointers to first and last constant in pool, as ordered by offset.  */
   struct constant_descriptor_rtx *first;
   struct constant_descriptor_rtx *last;
@@ -3318,8 +3441,7 @@ struct rtx_constant_pool GTY(())
   HOST_WIDE_INT offset;
 };
 
   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;
   struct constant_descriptor_rtx *next;
   rtx mem;
   rtx sym;
@@ -3337,15 +3459,18 @@ struct constant_descriptor_rtx GTY((chain_next ("%h.next")))
 static hashval_t
 const_desc_rtx_hash (const void *ptr)
 {
 static hashval_t
 const_desc_rtx_hash (const void *ptr)
 {
-  const struct constant_descriptor_rtx *desc = ptr;
+  const struct constant_descriptor_rtx *const desc
+    = (const struct constant_descriptor_rtx *) ptr;
   return desc->hash;
 }
 
 static int
 const_desc_rtx_eq (const void *a, const void *b)
 {
   return desc->hash;
 }
 
 static int
 const_desc_rtx_eq (const void *a, const void *b)
 {
-  const struct constant_descriptor_rtx *x = a;
-  const struct constant_descriptor_rtx *y = b;
+  const struct constant_descriptor_rtx *const x
+    = (const struct constant_descriptor_rtx *) a;
+  const struct constant_descriptor_rtx *const y
+    = (const struct constant_descriptor_rtx *) b;
 
   if (x->mode != y->mode)
     return 0;
 
   if (x->mode != y->mode)
     return 0;
@@ -3374,7 +3499,7 @@ const_rtx_hash_1 (rtx *xp, void *data)
       hwi = INTVAL (x);
     fold_hwi:
       {
       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;
 
        const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
        int i;
 
@@ -3397,6 +3522,10 @@ const_rtx_hash_1 (rtx *xp, void *data)
        h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
       break;
 
        h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
       break;
 
+    case CONST_FIXED:
+      h ^= fixed_hash (CONST_FIXED_VALUE (x));
+      break;
+
     case CONST_VECTOR:
       {
        int i;
     case CONST_VECTOR:
       {
        int i;
@@ -3422,7 +3551,7 @@ const_rtx_hash_1 (rtx *xp, void *data)
       break;
     }
 
       break;
     }
 
-  hp = data;
+  hp = (hashval_t *) data;
   *hp = *hp * 509 + h;
   return 0;
 }
   *hp = *hp * 509 + h;
   return 0;
 }
@@ -3445,7 +3574,7 @@ create_constant_pool (void)
 {
   struct rtx_constant_pool *pool;
 
 {
   struct rtx_constant_pool *pool;
 
-  pool = ggc_alloc (sizeof (struct rtx_constant_pool));
+  pool = GGC_NEW (struct rtx_constant_pool);
   pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
                                          const_desc_rtx_eq, NULL);
   pool->first = NULL;
   pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
                                          const_desc_rtx_eq, NULL);
   pool->first = NULL;
@@ -3457,15 +3586,10 @@ create_constant_pool (void)
 /* Initialize constant pool hashing for a new function.  */
 
 void
 /* Initialize constant pool hashing for a new function.  */
 
 void
-init_varasm_status (struct function *f)
+init_varasm_status (void)
 {
 {
-  struct varasm_status *p;
-
-  p = ggc_alloc (sizeof (struct varasm_status));
-  f->varasm = p;
-
-  p->pool = create_constant_pool ();
-  p->deferred_constants = 0;
+  crtl->varasm.pool = create_constant_pool ();
+  crtl->varasm.deferred_constants = 0;
 }
 \f
 /* Given a MINUS expression, simplify it if both sides
 }
 \f
 /* Given a MINUS expression, simplify it if both sides
@@ -3497,26 +3621,26 @@ force_const_mem (enum machine_mode mode, rtx x)
     return NULL_RTX;
 
   /* Record that this function has used a constant pool entry.  */
     return NULL_RTX;
 
   /* Record that this function has used a constant pool entry.  */
-  current_function_uses_const_pool = 1;
+  crtl->uses_const_pool = 1;
 
   /* Decide which pool to use.  */
   pool = (targetm.use_blocks_for_constant_p (mode, x)
          ? shared_constant_pool
 
   /* Decide which pool to use.  */
   pool = (targetm.use_blocks_for_constant_p (mode, x)
          ? shared_constant_pool
-         : cfun->varasm->pool);
+         : crtl->varasm.pool);
 
   /* Lookup the value in the hashtable.  */
   tmp.constant = x;
   tmp.mode = mode;
   hash = const_rtx_hash (x);
   slot = htab_find_slot_with_hash (pool->const_rtx_htab, &tmp, hash, INSERT);
 
   /* Lookup the value in the hashtable.  */
   tmp.constant = x;
   tmp.mode = mode;
   hash = const_rtx_hash (x);
   slot = htab_find_slot_with_hash (pool->const_rtx_htab, &tmp, hash, INSERT);
-  desc = *slot;
+  desc = (struct constant_descriptor_rtx *) *slot;
 
   /* If the constant was already present, return its memory.  */
   if (desc)
     return copy_rtx (desc->mem);
 
   /* Otherwise, create a new descriptor.  */
 
   /* If the constant was already present, return its memory.  */
   if (desc)
     return copy_rtx (desc->mem);
 
   /* Otherwise, create a new descriptor.  */
-  desc = ggc_alloc (sizeof (*desc));
+  desc = GGC_NEW (struct constant_descriptor_rtx);
   *slot = desc;
 
   /* Align the location counter as required by EXP's data type.  */
   *slot = desc;
 
   /* Align the location counter as required by EXP's data type.  */
@@ -3604,7 +3728,7 @@ get_pool_constant_mark (rtx addr, bool *pmarked)
 /* Similar, return the mode.  */
 
 enum machine_mode
 /* Similar, return the mode.  */
 
 enum machine_mode
-get_pool_mode (rtx addr)
+get_pool_mode (const_rtx addr)
 {
   return SYMBOL_REF_CONSTANT (addr)->mode;
 }
 {
   return SYMBOL_REF_CONSTANT (addr)->mode;
 }
@@ -3614,7 +3738,7 @@ get_pool_mode (rtx addr)
 int
 get_pool_size (void)
 {
 int
 get_pool_size (void)
 {
-  return cfun->varasm->pool->offset;
+  return crtl->varasm.pool->offset;
 }
 \f
 /* Worker function for output_constant_pool_1.  Emit assembly for X
 }
 \f
 /* Worker function for output_constant_pool_1.  Emit assembly for X
@@ -3638,11 +3762,19 @@ output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
 
     case MODE_INT:
     case MODE_PARTIAL_INT:
 
     case MODE_INT:
     case MODE_PARTIAL_INT:
+    case MODE_FRACT:
+    case MODE_UFRACT:
+    case MODE_ACCUM:
+    case MODE_UACCUM:
       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
       break;
 
     case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_INT:
       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
       break;
 
     case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_INT:
+    case MODE_VECTOR_FRACT:
+    case MODE_VECTOR_UFRACT:
+    case MODE_VECTOR_ACCUM:
+    case MODE_VECTOR_UACCUM:
       {
        int i, units;
         enum machine_mode submode = GET_MODE_INNER (mode);
       {
        int i, units;
         enum machine_mode submode = GET_MODE_INNER (mode);
@@ -3685,17 +3817,17 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc,
      functioning even with INSN_DELETED_P and friends.  */
 
   tmp = x;
      functioning even with INSN_DELETED_P and friends.  */
 
   tmp = x;
-  switch (GET_CODE (x))
+  switch (GET_CODE (tmp))
     {
     case CONST:
     {
     case CONST:
-      if (GET_CODE (XEXP (x, 0)) != PLUS
-         || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
+      if (GET_CODE (XEXP (tmp, 0)) != PLUS
+         || GET_CODE (XEXP (XEXP (tmp, 0), 0)) != LABEL_REF)
        break;
        break;
-      tmp = XEXP (XEXP (x, 0), 0);
+      tmp = XEXP (XEXP (tmp, 0), 0);
       /* FALLTHRU  */
 
     case LABEL_REF:
       /* FALLTHRU  */
 
     case LABEL_REF:
-      tmp = XEXP (x, 0);
+      tmp = XEXP (tmp, 0);
       gcc_assert (!INSN_DELETED_P (tmp));
       gcc_assert (!NOTE_P (tmp)
                  || NOTE_KIND (tmp) != NOTE_INSN_DELETED);
       gcc_assert (!INSN_DELETED_P (tmp));
       gcc_assert (!NOTE_P (tmp)
                  || NOTE_KIND (tmp) != NOTE_INSN_DELETED);
@@ -3803,13 +3935,13 @@ mark_constant_pool (void)
 {
   rtx insn, link;
 
 {
   rtx insn, link;
 
-  if (!current_function_uses_const_pool && n_deferred_constants == 0)
+  if (!crtl->uses_const_pool && n_deferred_constants == 0)
     return;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     mark_constants (insn);
 
     return;
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     mark_constants (insn);
 
-  for (link = current_function_epilogue_delay_list;
+  for (link = crtl->epilogue_delay_list;
        link;
        link = XEXP (link, 1))
     mark_constants (XEXP (link, 0));
        link;
        link = XEXP (link, 1))
     mark_constants (XEXP (link, 0));
@@ -3848,7 +3980,7 @@ static void
 output_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
                      tree fndecl ATTRIBUTE_UNUSED)
 {
 output_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
                      tree fndecl ATTRIBUTE_UNUSED)
 {
-  struct rtx_constant_pool *pool = cfun->varasm->pool;
+  struct rtx_constant_pool *pool = crtl->varasm.pool;
 
   /* It is possible for gcc to call force_const_mem and then to later
      discard the instructions which refer to the constant.  In such a
 
   /* It is possible for gcc to call force_const_mem and then to later
      discard the instructions which refer to the constant.  In such a
@@ -3882,10 +4014,6 @@ compute_reloc_for_constant (tree exp)
   int reloc = 0, reloc2;
   tree tem;
 
   int reloc = 0, reloc2;
   tree tem;
 
-  /* Give the front-end a chance to convert VALUE to something that
-     looks more like a constant to the back-end.  */
-  exp = lang_hooks.expand_constant (exp);
-
   switch (TREE_CODE (exp))
     {
     case ADDR_EXPR:
   switch (TREE_CODE (exp))
     {
     case ADDR_EXPR:
@@ -3919,9 +4047,7 @@ compute_reloc_for_constant (tree exp)
        reloc |= reloc2;
       break;
 
        reloc |= reloc2;
       break;
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
+    CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
       reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
       break;
     case VIEW_CONVERT_EXPR:
       reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
       break;
@@ -3950,10 +4076,6 @@ output_addressed_constants (tree exp)
 {
   tree tem;
 
 {
   tree tem;
 
-  /* Give the front-end a chance to convert VALUE to something that
-     looks more like a constant to the back-end.  */
-  exp = lang_hooks.expand_constant (exp);
-
   switch (TREE_CODE (exp))
     {
     case ADDR_EXPR:
   switch (TREE_CODE (exp))
     {
     case ADDR_EXPR:
@@ -3979,9 +4101,7 @@ output_addressed_constants (tree exp)
       output_addressed_constants (TREE_OPERAND (exp, 1));
       /* Fall through.  */
 
       output_addressed_constants (TREE_OPERAND (exp, 1));
       /* Fall through.  */
 
-    case NOP_EXPR:
-    case CONVERT_EXPR:
-    case NON_LVALUE_EXPR:
+    CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
       output_addressed_constants (TREE_OPERAND (exp, 0));
       break;
     case VIEW_CONVERT_EXPR:
       output_addressed_constants (TREE_OPERAND (exp, 0));
       break;
@@ -4006,7 +4126,7 @@ output_addressed_constants (tree exp)
    evaluate the property while walking a constructor for other purposes.  */
 
 bool
    evaluate the property while walking a constructor for other purposes.  */
 
 bool
-constructor_static_from_elts_p (tree ctor)
+constructor_static_from_elts_p (const_tree ctor)
 {
   return (TREE_CONSTANT (ctor)
          && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
 {
   return (TREE_CONSTANT (ctor)
          && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
@@ -4014,7 +4134,87 @@ constructor_static_from_elts_p (tree ctor)
          && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
 }
 
          && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
 }
 
-/* Return nonzero if VALUE is a valid constant-valued expression
+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
+   particular, this does not accept a pointer minus a constant.  This
+   returns null_pointer_node if the VALUE is an absolute constant
+   which can be used to initialize a static variable.  Otherwise it
+   returns NULL.  */
+
+static tree
+narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
+{
+  tree op0, op1;
+
+  if (!INTEGRAL_TYPE_P (endtype))
+    return NULL_TREE;
+
+  op0 = TREE_OPERAND (value, 0);
+  op1 = TREE_OPERAND (value, 1);
+
+  /* Like STRIP_NOPS except allow the operand mode to widen.  This
+     works around a feature of fold that simplifies (int)(p1 - p2) to
+     ((int)p1 - (int)p2) under the theory that the narrower operation
+     is cheaper.  */
+
+  while (CONVERT_EXPR_P (op0)
+        || TREE_CODE (op0) == NON_LVALUE_EXPR)
+    {
+      tree inner = TREE_OPERAND (op0, 0);
+      if (inner == error_mark_node
+         || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+         || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
+             > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+       break;
+      op0 = inner;
+    }
+
+  while (CONVERT_EXPR_P (op1)
+        || TREE_CODE (op1) == NON_LVALUE_EXPR)
+    {
+      tree inner = TREE_OPERAND (op1, 0);
+      if (inner == error_mark_node
+         || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+         || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
+             > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+       break;
+      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);
+  /* Both initializers must be known.  */
+  if (op1)
+    {
+      if (op0 == op1
+         && (op0 == null_pointer_node
+             || TREE_CODE (value) == MINUS_EXPR))
+       return null_pointer_node;
+
+      /* Support differences between labels.  */
+      if (TREE_CODE (op0) == LABEL_DECL
+         && TREE_CODE (op1) == LABEL_DECL)
+       return null_pointer_node;
+
+      if (TREE_CODE (op0) == STRING_CST
+         && TREE_CODE (op1) == STRING_CST
+         && operand_equal_p (op0, op1, 1))
+       return null_pointer_node;
+    }
+
+  return NULL_TREE;
+}
+
+/* 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.
 
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
 
@@ -4022,14 +4222,14 @@ constructor_static_from_elts_p (tree ctor)
    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
    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)
 {
 {
-  /* Give the front-end a chance to convert VALUE to something that
-     looks more like a constant to the back-end.  */
-  value = lang_hooks.expand_constant (value);
+  tree ret;
 
   switch (TREE_CODE (value))
     {
 
   switch (TREE_CODE (value))
     {
@@ -4040,18 +4240,33 @@ initializer_constant_valid_p (tree value, tree endtype)
          tree elt;
          bool absolute = true;
 
          tree elt;
          bool absolute = true;
 
+         if (cache && cache[0] == value)
+           return cache[1];
          FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
            {
              tree reloc;
          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)
              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 (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;
        }
 
          return absolute ? null_pointer_node : error_mark_node;
        }
 
@@ -4060,46 +4275,67 @@ initializer_constant_valid_p (tree value, tree endtype)
     case INTEGER_CST:
     case VECTOR_CST:
     case REAL_CST:
     case INTEGER_CST:
     case VECTOR_CST:
     case REAL_CST:
+    case FIXED_CST:
     case STRING_CST:
     case COMPLEX_CST:
       return null_pointer_node;
 
     case ADDR_EXPR:
     case FDESC_EXPR:
     case STRING_CST:
     case COMPLEX_CST:
       return null_pointer_node;
 
     case ADDR_EXPR:
     case FDESC_EXPR:
-      value = staticp (TREE_OPERAND (value, 0));
-      if (value)
-       {
-         /* "&(*a).f" is like unto pointer arithmetic.  If "a" turns out to
-            be a constant, this is old-skool offsetof-like nonsense.  */
-         if (TREE_CODE (value) == INDIRECT_REF
-             && TREE_CONSTANT (TREE_OPERAND (value, 0)))
-           return null_pointer_node;
-         /* Taking the address of a nested function involves a trampoline.  */
-         if (TREE_CODE (value) == FUNCTION_DECL
-             && decl_function_context (value)
-             && !DECL_NO_STATIC_CHAIN (value))
-           return NULL_TREE;
-         /* "&{...}" requires a temporary to hold the constructed
-            object.  */
-         if (TREE_CODE (value) == CONSTRUCTOR)
-           return NULL_TREE;
-       }
-      return value;
+      {
+       tree op0 = staticp (TREE_OPERAND (value, 0));
+       if (op0)
+         {
+           /* "&(*a).f" is like unto pointer arithmetic.  If "a" turns out
+              to be a constant, this is old-skool offsetof-like nonsense.  */
+           if (TREE_CODE (op0) == INDIRECT_REF
+               && TREE_CONSTANT (TREE_OPERAND (op0, 0)))
+             return null_pointer_node;
+           /* 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_STATIC_CHAIN (op0)
+               && !TREE_NO_TRAMPOLINE (value))
+             return NULL_TREE;
+           /* "&{...}" requires a temporary to hold the constructed
+              object.  */
+           if (TREE_CODE (op0) == CONSTRUCTOR)
+             return NULL_TREE;
+         }
+       return op0;
+      }
 
 
-    case VIEW_CONVERT_EXPR:
     case NON_LVALUE_EXPR:
     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 CONVERT_EXPR:
-    case NOP_EXPR:
+    case VIEW_CONVERT_EXPR:
       {
       {
-       tree src;
-       tree src_type;
-       tree dest_type;
+       tree src = TREE_OPERAND (value, 0);
+       tree src_type = TREE_TYPE (src);
+       tree dest_type = TREE_TYPE (value);
+
+       /* Allow view-conversions from aggregate to non-aggregate type only
+          if the bit pattern is fully preserved afterwards; otherwise, the
+          RTL expander won't be able to apply a subsequent transformation
+          to the underlying constructor.  */
+       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);
+           else
+             return NULL_TREE;
+         }
 
 
-       src = TREE_OPERAND (value, 0);
-       src_type = TREE_TYPE (src);
-       dest_type = TREE_TYPE (value);
+       /* Allow all other kinds of view-conversion.  */
+       return initializer_constant_valid_p_1 (src, endtype, cache);
+      }
+
+    CASE_CONVERT:
+      {
+       tree src = TREE_OPERAND (value, 0);
+       tree src_type = TREE_TYPE (src);
+       tree dest_type = TREE_TYPE (value);
 
        /* Allow conversions between pointer types, floating-point
           types, and offset types.  */
 
        /* Allow conversions between pointer types, floating-point
           types, and offset types.  */
@@ -4107,18 +4343,18 @@ initializer_constant_valid_p (tree value, tree endtype)
            || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
            || (TREE_CODE (dest_type) == OFFSET_TYPE
                && TREE_CODE (src_type) == OFFSET_TYPE))
            || (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)))
 
        /* 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))
          {
 
        /* 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;
            if (inner == null_pointer_node)
              return null_pointer_node;
            break;
@@ -4127,7 +4363,7 @@ initializer_constant_valid_p (tree value, tree endtype)
        /* Allow (int) &foo provided int is as wide as a pointer.  */
        if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
            && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
        /* 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.  */
 
        /* Likewise conversions from int to pointers, but also allow
           conversions from 0.  */
@@ -4141,127 +4377,170 @@ 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))
            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)
          }
 
        /* 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:
       }
       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)
       if (! INTEGRAL_TYPE_P (endtype)
-         || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+         || 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);
-         /* If either term is absolute, use the other terms relocation.  */
+         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)
          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);
        }
        }
-      break;
+      else
+      /* Support narrowing pointer differences.  */
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
+       {
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
     case MINUS_EXPR:
 
     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)
       if (! INTEGRAL_TYPE_P (endtype)
-         || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+         || 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)
          /* 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.  */
          /* 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.  */
          /* 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.  */
-      if (INTEGRAL_TYPE_P (endtype))
+      else
+       /* Support narrowing differences.  */
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
        {
        {
-         tree op0, op1;
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
 
-         op0 = TREE_OPERAND (value, 0);
-         op1 = TREE_OPERAND (value, 1);
+    default:
+      break;
+    }
 
 
-         /* Like STRIP_NOPS except allow the operand mode to widen.
-            This works around a feature of fold that simplifies
-            (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
-            that the narrower operation is cheaper.  */
+  return NULL_TREE;
+}
 
 
-         while (TREE_CODE (op0) == NOP_EXPR
-                || TREE_CODE (op0) == CONVERT_EXPR
-                || TREE_CODE (op0) == NON_LVALUE_EXPR)
-           {
-             tree inner = TREE_OPERAND (op0, 0);
-             if (inner == error_mark_node
-                 || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
-                 || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
-                     > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
-               break;
-             op0 = inner;
-           }
+/* 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.
 
 
-         while (TREE_CODE (op1) == NOP_EXPR
-                || TREE_CODE (op1) == CONVERT_EXPR
-                || TREE_CODE (op1) == NON_LVALUE_EXPR)
-           {
-             tree inner = TREE_OPERAND (op1, 0);
-             if (inner == error_mark_node
-                 || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
-                 || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
-                     > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
-               break;
-             op1 = inner;
-           }
+   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
+   for use in initializing a static bit-field; one that can be
+   an element of a "constant" initializer.  */
 
 
-         op0 = initializer_constant_valid_p (op0, endtype);
-         op1 = initializer_constant_valid_p (op1, endtype);
+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;
 
 
-         /* Both initializers must be known.  */
-         if (op0 && op1)
-           {
-             if (op0 == op1)
-               return null_pointer_node;
-
-             /* Support differences between labels.  */
-             if (TREE_CODE (op0) == LABEL_DECL
-                 && TREE_CODE (op1) == LABEL_DECL)
-               return null_pointer_node;
-
-             if (TREE_CODE (op0) == STRING_CST
-                 && TREE_CODE (op1) == STRING_CST
-                 && operand_equal_p (op0, op1, 1))
-               return null_pointer_node;
-           }
-       }
-      break;
+       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;
     }
 
 
     default:
       break;
     }
 
-  return 0;
+  return false;
 }
 }
-\f
+
+/* 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.
 /* 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.
@@ -4288,11 +4567,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
   enum tree_code code;
   unsigned HOST_WIDE_INT thissize;
 
   enum tree_code code;
   unsigned HOST_WIDE_INT thissize;
 
-  /* Some front-ends use constants other than the standard language-independent
-     varieties, but which may still be output directly.  Give the front-end a
-     chance to convert EXP to a language-independent representation.  */
-  exp = lang_hooks.expand_constant (exp);
-
   if (size == 0 || flag_syntax_only)
     return;
 
   if (size == 0 || flag_syntax_only)
     return;
 
@@ -4302,7 +4576,9 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
      resolving it.  */
   if (TREE_CODE (exp) == NOP_EXPR
       && POINTER_TYPE_P (TREE_TYPE (exp))
      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);
 
     {
       tree saved_type = TREE_TYPE (exp);
 
@@ -4310,7 +4586,9 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
         pointer modes.  */
       while (TREE_CODE (exp) == NOP_EXPR
             && POINTER_TYPE_P (TREE_TYPE (exp))
         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
        exp = TREE_OPERAND (exp, 0);
 
       /* If what we're left with is the address of something, we can
@@ -4322,12 +4600,12 @@ 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));
       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
      constant.  */
     }
 
   /* Eliminate any conversions since we'll be outputting the underlying
      constant.  */
-  while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
+  while (CONVERT_EXPR_P (exp)
         || TREE_CODE (exp) == NON_LVALUE_EXPR
         || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     {
         || TREE_CODE (exp) == NON_LVALUE_EXPR
         || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
     {
@@ -4349,9 +4627,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
   code = TREE_CODE (TREE_TYPE (exp));
   thissize = int_size_in_bytes (TREE_TYPE (exp));
 
   code = TREE_CODE (TREE_TYPE (exp));
   thissize = int_size_in_bytes (TREE_TYPE (exp));
 
-  /* Give the front end another chance to expand constants.  */
-  exp = lang_hooks.expand_constant (exp);
-
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
   if (TREE_CODE (exp) == CONSTRUCTOR
   /* Allow a constructor with no elements for any data type.
      This means to fill the space with zeros.  */
   if (TREE_CODE (exp) == CONSTRUCTOR
@@ -4383,17 +4658,18 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
+    case FIXED_POINT_TYPE:
       if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              MIN (size, thissize), align, 0))
       if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              MIN (size, thissize), align, 0))
-       error ("initializer for integer value is too complicated");
+       error ("initializer for integer/fixed-point value is too complicated");
       break;
 
     case REAL_TYPE:
       if (TREE_CODE (exp) != REAL_CST)
        error ("initializer for floating value is not a floating constant");
       break;
 
     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:
       break;
 
     case COMPLEX_TYPE:
@@ -4407,7 +4683,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
       switch (TREE_CODE (exp))
        {
        case CONSTRUCTOR:
       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),
          return;
        case STRING_CST:
          thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
@@ -4445,7 +4721,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case RECORD_TYPE:
     case UNION_TYPE:
       gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
     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:
       return;
 
     case ERROR_MARK:
@@ -4501,322 +4777,464 @@ array_size_for_constructor (tree val)
   return tree_low_cst (i, 1);
 }
 
   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.  */
 
 
-static void
-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 HOST_WIDE_INT cnt;
-  constructor_elt *ce;
+/* output_constructor local state to support interaction with helpers.  */
 
 
-  gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
+typedef struct {
 
 
-  if (TREE_CODE (type) == RECORD_TYPE)
-    field = TYPE_FIELDS (type);
+  /* Received arguments.  */
+  tree exp;                     /* Constructor expression.  */
+  unsigned HOST_WIDE_INT size;  /* # bytes to output - pad if necessary.  */
+  unsigned int align;           /* Known initial alignment.  */
 
 
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_DOMAIN (type) != 0)
-    min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+  /* 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.  */
 
 
-  /* 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.
-     But the constant could also be an array.  Then FIELD is zero.
+  /* 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.  */
 
 
-     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).  */
-  for (cnt = 0;
-       VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
-       cnt++, field = field ? TREE_CHAIN (field) : 0)
+  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++)
     {
     {
-      tree val = ce->value;
-      tree index = 0;
+      /* Output the element's initial value.  */
+      if (local->val == NULL_TREE)
+       assemble_zeros (fieldsize);
+      else
+       output_constant (local->val, fieldsize, align2);
 
 
-      /* 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;
+      /* Count its size.  */
+      local->total_bytes += fieldsize;
+    }
+}
 
 
-      else if (TREE_CODE (type) == ARRAY_TYPE)
-       index = ce->index;
+/* Helper for output_constructor.  From the current LOCAL state, output a
+   field element that is not true bitfield or part of an outer one.  */
 
 
-#ifdef ASM_COMMENT_START
-      if (field && flag_verbose_asm)
-       fprintf (asm_out_file, "%s %s:\n",
-                ASM_COMMENT_START,
-                DECL_NAME (field)
-                ? IDENTIFIER_POINTER (DECL_NAME (field))
-                : "<anonymous>");
-#endif
+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;
 
 
-      /* Eliminate the marker that makes a cast not be an lvalue.  */
-      if (val != 0)
-       STRIP_NOPS (val);
+  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);
 
 
-      if (index && TREE_CODE (index) == RANGE_EXPR)
+  /* 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))))
        {
        {
-         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;
-           }
+         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 (field == 0 || !DECL_BIT_FIELD (field))
+      else if (DECL_SIZE_UNIT (local->field))
        {
        {
-         /* An element that is not a bit-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));
 
 
-         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;
+  /* Output the element's initial value.  */
+  if (local->val == NULL_TREE)
+    assemble_zeros (fieldsize);
+  else
+    output_constant (local->val, fieldsize, 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)));
+  /* Count its size.  */
+  local->total_bytes += fieldsize;
+}
 
 
-         /* 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;
-           }
+/* 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.  */
 
 
-         /* 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;
-           }
+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;
+       }
 
 
-         /* Find the alignment of this element.  */
-         align2 = min_align (align, BITS_PER_UNIT * pos);
+      /* 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;
 
 
-         /* Determine size this element should occupy.  */
-         if (field)
+      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)
            {
            {
-             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);
-               }
+             this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
+             shift = HOST_BITS_PER_WIDE_INT;
            }
            }
-         else
-           fieldsize = int_size_in_bytes (TREE_TYPE (type));
 
 
-         /* Output the element's initial value.  */
-         if (val == 0)
-           assemble_zeros (fieldsize);
+         /* Now get the bits from the appropriate constant word.  */
+         if (shift < HOST_BITS_PER_WIDE_INT)
+           value = TREE_INT_CST_LOW (local->val);
          else
          else
-           output_constant (val, fieldsize, align2);
+           {
+             gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+             value = TREE_INT_CST_HIGH (local->val);
+             shift -= HOST_BITS_PER_WIDE_INT;
+           }
 
 
-         /* Count its size.  */
-         total_bytes += fieldsize;
+         /* 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 if (val != 0 && TREE_CODE (val) != INTEGER_CST)
-       error ("invalid initial value for member %qs",
-              IDENTIFIER_POINTER (DECL_NAME (field)));
       else
        {
       else
        {
-         /* Element that is a bit-field.  */
+         /* 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;
+           }
 
 
-         HOST_WIDE_INT next_offset = int_bit_position (field);
-         HOST_WIDE_INT end_offset
-           = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
+         /* 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);
+       }
 
 
-         if (val == 0)
-           val = integer_zero_node;
+      next_offset += this_time;
+      local->byte_buffer_in_use = true;
+    }
+}
 
 
-         /* 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;
-               }
+/* 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.  */
 
 
-             /* 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;
-               }
-           }
+static unsigned HOST_WIDE_INT
+output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+                   unsigned int align, oc_outer_state * outer)
+{
+  unsigned HOST_WIDE_INT cnt;
+  constructor_elt *ce;
 
 
-         if (! byte_buffer_in_use)
-           byte = 0;
+  oc_local_state local;
 
 
-         /* We must split the element into pieces that fall within
-            separate bytes, and combine each byte with previous or
-            following bit-fields.  */
+  /* Setup our local state to communicate with helpers.  */
+  local.exp = exp;
+  local.size = size;
+  local.align = align;
 
 
-         /* 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;
-               }
+  local.total_bytes = 0;
+  local.byte_buffer_in_use = outer != NULL;
+  local.byte = outer ? outer->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;
-                   }
+  local.type = TREE_TYPE (exp);
 
 
-                 /* 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;
-                   }
+  local.last_relative_index = -1;
 
 
-                 /* 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;
-                   }
+  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));
 
 
-                 /* 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);
-               }
+  gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
 
 
-             next_offset += this_time;
-             byte_buffer_in_use = 1;
-           }
-       }
+  /* 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++, local.field = local.field ? TREE_CHAIN (local.field) : 0)
+    {
+      local.val = ce->value;
+      local.index = NULL_TREE;
+
+      /* The element in a union constructor specifies the proper field
+        or 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 (local.field && flag_verbose_asm)
+       fprintf (asm_out_file, "%s %s:\n",
+                ASM_COMMENT_START,
+                DECL_NAME (local.field)
+                ? IDENTIFIER_POINTER (DECL_NAME (local.field))
+                : "<anonymous>");
+#endif
+
+      /* Eliminate the marker that makes a cast not be an lvalue.  */
+      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 (byte_buffer_in_use)
+  /* 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
     {
     {
-      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-      total_bytes++;
+      if (local.byte_buffer_in_use)
+       {
+         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 ((unsigned HOST_WIDE_INT)total_bytes < size)
-    assemble_zeros (size - total_bytes);
+  return local.total_bytes;
 }
 
 }
 
-/* This TREE_LIST contains any weak symbol declarations waiting
-   to be emitted.  */
-static GTY(()) tree weak_decls;
-
 /* Mark DECL as weak.  */
 
 static void
 /* Mark DECL as weak.  */
 
 static void
@@ -4860,7 +5278,7 @@ merge_weak (tree newdecl, tree olddecl)
       /* NEWDECL is weak, but OLDDECL is not.  */
 
       /* If we already output the OLDDECL, we're in trouble; we can't
       /* NEWDECL is weak, but OLDDECL is not.  */
 
       /* If we already output the OLDDECL, we're in trouble; we can't
-        go back and make it weak.  This error cannot caught in
+        go back and make it weak.  This error cannot be caught in
         declare_weak because the NEWDECL and OLDDECL was not yet
         been merged; therefore, TREE_ASM_WRITTEN was not set.  */
       if (TREE_ASM_WRITTEN (olddecl))
         declare_weak because the NEWDECL and OLDDECL was not yet
         been merged; therefore, TREE_ASM_WRITTEN was not set.  */
       if (TREE_ASM_WRITTEN (olddecl))
@@ -4909,15 +5327,13 @@ declare_weak (tree decl)
     error ("weak declaration of %q+D must be public", decl);
   else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
     error ("weak declaration of %q+D must precede definition", decl);
     error ("weak declaration of %q+D must be public", decl);
   else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
     error ("weak declaration of %q+D must precede definition", decl);
-  else if (SUPPORTS_WEAK)
-    {
-      if (! DECL_WEAK (decl))
-       weak_decls = tree_cons (NULL, decl, weak_decls);
-    }
-  else
+  else if (!SUPPORTS_WEAK)
     warning (0, "weak declaration of %q+D not supported", decl);
 
   mark_weak (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
 }
 
 static void
@@ -4978,7 +5394,7 @@ weak_finish (void)
       else if (! TREE_SYMBOL_REFERENCED (target))
        {
          /* Use ASM_WEAKEN_LABEL only if ASM_WEAKEN_DECL is not
       else if (! TREE_SYMBOL_REFERENCED (target))
        {
          /* Use ASM_WEAKEN_LABEL only if ASM_WEAKEN_DECL is not
-            defined, otherwise we and weak_finish_1 would use a
+            defined, otherwise we and weak_finish_1 would use
             different macros.  */
 # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
          ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
             different macros.  */
 # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
          ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
@@ -4987,7 +5403,8 @@ weak_finish (void)
 
          if (! decl)
            {
 
          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;
                                 TREE_TYPE (alias_decl));
 
              DECL_EXTERNAL (decl) = 1;
@@ -5083,21 +5500,7 @@ globalize_decl (tree decl)
   targetm.asm_out.globalize_decl_name (asm_out_file, decl);
 }
 
   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.  */
 
 /* Given an assembly name, find the decl it is associated with.  At the
    same time, mark it needed for cgraph.  */
@@ -5123,13 +5526,7 @@ find_decl_and_mark_needed (tree decl, tree target)
 
   if (fnode)
     {
 
   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)
       return fnode->decl;
     }
   else if (vnode)
@@ -5151,6 +5548,10 @@ do_assemble_alias (tree decl, tree target)
   if (TREE_ASM_WRITTEN (decl))
     return;
 
   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;
 
   TREE_ASM_WRITTEN (decl) = 1;
   TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
 
@@ -5176,7 +5577,8 @@ do_assemble_alias (tree decl, tree target)
 #else
       if (!SUPPORTS_WEAK)
        {
 #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
          return;
        }
 #endif
@@ -5240,6 +5642,39 @@ do_assemble_alias (tree decl, tree target)
 #endif
 }
 
 #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.  */
 
 /* First pass of completing pending aliases.  Make sure that cgraph knows
    which symbols will be required.  */
 
@@ -5257,13 +5692,18 @@ finish_aliases_1 (void)
       if (target_decl == NULL)
        {
          if (! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
       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)
        }
       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)))
               && ! 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);
     }
 }
 
     }
 }
 
@@ -5316,21 +5756,19 @@ assemble_alias (tree decl, tree target)
     {
 #if !defined (ASM_OUTPUT_DEF)
 # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
     {
 #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))
        {
       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
 #endif
     }
          return;
        }
 # 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
   TREE_USED (decl) = 1;
 
   /* A quirk of the initial implementation of aliases required that the user
@@ -5346,8 +5784,11 @@ assemble_alias (tree decl, tree target)
     varpool_node (decl)->alias = true;
 
   /* If the target has already been emitted, we don't have to queue the
     varpool_node (decl)->alias = true;
 
   /* If the target has already been emitted, we don't have to queue the
-     alias.  This saves a tad o memory.  */
-  target_decl = find_decl_and_mark_needed (decl, target);
+     alias.  This saves a tad of memory.  */
+  if (cgraph_global_info_ready)
+    target_decl = find_decl_and_mark_needed (decl, target);
+  else
+    target_decl= NULL;
   if (target_decl && TREE_ASM_WRITTEN (target_decl))
     do_assemble_alias (decl, target);
   else
   if (target_decl && TREE_ASM_WRITTEN (target_decl))
     do_assemble_alias (decl, target);
   else
@@ -5416,7 +5857,7 @@ supports_one_only (void)
    translation units without generating a linker error.  */
 
 void
    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);
 {
   gcc_assert (TREE_CODE (decl) == VAR_DECL
              || TREE_CODE (decl) == FUNCTION_DECL);
@@ -5428,7 +5869,7 @@ make_decl_one_only (tree decl)
 #ifdef MAKE_DECL_ONE_ONLY
       MAKE_DECL_ONE_ONLY (decl);
 #endif
 #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))
     }
   else if (TREE_CODE (decl) == VAR_DECL
       && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
@@ -5514,7 +5955,7 @@ init_varasm_once (void)
 }
 
 enum tls_model
 }
 
 enum tls_model
-decl_default_tls_model (tree decl)
+decl_default_tls_model (const_tree decl)
 {
   enum tls_model kind;
   bool is_local;
 {
   enum tls_model kind;
   bool is_local;
@@ -5558,8 +5999,8 @@ default_section_type_flags (tree decl, const char *name, int reloc)
     flags = 0;
   else if (current_function_decl
           && cfun
     flags = 0;
   else if (current_function_decl
           && cfun
-          && cfun->unlikely_text_section_name
-          && strcmp (name, cfun->unlikely_text_section_name) == 0)
+          && crtl->subsections.unlikely_text_section_name
+          && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0)
     flags = SECTION_CODE;
   else if (!decl
           && (!current_function_decl || !cfun)
     flags = SECTION_CODE;
   else if (!decl
           && (!current_function_decl || !cfun)
@@ -5629,6 +6070,10 @@ default_no_named_section (const char *name ATTRIBUTE_UNUSED,
   gcc_unreachable ();
 }
 
   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)
 void
 default_elf_asm_named_section (const char *name, unsigned int flags,
                               tree decl ATTRIBUTE_UNUSED)
@@ -5659,7 +6104,7 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
   if (flags & SECTION_STRINGS)
     *f++ = 'S';
   if (flags & SECTION_TLS)
   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';
   if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
     *f++ = 'G';
   *f = '\0';
@@ -5688,8 +6133,13 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
       if (flags & SECTION_ENTSIZE)
        fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
       if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
       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);
     }
 
   putc ('\n', asm_out_file);
@@ -5754,7 +6204,7 @@ default_select_section (tree decl, int reloc,
 }
 
 enum section_category
 }
 
 enum section_category
-categorize_decl_for_section (tree decl, int reloc)
+categorize_decl_for_section (const_tree decl, int reloc)
 {
   enum section_category ret;
 
 {
   enum section_category ret;
 
@@ -5809,13 +6259,26 @@ categorize_decl_for_section (tree decl, int reloc)
     ret = SECCAT_RODATA;
 
   /* There are no read-only thread-local sections.  */
     ret = SECCAT_RODATA;
 
   /* There are no read-only thread-local sections.  */
-  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
+  if (TREE_CODE (decl) == VAR_DECL && DECL_TLS_MODEL (decl))
     {
     {
+      if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED)
+       {
+         if (DECL_EMUTLS_VAR_P (decl))
+           {
+             if (targetm.emutls.var_section)
+               ret = SECCAT_EMUTLS_VAR;
+           }
+         else
+           {
+             if (targetm.emutls.tmpl_prefix)
+               ret = SECCAT_EMUTLS_TMPL;
+           }
+       }
       /* Note that this would be *just* SECCAT_BSS, except that there's
         no concept of a read-only thread-local-data section.  */
       /* Note that this would be *just* SECCAT_BSS, except that there's
         no concept of a read-only thread-local-data section.  */
-      if (ret == SECCAT_BSS
-         || (flag_zero_initialized_in_bss
-             && initializer_zerop (DECL_INITIAL (decl))))
+      else if (ret == SECCAT_BSS
+              || (flag_zero_initialized_in_bss
+                  && initializer_zerop (DECL_INITIAL (decl))))
        ret = SECCAT_TBSS;
       else
        ret = SECCAT_TDATA;
        ret = SECCAT_TBSS;
       else
        ret = SECCAT_TDATA;
@@ -5836,7 +6299,7 @@ categorize_decl_for_section (tree decl, int reloc)
 }
 
 bool
 }
 
 bool
-decl_readonly_section (tree decl, int reloc)
+decl_readonly_section (const_tree decl, int reloc)
 {
   switch (categorize_decl_for_section (decl, reloc))
     {
 {
   switch (categorize_decl_for_section (decl, reloc))
     {
@@ -5907,6 +6370,12 @@ default_elf_select_section (tree decl, int reloc,
     case SECCAT_TBSS:
       sname = ".tbss";
       break;
     case SECCAT_TBSS:
       sname = ".tbss";
       break;
+    case SECCAT_EMUTLS_VAR:
+      sname = targetm.emutls.var_section;
+      break;
+    case SECCAT_EMUTLS_TMPL:
+      sname = targetm.emutls.tmpl_section;
+      break;
     default:
       gcc_unreachable ();
     }
     default:
       gcc_unreachable ();
     }
@@ -5924,69 +6393,73 @@ default_unique_section (tree decl, int reloc)
 {
   /* We only need to use .gnu.linkonce if we don't have COMDAT groups.  */
   bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
 {
   /* We only need to use .gnu.linkonce if we don't have COMDAT groups.  */
   bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
-  const char *prefix, *name;
-  size_t nlen, plen;
+  const char *prefix, *name, *linkonce;
   char *string;
 
   switch (categorize_decl_for_section (decl, reloc))
     {
     case SECCAT_TEXT:
   char *string;
 
   switch (categorize_decl_for_section (decl, reloc))
     {
     case SECCAT_TEXT:
-      prefix = one_only ? ".gnu.linkonce.t." : ".text.";
+      prefix = one_only ? ".t" : ".text";
       break;
     case SECCAT_RODATA:
     case SECCAT_RODATA_MERGE_STR:
     case SECCAT_RODATA_MERGE_STR_INIT:
     case SECCAT_RODATA_MERGE_CONST:
       break;
     case SECCAT_RODATA:
     case SECCAT_RODATA_MERGE_STR:
     case SECCAT_RODATA_MERGE_STR_INIT:
     case SECCAT_RODATA_MERGE_CONST:
-      prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
+      prefix = one_only ? ".r" : ".rodata";
       break;
     case SECCAT_SRODATA:
       break;
     case SECCAT_SRODATA:
-      prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2.";
+      prefix = one_only ? ".s2" : ".sdata2";
       break;
     case SECCAT_DATA:
       break;
     case SECCAT_DATA:
-      prefix = one_only ? ".gnu.linkonce.d." : ".data.";
+      prefix = one_only ? ".d" : ".data";
       break;
     case SECCAT_DATA_REL:
       break;
     case SECCAT_DATA_REL:
-      prefix = one_only ? ".gnu.linkonce.d.rel." : ".data.rel.";
+      prefix = one_only ? ".d.rel" : ".data.rel";
       break;
     case SECCAT_DATA_REL_LOCAL:
       break;
     case SECCAT_DATA_REL_LOCAL:
-      prefix = one_only ? ".gnu.linkonce.d.rel.local." : ".data.rel.local.";
+      prefix = one_only ? ".d.rel.local" : ".data.rel.local";
       break;
     case SECCAT_DATA_REL_RO:
       break;
     case SECCAT_DATA_REL_RO:
-      prefix = one_only ? ".gnu.linkonce.d.rel.ro." : ".data.rel.ro.";
+      prefix = one_only ? ".d.rel.ro" : ".data.rel.ro";
       break;
     case SECCAT_DATA_REL_RO_LOCAL:
       break;
     case SECCAT_DATA_REL_RO_LOCAL:
-      prefix = one_only ? ".gnu.linkonce.d.rel.ro.local."
-              : ".data.rel.ro.local.";
+      prefix = one_only ? ".d.rel.ro.local" : ".data.rel.ro.local";
       break;
     case SECCAT_SDATA:
       break;
     case SECCAT_SDATA:
-      prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
+      prefix = one_only ? ".s" : ".sdata";
       break;
     case SECCAT_BSS:
       break;
     case SECCAT_BSS:
-      prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
+      prefix = one_only ? ".b" : ".bss";
       break;
     case SECCAT_SBSS:
       break;
     case SECCAT_SBSS:
-      prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
+      prefix = one_only ? ".sb" : ".sbss";
       break;
     case SECCAT_TDATA:
       break;
     case SECCAT_TDATA:
-      prefix = one_only ? ".gnu.linkonce.td." : ".tdata.";
+      prefix = one_only ? ".td" : ".tdata";
       break;
     case SECCAT_TBSS:
       break;
     case SECCAT_TBSS:
-      prefix = one_only ? ".gnu.linkonce.tb." : ".tbss.";
+      prefix = one_only ? ".tb" : ".tbss";
+      break;
+    case SECCAT_EMUTLS_VAR:
+      prefix = targetm.emutls.var_section;
+      break;
+    case SECCAT_EMUTLS_TMPL:
+      prefix = targetm.emutls.tmpl_section;
       break;
     default:
       gcc_unreachable ();
     }
       break;
     default:
       gcc_unreachable ();
     }
-  plen = strlen (prefix);
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   name = targetm.strip_name_encoding (name);
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   name = targetm.strip_name_encoding (name);
-  nlen = strlen (name);
 
 
-  string = alloca (nlen + plen + 1);
-  memcpy (string, prefix, plen);
-  memcpy (string + plen, name, nlen + 1);
+  /* If we're using one_only, then there needs to be a .gnu.linkonce
+     prefix to the section name.  */
+  linkonce = one_only ? ".gnu.linkonce" : "";
 
 
-  DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
+  string = ACONCAT ((linkonce, prefix, ".", name, NULL));
+
+  DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
 }
 
 /* Like compute_reloc_for_constant, except for an RTX.  The return value
 }
 
 /* Like compute_reloc_for_constant, except for an RTX.  The return value
@@ -5996,7 +6469,7 @@ default_unique_section (tree decl, int reloc)
 static int
 compute_reloc_for_rtx_1 (rtx *xp, void *data)
 {
 static int
 compute_reloc_for_rtx_1 (rtx *xp, void *data)
 {
-  int *preloc = data;
+  int *preloc = (int *) data;
   rtx x = *xp;
 
   switch (GET_CODE (x))
   rtx x = *xp;
 
   switch (GET_CODE (x))
@@ -6083,8 +6556,8 @@ default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
     flags |= SYMBOL_FLAG_FUNCTION;
   if (targetm.binds_local_p (decl))
     flags |= SYMBOL_FLAG_LOCAL;
     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;
     flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
   else if (targetm.in_small_data_p (decl))
     flags |= SYMBOL_FLAG_SMALL;
@@ -6124,7 +6597,7 @@ default_asm_output_anchor (rtx symbol)
 /* The default implementation of TARGET_USE_ANCHORS_FOR_SYMBOL_P.  */
 
 bool
 /* The default implementation of TARGET_USE_ANCHORS_FOR_SYMBOL_P.  */
 
 bool
-default_use_anchors_for_symbol_p (rtx symbol)
+default_use_anchors_for_symbol_p (const_rtx symbol)
 {
   section *sect;
   tree decl;
 {
   section *sect;
   tree decl;
@@ -6163,13 +6636,13 @@ default_use_anchors_for_symbol_p (rtx symbol)
    wrt cross-module name binding.  */
 
 bool
    wrt cross-module name binding.  */
 
 bool
-default_binds_local_p (tree exp)
+default_binds_local_p (const_tree exp)
 {
   return default_binds_local_p_1 (exp, flag_shlib);
 }
 
 bool
 {
   return default_binds_local_p_1 (exp, flag_shlib);
 }
 
 bool
-default_binds_local_p_1 (tree exp, int shlib)
+default_binds_local_p_1 (const_tree exp, int shlib)
 {
   bool local_p;
 
 {
   bool local_p;
 
@@ -6200,9 +6673,10 @@ default_binds_local_p_1 (tree exp, int shlib)
   else if (DECL_WEAK (exp))
     local_p = false;
   /* If PIC, then assume that any global name can be overridden by
   else if (DECL_WEAK (exp))
     local_p = false;
   /* If PIC, then assume that any global name can be overridden by
-     symbols resolved from other modules.  */
+     symbols resolved from other modules, unless we are compiling with
+     -fwhole-program, which assumes that names are local.  */
   else if (shlib)
   else if (shlib)
-    local_p = false;
+    local_p = flag_whole_program;
   /* Uninitialized COMMON variable may be unified with symbols
      resolved from other modules.  */
   else if (DECL_COMMON (exp)
   /* Uninitialized COMMON variable may be unified with symbols
      resolved from other modules.  */
   else if (DECL_COMMON (exp)
@@ -6217,14 +6691,6 @@ default_binds_local_p_1 (tree exp, int shlib)
   return local_p;
 }
 
   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.  */
 /* 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.  */
@@ -6272,7 +6738,7 @@ void
 default_internal_label (FILE *stream, const char *prefix,
                        unsigned long labelno)
 {
 default_internal_label (FILE *stream, const char *prefix,
                        unsigned long labelno)
 {
-  char *const buf = alloca (40 + strlen (prefix));
+  char *const buf = (char *) alloca (40 + strlen (prefix));
   ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
   ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
 }
   ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
   ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
 }
@@ -6282,7 +6748,8 @@ default_internal_label (FILE *stream, const char *prefix,
 void
 default_file_start (void)
 {
 void
 default_file_start (void)
 {
-  if (targetm.file_start_app_off && !flag_verbose_asm)
+  if (targetm.file_start_app_off
+      && !(flag_verbose_asm || flag_debug_asm || flag_dump_rtl_in_asm))
     fputs (ASM_APP_OFF, asm_out_file);
 
   if (targetm.file_start_file_directive)
     fputs (ASM_APP_OFF, asm_out_file);
 
   if (targetm.file_start_file_directive)
@@ -6333,10 +6800,10 @@ switch_to_section (section *new_section)
     {
     case SECTION_NAMED:
       if (cfun
     {
     case SECTION_NAMED:
       if (cfun
-         && !cfun->unlikely_text_section_name
+         && !crtl->subsections.unlikely_text_section_name
          && strcmp (new_section->named.name,
                     UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
          && strcmp (new_section->named.name,
                     UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
-       cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
+       crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME;
 
       targetm.asm_out.named_section (new_section->named.name,
                                     new_section->named.common.flags,
 
       targetm.asm_out.named_section (new_section->named.name,
                                     new_section->named.common.flags,