OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / varasm.c
index 8a61fd2..4742304 100644 (file)
@@ -1,7 +1,7 @@
 /* Output variables, constants and external declarations, for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -38,8 +38,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "hard-reg-set.h"
 #include "regs.h"
-#include "real.h"
 #include "output.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "hashtab.h"
 #include "ggc.h"
@@ -170,11 +170,9 @@ bool in_cold_section_p;
 static GTY(()) section *unnamed_sections;
 
 /* Return a nonzero value if DECL has a section attribute.  */
-#ifndef IN_NAMED_SECTION
 #define IN_NAMED_SECTION(DECL) \
   ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
    && DECL_SECTION_NAME (DECL) != NULL_TREE)
-#endif
 
 /* Hash table of named sections.  */
 static GTY((param_is (section))) htab_t section_htab;
@@ -188,287 +186,6 @@ static GTY(()) int anchor_labelno;
 /* A pool of constants that can be shared between functions.  */
 static GTY(()) struct rtx_constant_pool *shared_constant_pool;
 
-/* TLS emulation.  */
-
-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
-     htab_t emutls_htab;
-static GTY (()) tree emutls_object_type;
-/* 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
-# define EMUTLS_SEPARATOR      "_"
-#endif
-
-/* Create an IDENTIFIER_NODE by prefixing PREFIX to the
-   IDENTIFIER_NODE NAME's name.  */
-
-static tree
-prefix_name (const char *prefix, tree name)
-{
-  unsigned plen = strlen (prefix);
-  unsigned nlen = strlen (IDENTIFIER_POINTER (name));
-  char *toname = (char *) alloca (plen + nlen + 1);
-  
-  memcpy (toname, prefix, plen);
-  memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1);
-
-  return get_identifier (toname);
-}
-
-/* Create an identifier for the struct __emutls_object, given an identifier
-   of the DECL_ASSEMBLY_NAME of the original object.  */
-
-static tree
-get_emutls_object_name (tree name)
-{
-  const char *prefix = (targetm.emutls.var_prefix
-                       ? targetm.emutls.var_prefix
-                       : "__emutls_v" EMUTLS_SEPARATOR);
-  return prefix_name (prefix, name);
-}
-
-tree
-default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
-{
-  tree word_type_node, field, next_field;
-  
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
-  DECL_CONTEXT (field) = type;
-  next_field = field;
-    
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__offset"),
-                     ptr_type_node);
-  DECL_CONTEXT (field) = type;
-  TREE_CHAIN (field) = next_field;
-  next_field = field;
-  
-  word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__align"),
-                     word_type_node);
-  DECL_CONTEXT (field) = type;
-  TREE_CHAIN (field) = next_field;
-  next_field = field;
-  
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__size"), word_type_node);
-  DECL_CONTEXT (field) = type;
-  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);
-
-  return type;
-}
-
-/* Create a read-only variable like DECL, with the same DECL_INITIAL.
-   This will be used for initializing the emulated tls data area.  */
-
-static tree
-get_emutls_init_templ_addr (tree decl)
-{
-  tree name, to;
-  
-  if (targetm.emutls.register_common && !DECL_INITIAL (decl)
-      && !DECL_SECTION_NAME (decl))
-    return null_pointer_node;
-
-  name = DECL_ASSEMBLER_NAME (decl);
-  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 (DECL_SOURCE_LOCATION (decl),
-                  VAR_DECL, name, TREE_TYPE (decl));
-  SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
-  DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED;
-  DECL_ARTIFICIAL (to) = 1;
-  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))
-    {
-      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);
-    }
-  else
-    TREE_STATIC (to) = 1;
-
-  DECL_INITIAL (to) = DECL_INITIAL (decl);
-  DECL_INITIAL (decl) = NULL;
-
-  varpool_finalize_decl (to);
-  return build_fold_addr_expr (to);
-}
-
-/* When emulating tls, we use a control structure for use by the runtime.
-   Create and return this structure.  */
-
-tree
-emutls_decl (tree decl)
-{
-  tree name, to;
-  struct tree_map *h, in;
-  void **loc;
-
-  if (targetm.have_tls || decl == NULL || decl == error_mark_node
-      || TREE_CODE (decl) != VAR_DECL || ! DECL_THREAD_LOCAL_P (decl))
-    return decl;
-
-  /* Look up the object in the hash; return the control structure if
-     it has already been created.  */
-  if (! emutls_htab)
-    emutls_htab = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0);
-
-  name = DECL_ASSEMBLER_NAME (decl);
-
-  /* Note that we use the hash of the decl's name, rather than a hash
-     of the decl's pointer.  In emutls_finish we iterate through the
-     hash table, and we want this traversal to be predictable.  */
-  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 = (struct tree_map *) *loc;
-  if (h != NULL)
-    to = h->to;
-  else
-    {
-      to = build_decl (DECL_SOURCE_LOCATION (decl),
-                      VAR_DECL, get_emutls_object_name (name),
-                      get_emutls_object_type ());
-
-      h = GGC_NEW (struct tree_map);
-      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;
-      SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to));
-      if (DECL_ONE_ONLY (decl))
-       make_decl_one_only (to, DECL_ASSEMBLER_NAME (to));
-      DECL_CONTEXT (to) = DECL_CONTEXT (decl);
-      if (targetm.emutls.var_align_fixed)
-       /* If we're not allowed to change the proxy object's
-          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
-     the original decl.  Consider:
-       extern __thread int i;
-       int foo() { return i; }
-       __thread int i = 1;
-     in which I goes from external to locally defined and initialized.  */
-
-  TREE_STATIC (to) = TREE_STATIC (decl);
-  TREE_USED (to) = TREE_USED (decl);
-  TREE_PUBLIC (to) = TREE_PUBLIC (decl);
-  DECL_EXTERNAL (to) = DECL_EXTERNAL (decl);
-  DECL_COMMON (to) = DECL_COMMON (decl);
-  DECL_WEAK (to) = DECL_WEAK (decl);
-  DECL_VISIBILITY (to) = DECL_VISIBILITY (decl);
-
-  return to;
-}
-
-static int
-emutls_common_1 (void **loc, void *xstmts)
-{
-  struct tree_map *h = *(struct tree_map **) loc;
-  tree args, x, *pstmts = (tree *) xstmts;
-  tree word_type_node;
-
-  if (! DECL_COMMON (h->base.from)
-      || (DECL_INITIAL (h->base.from)
-         && DECL_INITIAL (h->base.from) != error_mark_node))
-    return 1;
-
-  word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
-
-  /* The idea was to call get_emutls_init_templ_addr here, but if we
-     do this and there is an initializer, -fanchor_section loses,
-     because it would be too late to ensure the template is
-     output.  */
-  x = null_pointer_node;
-  args = tree_cons (NULL, x, NULL);
-  x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->base.from));
-  args = tree_cons (NULL, x, args);
-  x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->base.from));
-  args = tree_cons (NULL, x, args);
-  x = build_fold_addr_expr (h->to);
-  args = tree_cons (NULL, x, args);
-
-  x = built_in_decls[BUILT_IN_EMUTLS_REGISTER_COMMON];
-  x = build_function_call_expr (UNKNOWN_LOCATION, x, args);
-
-  append_to_statement_list (x, pstmts);
-  return 1;
-}
-
-void
-emutls_finish (void)
-{
-  if (targetm.emutls.register_common)
-    {
-      tree body = NULL_TREE;
-
-      if (emutls_htab == NULL)
-       return;
-
-      htab_traverse_noresize (emutls_htab, emutls_common_1, &body);
-      if (body == NULL_TREE)
-       return;
-      
-      cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY);
-    }
-}
-
 /* Helper routines for maintaining section_htab.  */
 
 static int
@@ -523,7 +240,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
 {
   section *sect;
 
-  sect = GGC_NEW (section);
+  sect = ggc_alloc_section ();
   sect->unnamed.common.flags = flags | SECTION_UNNAMED;
   sect->unnamed.callback = callback;
   sect->unnamed.data = data;
@@ -540,7 +257,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
 {
   section *sect;
 
-  sect = GGC_NEW (section);
+  sect = ggc_alloc_section ();
   sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
   sect->noswitch.callback = callback;
 
@@ -561,7 +278,7 @@ get_section (const char *name, unsigned int flags, tree decl)
   flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
-      sect = GGC_NEW (section);
+      sect = ggc_alloc_section ();
       sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
@@ -610,8 +327,7 @@ get_block_for_section (section *sect)
   block = (struct object_block *) *slot;
   if (block == NULL)
     {
-      block = (struct object_block *)
-       ggc_alloc_cleared (sizeof (struct object_block));
+      block = ggc_alloc_cleared_object_block ();
       block->sect = sect;
       *slot = block;
     }
@@ -631,7 +347,7 @@ create_block_symbol (const char *label, struct object_block *block,
 
   /* Create the extended SYMBOL_REF.  */
   size = RTX_HDR_SIZE + sizeof (struct block_symbol);
-  symbol = (rtx) ggc_alloc_zone (size, &rtl_zone);
+  symbol = ggc_alloc_zone_rtx_def (size, &rtl_zone);
 
   /* Initialize the normal SYMBOL_REF fields.  */
   memset (symbol, 0, size);
@@ -1168,19 +884,21 @@ align_variable (tree decl, bool dont_output_data)
 static section *
 get_variable_section (tree decl, bool prefer_noswitch_p)
 {
+  addr_space_t as = ADDR_SPACE_GENERIC;
   int reloc;
 
-  /* If the decl has been given an explicit section name, then it
-     isn't common, and shouldn't be handled as such.  */
-  if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL)
+  if (TREE_TYPE (decl) != error_mark_node)
+    as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+
+  if (DECL_COMMON (decl))
     {
+      /* If the decl has been given an explicit section name, or it resides
+        in a non-generic address space, then it isn't common, and shouldn't
+        be handled as such.  */
+      gcc_assert (DECL_SECTION_NAME (decl) == NULL
+                 && ADDR_SPACE_GENERIC_P (as));
       if (DECL_THREAD_LOCAL_P (decl))
        return tls_comm_section;
-      /* This cannot be common bss for an emulated TLS object without
-        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;
     }
@@ -1196,7 +914,8 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
   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))
     {
@@ -1348,6 +1067,14 @@ make_decl_rtl (tree decl)
       return;
     }
 
+  /* If this variable belongs to the global constant pool, retrieve the
+     pre-computed RTL or recompute it in LTO mode.  */
+  if (TREE_CODE (decl) == VAR_DECL && DECL_IN_CONSTANT_POOL (decl))
+    {
+      SET_DECL_RTL (decl, output_constant_def (DECL_INITIAL (decl), 1));
+      return;
+    }
+
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
 
   if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
@@ -1427,6 +1154,10 @@ make_decl_rtl (tree decl)
 
   /* Specifying a section attribute on a variable forces it into a
      non-.bss section, and thus it cannot be common.  */
+  /* FIXME: In general this code should not be necessary because
+     visibility pass is doing the same work.  But notice_global_symbol
+     is called early and it needs to make DECL_RTL to get the name.
+     we take care of recomputing the DECL_RTL after visibility is changed.  */
   if (TREE_CODE (decl) == VAR_DECL
       && DECL_SECTION_NAME (decl) != NULL_TREE
       && DECL_INITIAL (decl) == NULL_TREE
@@ -1440,7 +1171,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
-    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);
 
@@ -1459,6 +1198,42 @@ make_decl_rtl (tree decl)
   if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
     mudflap_enqueue_decl (decl);
 }
+
+/* Like make_decl_rtl, but inhibit creation of new alias sets when
+   calling make_decl_rtl.  Also, reset DECL_RTL before returning the
+   rtl.  */
+
+rtx
+make_decl_rtl_for_debug (tree decl)
+{
+  unsigned int save_aliasing_flag, save_mudflap_flag;
+  rtx rtl;
+
+  if (DECL_RTL_SET_P (decl))
+    return DECL_RTL (decl);
+
+  /* Kludge alert!  Somewhere down the call chain, make_decl_rtl will
+     call new_alias_set.  If running with -fcompare-debug, sometimes
+     we do not want to create alias sets that will throw the alias
+     numbers off in the comparison dumps.  So... clearing
+     flag_strict_aliasing will keep new_alias_set() from creating a
+     new set.  It is undesirable to register decl with mudflap
+     in this case as well.  */
+  save_aliasing_flag = flag_strict_aliasing;
+  flag_strict_aliasing = 0;
+  save_mudflap_flag = flag_mudflap;
+  flag_mudflap = 0;
+
+  rtl = DECL_RTL (decl);
+  /* Reset DECL_RTL back, as various parts of the compiler expects
+     DECL_RTL set meaning it is actually going to be output.  */
+  SET_DECL_RTL (decl, NULL);
+
+  flag_strict_aliasing = save_aliasing_flag;
+  flag_mudflap = save_mudflap_flag;
+
+  return rtl;
+}
 \f
 /* Output a string of literal assembler code
    for an `asm' keyword used between functions.  */
@@ -1494,7 +1269,7 @@ default_stabs_asm_out_destructor (rtx symbol ATTRIBUTE_UNUSED,
 }
 
 /* Write the address of the entity given by SYMBOL to SEC.  */
-void 
+void
 assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
@@ -1525,7 +1300,7 @@ default_named_section_asm_out_destructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_PRIORITY)
-    sec = get_cdtor_priority_section (priority, 
+    sec = get_cdtor_priority_section (priority,
                                      /*constructor_p=*/false);
   else
     sec = get_section (".dtors", SECTION_WRITE, NULL);
@@ -1565,7 +1340,7 @@ default_named_section_asm_out_constructor (rtx symbol, int priority)
   section *sec;
 
   if (priority != DEFAULT_INIT_PRIORITY)
-    sec = get_cdtor_priority_section (priority, 
+    sec = get_cdtor_priority_section (priority,
                                      /*constructor_p=*/true);
   else
     sec = get_section (".ctors", SECTION_WRITE, NULL);
@@ -1771,7 +1546,7 @@ assemble_start_function (tree decl, const char *fnname)
   ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
 #else
   /* Standard thing is just output label for the function.  */
-  ASM_OUTPUT_LABEL (asm_out_file, fnname);
+  ASM_OUTPUT_FUNCTION_LABEL (asm_out_file, fnname, current_function_decl);
 #endif /* ASM_DECLARE_FUNCTION_NAME */
 }
 
@@ -2007,40 +1782,6 @@ 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.
@@ -2059,35 +1800,12 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   rtx decl_rtl, symbol;
   section *sect;
 
-  if (! targetm.have_tls
-      && TREE_CODE (decl) == VAR_DECL
-      && DECL_THREAD_LOCAL_P (decl))
-    {
-      tree to = emutls_decl (decl);
-
-      /* If this variable is defined locally, then we need to initialize the
-         control structure with size and alignment information.  We do this
-        at the last moment because tentative definitions can take a locally
-        defined but uninitialized variable and initialize it later, which
-        would result in incorrect contents.  */
-      if (! DECL_EXTERNAL (to)
-         && (! DECL_COMMON (to)
-             || (DECL_INITIAL (decl)
-                 && DECL_INITIAL (decl) != error_mark_node)))
-       {
-         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.  */
-         record_references_in_initializer (to);
-       }
-
-      decl = to;
-    }
+  /* This function is supposed to handle VARIABLES.  Ensure we have one.  */
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
 
+  /* Emulated TLS had better not get this far.  */
+  gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl));
+              
   last_assemble_variable_decl = 0;
 
   /* Normally no need to say anything here for external references,
@@ -2097,12 +1815,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   if (DECL_EXTERNAL (decl))
     return;
 
-  /* Output no assembler code for a function declaration.
-     Only definitions of functions output anything.  */
-
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    return;
-
   /* Do nothing for global register variables.  */
   if (DECL_RTL_SET_P (decl) && REG_P (DECL_RTL (decl)))
     {
@@ -2144,8 +1856,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   if (flag_syntax_only)
     return;
 
-  app_disable ();
-
   if (! dont_output_data
       && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
     {
@@ -2156,6 +1866,19 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   gcc_assert (MEM_P (decl_rtl));
   gcc_assert (GET_CODE (XEXP (decl_rtl, 0)) == SYMBOL_REF);
   symbol = XEXP (decl_rtl, 0);
+
+  /* If this symbol belongs to the tree constant pool, output the constant
+     if it hasn't already been written.  */
+  if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
+    {
+      tree decl = SYMBOL_REF_DECL (symbol);
+      if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
+       output_constant_def_contents (symbol);
+      return;
+    }
+
+  app_disable ();
+
   name = XSTR (symbol, 0);
   if (TREE_PUBLIC (decl) && DECL_NAME (decl))
     notice_global_symbol (decl);
@@ -2224,7 +1947,7 @@ contains_pointers_p (tree type)
       {
        tree fields;
        /* For a type that has fields, see if the fields have pointers.  */
-       for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+       for (fields = TYPE_FIELDS (type); fields; fields = DECL_CHAIN (fields))
          if (TREE_CODE (fields) == FIELD_DECL
              && contains_pointers_p (TREE_TYPE (fields)))
            return 1;
@@ -2322,13 +2045,15 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
   /* We want to output annotation for weak and external symbols at
      very last to check if they are references or not.  */
 
-  if (SUPPORTS_WEAK && DECL_WEAK (decl)
+  if (SUPPORTS_WEAK
+      && DECL_WEAK (decl)
       /* TREE_STATIC is a weird and abused creature which is not
         generally the right test for whether an entity has been
         locally emitted, inlined or otherwise not-really-extern, but
         for declarations that can be weak, it happens to be
         match.  */
       && !TREE_STATIC (decl)
+      && lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
       && value_member (decl, weak_decls) == NULL_TREE)
     weak_decls = tree_cons (NULL, decl, weak_decls);
 
@@ -2355,9 +2080,9 @@ assemble_external_libcall (rtx fun)
 /* Assemble a label named NAME.  */
 
 void
-assemble_label (const char *name)
+assemble_label (FILE *file, const char *name)
 {
-  ASM_OUTPUT_LABEL (asm_out_file, name);
+  ASM_OUTPUT_LABEL (file, name);
 }
 
 /* Set the symbol_referenced flag for ID.  */
@@ -2507,7 +2232,6 @@ assemble_static_space (unsigned HOST_WIDE_INT size)
 
 static GTY(()) rtx initial_trampoline;
 
-#ifdef TRAMPOLINE_TEMPLATE
 rtx
 assemble_trampoline_template (void)
 {
@@ -2516,6 +2240,8 @@ assemble_trampoline_template (void)
   int align;
   rtx symbol;
 
+  gcc_assert (targetm.asm_out.trampoline_template != NULL);
+
   if (initial_trampoline)
     return initial_trampoline;
 
@@ -2530,12 +2256,10 @@ assemble_trampoline_template (void)
   /* Write the assembler code to define one.  */
   align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
   if (align > 0)
-    {
-      ASM_OUTPUT_ALIGN (asm_out_file, align);
-    }
+    ASM_OUTPUT_ALIGN (asm_out_file, align);
 
   targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
-  TRAMPOLINE_TEMPLATE (asm_out_file);
+  targetm.asm_out.trampoline_template (asm_out_file);
 
   /* Record the rtl to refer to it.  */
   ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
@@ -2543,12 +2267,12 @@ assemble_trampoline_template (void)
   symbol = gen_rtx_SYMBOL_REF (Pmode, name);
   SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
 
-  initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
+  initial_trampoline = gen_const_mem (BLKmode, symbol);
   set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
+  set_mem_size (initial_trampoline, GEN_INT (TRAMPOLINE_SIZE));
 
   return initial_trampoline;
 }
-#endif
 \f
 /* A and B are either alignments or offsets.  Return the minimum alignment
    that may be assumed after adding the two together.  */
@@ -2735,7 +2459,6 @@ decode_addr_const (tree exp, struct addr_const *value)
     {
       if (TREE_CODE (target) == COMPONENT_REF
          && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
-
        {
          offset += int_byte_position (TREE_OPERAND (target, 1));
          target = TREE_OPERAND (target, 0);
@@ -2747,6 +2470,11 @@ decode_addr_const (tree exp, struct addr_const *value)
                     * tree_low_cst (TREE_OPERAND (target, 1), 0));
          target = TREE_OPERAND (target, 0);
        }
+      else if (TREE_CODE (target) == INDIRECT_REF
+              && TREE_CODE (TREE_OPERAND (target, 0)) == NOP_EXPR
+              && TREE_CODE (TREE_OPERAND (TREE_OPERAND (target, 0), 0))
+                 == ADDR_EXPR)
+       target = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (target, 0), 0), 0);
       else
        break;
     }
@@ -2787,12 +2515,11 @@ decode_addr_const (tree exp, struct addr_const *value)
 static GTY((param_is (struct constant_descriptor_tree)))
      htab_t const_desc_htab;
 
-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 
+htab_t
 constant_pool_htab (void)
 {
   return const_desc_htab;
@@ -2839,6 +2566,18 @@ const_hash_1 (const tree exp)
       return (const_hash_1 (TREE_REALPART (exp)) * 5
              + const_hash_1 (TREE_IMAGPART (exp)));
 
+    case VECTOR_CST:
+      {
+       tree link;
+
+       hi = 7 + TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp));
+
+       for (link = TREE_VECTOR_CST_ELTS (exp); link; link = TREE_CHAIN (link))
+           hi = hi * 563 + const_hash_1 (TREE_VALUE (link));
+
+       return hi;
+      }
+
     case CONSTRUCTOR:
       {
        unsigned HOST_WIDE_INT idx;
@@ -2967,6 +2706,27 @@ compare_constant (const tree t1, const tree t2)
       return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
              && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
 
+    case VECTOR_CST:
+      {
+        tree link1, link2;
+
+        if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1))
+           != TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)))
+         return 0;
+
+       link2 = TREE_VECTOR_CST_ELTS (t2);
+       for (link1 = TREE_VECTOR_CST_ELTS (t1);
+            link1;
+            link1 = TREE_CHAIN (link1))
+         {
+           if (!compare_constant (TREE_VALUE (link1), TREE_VALUE (link2)))
+             return 0;
+           link2 = TREE_CHAIN (link2);
+         }
+       
+       return 1;
+      }
+
     case CONSTRUCTOR:
       {
        VEC(constructor_elt, gc) *v1, *v2;
@@ -3027,11 +2787,34 @@ compare_constant (const tree t1, const tree t2)
     case FDESC_EXPR:
       {
        struct addr_const value1, value2;
+       enum rtx_code code;
+       int ret;
 
        decode_addr_const (t1, &value1);
        decode_addr_const (t2, &value2);
-       return (value1.offset == value2.offset
-               && strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
+
+       if (value1.offset != value2.offset)
+         return 0;
+
+       code = GET_CODE (value1.base);
+       if (code != GET_CODE (value2.base))
+         return 0;
+
+       switch (code)
+         {
+         case SYMBOL_REF:
+           ret = (strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
+           break;
+
+         case LABEL_REF:
+           ret = (CODE_LABEL_NUMBER (XEXP (value1.base, 0))
+                  == CODE_LABEL_NUMBER (XEXP (value2.base, 0)));
+           break;
+
+         default:
+           gcc_unreachable ();
+         }
+       return ret;
       }
 
     case PLUS_EXPR:
@@ -3092,6 +2875,10 @@ copy_constant (tree exp)
       return build1 (TREE_CODE (exp), TREE_TYPE (exp),
                     copy_constant (TREE_OPERAND (exp, 0)));
 
+    case VECTOR_CST:
+      return build_vector (TREE_TYPE (exp),
+                          copy_list (TREE_VECTOR_CST_ELTS (exp)));
+
     case CONSTRUCTOR:
       {
        tree copy = copy_node (exp);
@@ -3116,31 +2903,14 @@ copy_constant (tree exp)
     }
 }
 \f
-/* Return the alignment of constant EXP in bits.  */
-
-static unsigned int
-get_constant_alignment (tree exp)
-{
-  unsigned int align;
-
-  align = TYPE_ALIGN (TREE_TYPE (exp));
-#ifdef CONSTANT_ALIGNMENT
-  align = CONSTANT_ALIGNMENT (exp, align);
-#endif
-  return align;
-}
-
 /* Return the section into which constant EXP should be placed.  */
 
 static section *
-get_constant_section (tree exp)
+get_constant_section (tree exp, unsigned int align)
 {
-  if (IN_NAMED_SECTION (exp))
-    return get_named_section (exp, NULL, compute_reloc_for_constant (exp));
-  else
-    return targetm.asm_out.select_section (exp,
-                                          compute_reloc_for_constant (exp),
-                                          get_constant_alignment (exp));
+  return targetm.asm_out.select_section (exp,
+                                        compute_reloc_for_constant (exp),
+                                        align);
 }
 
 /* Return the size of constant EXP in bytes.  */
@@ -3166,13 +2936,13 @@ get_constant_size (tree exp)
 static struct constant_descriptor_tree *
 build_constant_desc (tree exp)
 {
-  rtx symbol;
-  rtx rtl;
+  struct constant_descriptor_tree *desc;
+  rtx symbol, rtl;
   char label[256];
   int labelno;
-  struct constant_descriptor_tree *desc;
+  tree decl;
 
-  desc = GGC_NEW (struct constant_descriptor_tree);
+  desc = ggc_alloc_constant_descriptor_tree ();
   desc->value = copy_constant (exp);
 
   /* Propagate marked-ness to copied constant.  */
@@ -3183,17 +2953,41 @@ build_constant_desc (tree exp)
   labelno = const_labelno++;
   ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
 
-  /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
+  /* Construct the VAR_DECL associated with the constant.  */
+  decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label),
+                    TREE_TYPE (exp));
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  TREE_READONLY (decl) = 1;
+  TREE_STATIC (decl) = 1;
+  TREE_ADDRESSABLE (decl) = 1;
+  /* We don't set the RTL yet as this would cause varpool to assume that the
+     variable is referenced.  Moreover, it would just be dropped in LTO mode.
+     Instead we set the flag that will be recognized in make_decl_rtl.  */
+  DECL_IN_CONSTANT_POOL (decl) = 1;
+  DECL_INITIAL (decl) = desc->value;
+  /* ??? CONSTANT_ALIGNMENT hasn't been updated for vector types on most
+     architectures so use DATA_ALIGNMENT as well, except for strings.  */
+  if (TREE_CODE (exp) == STRING_CST)
+    {
+#ifdef CONSTANT_ALIGNMENT
+      DECL_ALIGN (decl) = CONSTANT_ALIGNMENT (exp, DECL_ALIGN (decl));
+#endif
+    }
+  else
+    align_variable (decl, 0);
+
+  /* Now construct the SYMBOL_REF and the MEM.  */
   if (use_object_blocks_p ())
     {
-      section *sect = get_constant_section (exp);
+      section *sect = get_constant_section (exp, DECL_ALIGN (decl));
       symbol = create_block_symbol (ggc_strdup (label),
                                    get_block_for_section (sect), -1);
     }
   else
     symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
   SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL;
-  SET_SYMBOL_REF_DECL (symbol, desc->value);
+  SET_SYMBOL_REF_DECL (symbol, decl);
   TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
 
   rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
@@ -3210,7 +3004,6 @@ build_constant_desc (tree exp)
      ASM_OUTPUT_LABELREF will have to know how to strip this
      information.  This call might invalidate our local variable
      SYMBOL; we can't use it afterward.  */
-
   targetm.encode_section_info (exp, rtl, true);
 
   desc->rtl = rtl;
@@ -3301,12 +3094,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
   size = get_constant_size (exp);
 
   /* Do any machine/system dependent processing of the constant.  */
-#ifdef ASM_DECLARE_CONSTANT_NAME
-  ASM_DECLARE_CONSTANT_NAME (asm_out_file, label, exp, size);
-#else
-  /* Standard thing is just output label for the constant.  */
-  ASM_OUTPUT_LABEL (asm_out_file, label);
-#endif /* ASM_DECLARE_CONSTANT_NAME */
+  targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
 
   /* Output the value of EXP.  */
   output_constant (exp, size, align);
@@ -3317,7 +3105,8 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
 static void
 output_constant_def_contents (rtx symbol)
 {
-  tree exp = SYMBOL_REF_DECL (symbol);
+  tree decl = SYMBOL_REF_DECL (symbol);
+  tree exp = DECL_INITIAL (decl);
   unsigned int align;
 
   /* Make sure any other constants whose addresses appear in EXP
@@ -3334,8 +3123,8 @@ output_constant_def_contents (rtx symbol)
     place_block_symbol (symbol);
   else
     {
-      switch_to_section (get_constant_section (exp));
-      align = get_constant_alignment (exp);
+      align = DECL_ALIGN (decl);
+      switch_to_section (get_constant_section (exp, align));
       if (align > BITS_PER_UNIT)
        ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
       assemble_constant_contents (exp, XSTR (symbol, 0), align);
@@ -3360,6 +3149,37 @@ lookup_constant_def (tree exp)
 
   return (desc ? desc->rtl : NULL_RTX);
 }
+
+/* Return a tree representing a reference to constant data in memory
+   for the constant expression EXP.
+
+   This is the counterpart of output_constant_def at the Tree level.  */
+
+tree
+tree_output_constant_def (tree exp)
+{
+  struct constant_descriptor_tree *desc, key;
+  void **loc;
+  tree decl;
+
+  /* Look up EXP in the table of constant descriptors.  If we didn't find
+     it, create a new one.  */
+  key.value = exp;
+  key.hash = const_hash_1 (exp);
+  loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT);
+
+  desc = (struct constant_descriptor_tree *) *loc;
+  if (desc == 0)
+    {
+      desc = build_constant_desc (exp);
+      desc->hash = key.hash;
+      *loc = desc;
+    }
+
+  decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
+  varpool_finalize_decl (decl);
+  return decl;
+}
 \f
 /* Used in the hash tables to avoid outputting the same constant
    twice.  Unlike 'struct constant_descriptor_tree', RTX constants
@@ -3517,7 +3337,7 @@ create_constant_pool (void)
 {
   struct rtx_constant_pool *pool;
 
-  pool = GGC_NEW (struct rtx_constant_pool);
+  pool = ggc_alloc_rtx_constant_pool ();
   pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
                                          const_desc_rtx_eq, NULL);
   pool->first = NULL;
@@ -3583,7 +3403,7 @@ force_const_mem (enum machine_mode mode, rtx x)
     return copy_rtx (desc->mem);
 
   /* Otherwise, create a new descriptor.  */
-  desc = GGC_NEW (struct constant_descriptor_rtx);
+  desc = ggc_alloc_constant_descriptor_rtx ();
   *slot = desc;
 
   /* Align the location counter as required by EXP's data type.  */
@@ -3829,8 +3649,8 @@ mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
     }
   else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
     {
-      tree exp = SYMBOL_REF_DECL (x);
-      if (!TREE_ASM_WRITTEN (exp))
+      tree decl = SYMBOL_REF_DECL (x);
+      if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
        {
          n_deferred_constants--;
          output_constant_def_contents (x);
@@ -4077,6 +3897,9 @@ constructor_static_from_elts_p (const_tree ctor)
          && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
 }
 
+static tree initializer_constant_valid_p_1 (tree value, tree endtype,
+                                           tree *cache);
+
 /* A subroutine of initializer_constant_valid_p.  VALUE is a MINUS_EXPR,
    PLUS_EXPR or POINTER_PLUS_EXPR.  This looks for cases of VALUE
    which are valid when ENDTYPE is an integer of any size; in
@@ -4086,7 +3909,7 @@ constructor_static_from_elts_p (const_tree ctor)
    returns NULL.  */
 
 static tree
-narrowing_initializer_constant_valid_p (tree value, tree endtype)
+narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
 {
   tree op0, op1;
 
@@ -4125,11 +3948,14 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
       op1 = inner;
     }
 
-  op0 = initializer_constant_valid_p (op0, endtype);
-  op1 = initializer_constant_valid_p (op1, endtype);
+  op0 = initializer_constant_valid_p_1 (op0, endtype, cache);
+  if (!op0)
+    return NULL_TREE;
 
+  op1 = initializer_constant_valid_p_1 (op1, endtype,
+                                       cache ? cache + 2 : NULL);
   /* Both initializers must be known.  */
-  if (op0 && op1)
+  if (op1)
     {
       if (op0 == op1
          && (op0 == null_pointer_node
@@ -4150,7 +3976,8 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
   return NULL_TREE;
 }
 
-/* Return nonzero if VALUE is a valid constant-valued expression
+/* Helper function of initializer_constant_valid_p.
+   Return nonzero if VALUE is a valid constant-valued expression
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
 
@@ -4158,10 +3985,12 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
    if it is relocatable, return the variable that determines the relocation.
    We assume that VALUE has been folded as much as possible;
    therefore, we do not need to check for such things as
-   arithmetic-combinations of integers.  */
+   arithmetic-combinations of integers.
 
-tree
-initializer_constant_valid_p (tree value, tree endtype)
+   Use CACHE (pointer to 2 tree values) for caching if non-NULL.  */
+
+static tree
+initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
 {
   tree ret;
 
@@ -4174,18 +4003,33 @@ initializer_constant_valid_p (tree value, tree endtype)
          tree elt;
          bool absolute = true;
 
+         if (cache && cache[0] == value)
+           return cache[1];
          FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
            {
              tree reloc;
-             reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
+             reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
+                                                     NULL);
              if (!reloc)
-               return NULL_TREE;
+               {
+                 if (cache)
+                   {
+                     cache[0] = value;
+                     cache[1] = NULL_TREE;
+                   }
+                 return NULL_TREE;
+               }
              if (reloc != null_pointer_node)
                absolute = false;
            }
          /* For a non-absolute relocation, there is no single
             variable that can be "the variable that determines the
             relocation."  */
+         if (cache)
+           {
+             cache[0] = value;
+             cache[1] = absolute ? null_pointer_node : error_mark_node;
+           }
          return absolute ? null_pointer_node : error_mark_node;
        }
 
@@ -4213,8 +4057,7 @@ initializer_constant_valid_p (tree value, tree endtype)
            /* Taking the address of a nested function involves a trampoline,
               unless we don't need or want one.  */
            if (TREE_CODE (op0) == FUNCTION_DECL
-               && decl_function_context (op0)
-               && !DECL_NO_STATIC_CHAIN (op0)
+               && DECL_STATIC_CHAIN (op0)
                && !TREE_NO_TRAMPOLINE (value))
              return NULL_TREE;
            /* "&{...}" requires a temporary to hold the constructed
@@ -4226,7 +4069,8 @@ initializer_constant_valid_p (tree value, tree endtype)
       }
 
     case NON_LVALUE_EXPR:
-      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+      return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+                                            endtype, cache);
 
     case VIEW_CONVERT_EXPR:
       {
@@ -4241,13 +4085,13 @@ initializer_constant_valid_p (tree value, tree endtype)
        if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type))
          {
            if (TYPE_MODE (endtype) == TYPE_MODE (dest_type))
-             return initializer_constant_valid_p (src, endtype);
+             return initializer_constant_valid_p_1 (src, endtype, cache);
            else
              return NULL_TREE;
          }
 
        /* Allow all other kinds of view-conversion.  */
-       return initializer_constant_valid_p (src, endtype);
+       return initializer_constant_valid_p_1 (src, endtype, cache);
       }
 
     CASE_CONVERT:
@@ -4262,18 +4106,18 @@ initializer_constant_valid_p (tree value, tree endtype)
            || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
            || (TREE_CODE (dest_type) == OFFSET_TYPE
                && TREE_CODE (src_type) == OFFSET_TYPE))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Allow length-preserving conversions between integer types.  */
        if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
            && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Allow conversions between other integer types only if
           explicit value.  */
        if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
          {
-           tree inner = initializer_constant_valid_p (src, endtype);
+           tree inner = initializer_constant_valid_p_1 (src, endtype, cache);
            if (inner == null_pointer_node)
              return null_pointer_node;
            break;
@@ -4282,7 +4126,7 @@ initializer_constant_valid_p (tree value, tree endtype)
        /* Allow (int) &foo provided int is as wide as a pointer.  */
        if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
            && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
 
        /* Likewise conversions from int to pointers, but also allow
           conversions from 0.  */
@@ -4296,77 +4140,119 @@ initializer_constant_valid_p (tree value, tree endtype)
            if (integer_zerop (src))
              return null_pointer_node;
            else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
-             return initializer_constant_valid_p (src, endtype);
+             return initializer_constant_valid_p_1 (src, endtype, cache);
          }
 
        /* Allow conversions to struct or union types if the value
           inside is okay.  */
        if (TREE_CODE (dest_type) == RECORD_TYPE
            || TREE_CODE (dest_type) == UNION_TYPE)
-         return initializer_constant_valid_p (src, endtype);
+         return initializer_constant_valid_p_1 (src, endtype, cache);
       }
       break;
 
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
+      /* Any valid floating-point constants will have been folded by now;
+        with -frounding-math we hit this with addition of two constants.  */
+      if (TREE_CODE (endtype) == REAL_TYPE)
+       return NULL_TREE;
+      if (cache && cache[0] == value)
+       return cache[1];
       if (! INTEGRAL_TYPE_P (endtype)
-         || TYPE_PRECISION (endtype) >= 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);
          /* If either term is absolute, use the other term's relocation.  */
          if (valid0 == null_pointer_node)
-           return valid1;
-         if (valid1 == null_pointer_node)
-           return valid0;
+           ret = valid1;
+         else if (valid1 == null_pointer_node)
+           ret = valid0;
+         /* Support narrowing pointer differences.  */
+         else
+           ret = narrowing_initializer_constant_valid_p (value, endtype,
+                                                         ncache);
        }
-
+      else
       /* Support narrowing pointer differences.  */
-      ret = narrowing_initializer_constant_valid_p (value, endtype);
-      if (ret != NULL_TREE)
-       return ret;
-
-      break;
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
+       {
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
     case MINUS_EXPR:
+      if (TREE_CODE (endtype) == REAL_TYPE)
+       return NULL_TREE;
+      if (cache && cache[0] == value)
+       return cache[1];
       if (! INTEGRAL_TYPE_P (endtype)
-         || TYPE_PRECISION (endtype) >= 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)
-           return valid0;
+           ret = valid0;
          /* Win if both arguments have the same relocation.
             Then the value is absolute.  */
-         if (valid0 == valid1 && valid0 != 0)
-           return null_pointer_node;
-
+         else if (valid0 == valid1 && valid0 != 0)
+           ret = null_pointer_node;
          /* Since GCC guarantees that string constants are unique in the
             generated code, a subtraction between two copies of the same
             constant string is absolute.  */
-         if (valid0 && TREE_CODE (valid0) == STRING_CST
-             && valid1 && TREE_CODE (valid1) == STRING_CST
-             && operand_equal_p (valid0, valid1, 1))
-           return null_pointer_node;
+         else if (valid0 && TREE_CODE (valid0) == STRING_CST
+                  && valid1 && TREE_CODE (valid1) == STRING_CST
+                  && operand_equal_p (valid0, valid1, 1))
+           ret = null_pointer_node;
+         /* Support narrowing differences.  */
+         else
+           ret = narrowing_initializer_constant_valid_p (value, endtype,
+                                                         ncache);
        }
-
-      /* Support narrowing differences.  */
-      ret = narrowing_initializer_constant_valid_p (value, endtype);
-      if (ret != NULL_TREE)
-       return ret;
-
-      break;
+      else
+       /* Support narrowing differences.  */
+       ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+      if (cache)
+       {
+         cache[0] = value;
+         cache[1] = ret;
+       }
+      return ret;
 
     default:
       break;
     }
 
-  return 0;
+  return NULL_TREE;
+}
+
+/* Return nonzero if VALUE is a valid constant-valued expression
+   for use in initializing a static variable; one that can be an
+   element of a "constant" initializer.
+
+   Return null_pointer_node if the value is absolute;
+   if it is relocatable, return the variable that determines the relocation.
+   We assume that VALUE has been folded as much as possible;
+   therefore, we do not need to check for such things as
+   arithmetic-combinations of integers.  */
+tree
+initializer_constant_valid_p (tree value, tree endtype)
+{
+  return initializer_constant_valid_p_1 (value, endtype, NULL);
 }
 \f
 /* Return true if VALUE is a valid constant-valued expression
@@ -4453,7 +4339,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))
-      && 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);
 
@@ -4461,7 +4349,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))
-            && 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
@@ -4473,7 +4363,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
       else if (TREE_CODE (exp) == INTEGER_CST)
        exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
                                  TREE_INT_CST_HIGH (exp));
-      
+
     }
 
   /* Eliminate any conversions since we'll be outputting the underlying
@@ -4541,8 +4431,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case REAL_TYPE:
       if (TREE_CODE (exp) != REAL_CST)
        error ("initializer for floating value is not a floating constant");
-
-      assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
+      else
+       assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
       break;
 
     case COMPLEX_TYPE:
@@ -4642,7 +4532,7 @@ array_size_for_constructor (tree val)
   tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
   i = size_binop (MINUS_EXPR, fold_convert (sizetype, max_index),
                  fold_convert (sizetype, tmp));
-  i = size_binop (PLUS_EXPR, i, build_int_cst (sizetype, 1));
+  i = size_binop (PLUS_EXPR, i, size_one_node);
 
   /* Multiply by the array element unit size to find number of bytes.  */
   i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
@@ -4697,7 +4587,7 @@ output_constructor_array_range (oc_local_state *local)
 
   unsigned int align2
     = min_align (local->align, fieldsize * BITS_PER_UNIT);
-  
+
   for (index = lo_index; index <= hi_index; index++)
     {
       /* Output the element's initial value.  */
@@ -4705,7 +4595,7 @@ output_constructor_array_range (oc_local_state *local)
        assemble_zeros (fieldsize);
       else
        output_constant (local->val, fieldsize, align2);
-      
+
       /* Count its size.  */
       local->total_bytes += fieldsize;
     }
@@ -4726,12 +4616,12 @@ output_constructor_regular_field (oc_local_state *local)
 
   if (local->index != NULL_TREE)
     fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
-               * ((tree_low_cst (local->index, 0) 
+               * ((tree_low_cst (local->index, 0)
                    - tree_low_cst (local->min_index, 0))));
-  else if (local->field != NULL_TREE) 
+  else if (local->field != NULL_TREE)
     fieldpos = int_byte_position (local->field);
   else
-    fieldpos = 0; 
+    fieldpos = 0;
 
   /* Output any buffered-up bit-fields preceding this element.  */
   if (local->byte_buffer_in_use)
@@ -4740,7 +4630,7 @@ output_constructor_regular_field (oc_local_state *local)
       local->total_bytes++;
       local->byte_buffer_in_use = false;
     }
-  
+
   /* Advance to offset of this element.
      Note no alignment needed in an array, since that is guaranteed
      if each element has the proper size.  */
@@ -4751,7 +4641,7 @@ output_constructor_regular_field (oc_local_state *local)
       assemble_zeros (fieldpos - local->total_bytes);
       local->total_bytes = fieldpos;
     }
-  
+
   /* Find the alignment of this element.  */
   align2 = min_align (local->align, BITS_PER_UNIT * fieldpos);
 
@@ -4759,7 +4649,7 @@ output_constructor_regular_field (oc_local_state *local)
   if (local->field)
     {
       fieldsize = 0;
-      
+
       /* If this is an array with an unspecified upper bound,
         the initializer determines the size.  */
       /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
@@ -4772,7 +4662,7 @@ output_constructor_regular_field (oc_local_state *local)
          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));
+         gcc_assert (!fieldsize || !DECL_CHAIN (local->field));
        }
       else if (DECL_SIZE_UNIT (local->field))
        {
@@ -4784,7 +4674,7 @@ output_constructor_regular_field (oc_local_state *local)
     }
   else
     fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
-  
+
   /* Output the element's initial value.  */
   if (local->val == NULL_TREE)
     assemble_zeros (fieldsize);
@@ -4811,38 +4701,38 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
   HOST_WIDE_INT relative_index
     = (!local->field
        ? (local->index
-         ? (tree_low_cst (local->index, 0) 
+         ? (tree_low_cst (local->index, 0)
             - tree_low_cst (local->min_index, 0))
          : local->last_relative_index + 1)
        : 0);
-  
+
   /* Bit position of this element from the start of the containing
      constructor.  */
   HOST_WIDE_INT constructor_relative_ebitpos
       = (local->field
-        ? int_bit_position (local->field) 
+        ? int_bit_position (local->field)
         : ebitsize * relative_index);
-  
+
   /* Bit position of this element from the start of a possibly ongoing
      outer byte buffer.  */
   HOST_WIDE_INT byte_relative_ebitpos
       = ((outer ? outer->bit_offset : 0) + constructor_relative_ebitpos);
 
-  /* From the start of a possibly ongoing outer byte buffer, offsets to 
+  /* From the start of a possibly ongoing outer byte buffer, offsets to
      the first bit of this element and to the first bit past the end of
      this element.  */
   HOST_WIDE_INT next_offset = byte_relative_ebitpos;
   HOST_WIDE_INT end_offset = byte_relative_ebitpos + ebitsize;
-  
+
   local->last_relative_index = relative_index;
-  
+
   if (local->val == NULL_TREE)
     local->val = integer_zero_node;
-  
+
   while (TREE_CODE (local->val) == VIEW_CONVERT_EXPR
         || TREE_CODE (local->val) == NON_LVALUE_EXPR)
     local->val = TREE_OPERAND (local->val, 0);
-    
+
   if (TREE_CODE (local->val) != INTEGER_CST
       && TREE_CODE (local->val) != CONSTRUCTOR)
     {
@@ -4861,7 +4751,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes++;
          local->byte_buffer_in_use = false;
        }
-      
+
       /* If still not at proper byte, advance to there.  */
       if (next_offset / BITS_PER_UNIT != local->total_bytes)
        {
@@ -4870,7 +4760,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes = next_offset / BITS_PER_UNIT;
        }
     }
-  
+
   /* Set up the buffer if necessary.  */
   if (!local->byte_buffer_in_use)
     {
@@ -4878,7 +4768,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       if (ebitsize > 0)
        local->byte_buffer_in_use = true;
     }
-  
+
   /* If this is nested constructor, recurse passing the bit offset and the
      pending data, then retrieve the new pending data afterwards.  */
   if (TREE_CODE (local->val) == CONSTRUCTOR)
@@ -4892,10 +4782,10 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       local->byte = output_state.byte;
       return;
     }
-  
+
   /* Otherwise, we must split the element into pieces that fall within
      separate bytes, and combine each byte with previous or following
-     bit-fields.  */  
+     bit-fields.  */
   while (next_offset < end_offset)
     {
       int this_time;
@@ -4903,7 +4793,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       HOST_WIDE_INT value;
       HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
       HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
-      
+
       /* Advance from byte to byte
         within this element when necessary.  */
       while (next_byte != local->total_bytes)
@@ -4912,7 +4802,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          local->total_bytes++;
          local->byte = 0;
        }
-      
+
       /* Number of bits we can process at once
         (all part of the same byte).  */
       this_time = MIN (end_offset - next_offset,
@@ -4923,7 +4813,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
             first (of the bits that are significant)
             and put them into bytes from the most significant end.  */
          shift = end_offset - next_offset - this_time;
-         
+
          /* Don't try to take a bunch of bits that cross
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
@@ -4934,7 +4824,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
              shift = HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Now get the bits from the appropriate constant word.  */
          if (shift < HOST_BITS_PER_WIDE_INT)
            value = TREE_INT_CST_LOW (local->val);
@@ -4944,7 +4834,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              value = TREE_INT_CST_HIGH (local->val);
              shift -= HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
          local->byte |= (((value >> shift)
@@ -4958,7 +4848,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
             and pack them starting at the least significant
             bits of the bytes.  */
          shift = next_offset - byte_relative_ebitpos;
-         
+
          /* Don't try to take a bunch of bits that cross
             the word boundary in the INTEGER_CST. We can
             only select bits from the LOW or HIGH part
@@ -4966,7 +4856,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          if (shift < HOST_BITS_PER_WIDE_INT
              && shift + this_time > HOST_BITS_PER_WIDE_INT)
            this_time = (HOST_BITS_PER_WIDE_INT - shift);
-         
+
          /* Now get the bits from the appropriate constant word.  */
          if (shift < HOST_BITS_PER_WIDE_INT)
            value = TREE_INT_CST_LOW (local->val);
@@ -4976,14 +4866,14 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
              value = TREE_INT_CST_HIGH (local->val);
              shift -= HOST_BITS_PER_WIDE_INT;
            }
-         
+
          /* Get the result. This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
          local->byte |= (((value >> shift)
                           & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
                          << next_bit);
        }
-      
+
       next_offset += this_time;
       local->byte_buffer_in_use = true;
     }
@@ -5019,7 +4909,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
   if (TREE_CODE (local.type) == ARRAY_TYPE
       && TYPE_DOMAIN (local.type) != NULL_TREE)
     local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
-  
+
   gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
 
   /* As CE goes through the elements of the constant, FIELD goes through the
@@ -5037,7 +4927,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
 
   for (cnt = 0;
        VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
-       cnt++, local.field = local.field ? TREE_CHAIN (local.field) : 0)
+       cnt++, local.field = local.field ? DECL_CHAIN (local.field) : 0)
     {
       local.val = ce->value;
       local.index = NULL_TREE;
@@ -5080,7 +4970,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
               && (local.field == NULL_TREE
                   || !CONSTRUCTOR_BITFIELD_P (local.field)))
        output_constructor_regular_field (&local);
-      
+
       /* For a true bitfield or part of an outer one.  */
       else
        output_constructor_bitfield (&local, outer);
@@ -5104,7 +4994,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
          local.total_bytes = local.size;
        }
     }
-      
+
   return local.total_bytes;
 }
 
@@ -5204,6 +5094,9 @@ declare_weak (tree decl)
     warning (0, "weak declaration of %q+D not supported", decl);
 
   mark_weak (decl);
+  if (!lookup_attribute ("weak", DECL_ATTRIBUTES (decl)))
+    DECL_ATTRIBUTES (decl)
+      = tree_cons (get_identifier ("weak"), NULL, DECL_ATTRIBUTES (decl));
 }
 
 static void
@@ -5402,6 +5295,7 @@ find_decl_and_mark_needed (tree decl, tree target)
   else if (vnode)
     {
       varpool_mark_needed_node (vnode);
+      vnode->force_output = 1;
       return vnode->decl;
     }
   else
@@ -5415,9 +5309,18 @@ find_decl_and_mark_needed (tree decl, tree target)
 static void
 do_assemble_alias (tree decl, tree target)
 {
+  /* Emulated TLS had better not get this var.  */
+  gcc_assert(!(!targetm.have_tls
+              && TREE_CODE (decl) == VAR_DECL
+              && DECL_THREAD_LOCAL_P (decl)));
+
   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;
 
@@ -5425,14 +5328,6 @@ do_assemble_alias (tree decl, tree target)
     {
       ultimate_transparent_alias_target (&target);
 
-      if (!targetm.have_tls
-         && TREE_CODE (decl) == VAR_DECL
-         && DECL_THREAD_LOCAL_P (decl))
-       {
-         decl = emutls_decl (decl);
-         target = get_emutls_object_name (target);
-       }
-
       if (!TREE_SYMBOL_REFERENCED (target))
        weakref_targets = tree_cons (decl, target, weakref_targets);
 
@@ -5451,14 +5346,6 @@ do_assemble_alias (tree decl, tree target)
       return;
     }
 
-  if (!targetm.have_tls
-      && TREE_CODE (decl) == VAR_DECL
-      && DECL_THREAD_LOCAL_P (decl))
-    {
-      decl = emutls_decl (decl);
-      target = get_emutls_object_name (target);
-    }
-
 #ifdef ASM_OUTPUT_DEF
   /* Make name accessible from other files, if appropriate.  */
 
@@ -5635,10 +5522,6 @@ assemble_alias (tree decl, tree target)
 # endif
 #endif
     }
-
-  /* We must force creation of DECL_RTL for debug info generation, even though
-     we don't use it here.  */
-  make_decl_rtl (decl);
   TREE_USED (decl) = 1;
 
   /* A quirk of the initial implementation of aliases required that the user
@@ -5673,8 +5556,10 @@ assemble_alias (tree decl, tree target)
    the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
 
 void
-default_assemble_visibility (tree decl, int vis)
+default_assemble_visibility (tree decl ATTRIBUTE_UNUSED, 
+                            int vis ATTRIBUTE_UNUSED)
 {
+#ifdef HAVE_GAS_HIDDEN
   static const char * const visibility_types[] = {
     NULL, "protected", "hidden", "internal"
   };
@@ -5684,7 +5569,6 @@ default_assemble_visibility (tree decl, int vis)
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   type = visibility_types[vis];
 
-#ifdef HAVE_GAS_HIDDEN
   fprintf (asm_out_file, "\t.%s\t", type);
   assemble_name (asm_out_file, name);
   fprintf (asm_out_file, "\n");
@@ -5703,7 +5587,7 @@ maybe_assemble_visibility (tree decl)
 
   if (vis != VISIBILITY_DEFAULT)
     {
-      targetm.asm_out.visibility (decl, vis);
+      targetm.asm_out.assemble_visibility (decl, vis);
       return 1;
     }
   else
@@ -5940,6 +5824,10 @@ default_no_named_section (const char *name ATTRIBUTE_UNUSED,
   gcc_unreachable ();
 }
 
+#ifndef TLS_SECTION_ASM_FLAG
+#define TLS_SECTION_ASM_FLAG 'T'
+#endif
+
 void
 default_elf_asm_named_section (const char *name, unsigned int flags,
                               tree decl ATTRIBUTE_UNUSED)
@@ -5970,7 +5858,7 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
   if (flags & SECTION_STRINGS)
     *f++ = 'S';
   if (flags & SECTION_TLS)
-    *f++ = 'T';
+    *f++ = TLS_SECTION_ASM_FLAG;
   if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
     *f++ = 'G';
   *f = '\0';
@@ -5999,8 +5887,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))
-       fprintf (asm_out_file, ",%s,comdat",
-                IDENTIFIER_POINTER (DECL_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);
@@ -6120,24 +6013,11 @@ categorize_decl_for_section (const_tree decl, int reloc)
     ret = SECCAT_RODATA;
 
   /* There are no read-only thread-local sections.  */
-  if (TREE_CODE (decl) == VAR_DECL && DECL_TLS_MODEL (decl))
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (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.  */
-      else if (ret == SECCAT_BSS
+      if (ret == SECCAT_BSS
               || (flag_zero_initialized_in_bss
                   && initializer_zerop (DECL_INITIAL (decl))))
        ret = SECCAT_TBSS;
@@ -6231,12 +6111,6 @@ default_elf_select_section (tree decl, int reloc,
     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 ();
     }
@@ -6301,12 +6175,6 @@ default_unique_section (tree decl, int reloc)
     case SECCAT_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 ();
     }
@@ -6317,7 +6185,7 @@ default_unique_section (tree decl, int reloc)
   /* If we're using one_only, then there needs to be a .gnu.linkonce
      prefix to the section name.  */
   linkonce = one_only ? ".gnu.linkonce" : "";
-  
+
   string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
   DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
@@ -6417,8 +6285,7 @@ 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;
-  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)
-      && DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED)
+  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
     flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
   else if (targetm.in_small_data_p (decl))
     flags |= SYMBOL_FLAG_SMALL;
@@ -6552,14 +6419,6 @@ default_binds_local_p_1 (const_tree exp, int shlib)
   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.  */
@@ -6612,16 +6471,27 @@ default_internal_label (FILE *stream, const char *prefix,
   ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
 }
 
+
+/* The default implementation of ASM_DECLARE_CONSTANT_NAME.  */
+
+void
+default_asm_declare_constant_name (FILE *file, const char *name,
+                                  const_tree exp ATTRIBUTE_UNUSED,
+                                  HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+  assemble_label (file, name);
+}
+
 /* This is the default behavior at the beginning of a file.  It's
    controlled by two other target-hook toggles.  */
 void
 default_file_start (void)
 {
-  if (targetm.file_start_app_off
+  if (targetm.asm_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)
+  if (targetm.asm_file_start_file_directive)
     output_file_directive (asm_out_file, main_input_filename);
 }
 
@@ -6717,8 +6587,8 @@ place_block_symbol (rtx symbol)
   else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
     {
       decl = SYMBOL_REF_DECL (symbol);
-      alignment = get_constant_alignment (decl);
-      size = get_constant_size (decl);
+      alignment = DECL_ALIGN (decl);
+      size = get_constant_size (DECL_INITIAL (decl));
     }
   else
     {
@@ -6864,9 +6734,9 @@ output_object_block (struct object_block *block)
       else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
        {
          decl = SYMBOL_REF_DECL (symbol);
-         assemble_constant_contents (decl, XSTR (symbol, 0),
-                                     get_constant_alignment (decl));
-         offset += get_constant_size (decl);
+         assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
+                                     DECL_ALIGN (decl));
+         offset += get_constant_size (DECL_INITIAL (decl));
        }
       else
        {
@@ -6911,50 +6781,11 @@ output_object_blocks (void)
 int
 elf_record_gcc_switches (print_switch_type type, const char * name)
 {
-  static char buffer[1024];
-
-  /* This variable is used as part of a simplistic heuristic to detect
-     command line switches which take an argument:
-
-       "If a command line option does not start with a dash then
-        it is an argument for the previous command line option."
-
-     This fails in the case of the command line option which is the name
-     of the file to compile, but otherwise it is pretty reasonable.  */
-  static bool previous_name_held_back = FALSE;
-
   switch (type)
     {
     case SWITCH_TYPE_PASSED:
-      if (* name != '-')
-       {
-         if (previous_name_held_back)
-           {
-             unsigned int len = strlen (buffer);
-
-             snprintf (buffer + len, sizeof buffer - len, " %s", name);
-             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
-             ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1);
-             previous_name_held_back = FALSE;
-           }
-         else
-           {
-             strncpy (buffer, name, sizeof buffer);
-             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
-             ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1);
-           }
-       }
-      else
-       {
-         if (previous_name_held_back)
-           {
-             ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
-             ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1);
-           }
-
-         strncpy (buffer, name, sizeof buffer);
-         previous_name_held_back = TRUE;
-       }
+      ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name));
+      ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1);
       break;
 
     case SWITCH_TYPE_DESCRIPTIVE:
@@ -6963,15 +6794,7 @@ elf_record_gcc_switches (print_switch_type type, const char * name)
          /* Distinguish between invocations where name is NULL.  */
          static bool started = false;
 
-         if (started)
-           {
-             if (previous_name_held_back)
-               {
-                 ASM_OUTPUT_ASCII (asm_out_file, buffer, strlen (buffer));
-                 ASM_OUTPUT_SKIP (asm_out_file, (unsigned HOST_WIDE_INT) 1);
-               }
-           }
-         else
+         if (!started)
            {
              section * sec;
 
@@ -7011,4 +6834,72 @@ default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
     maybe_assemble_visibility (decl);
 }
 
+/* The default hook for TARGET_ASM_OUTPUT_SOURCE_FILENAME.  */
+
+void
+default_asm_output_source_filename (FILE *file, const char *name)
+{
+#ifdef ASM_OUTPUT_SOURCE_FILENAME
+  ASM_OUTPUT_SOURCE_FILENAME (file, name);
+#else
+  fprintf (file, "\t.file\t");
+  output_quoted_string (file, name);
+  putc ('\n', file);
+#endif
+}
+
+/* Output a file name in the form wanted by System V.  */
+
+void
+output_file_directive (FILE *asm_file, const char *input_name)
+{
+  int len;
+  const char *na;
+
+  if (input_name == NULL)
+    input_name = "<stdin>";
+  else
+    input_name = remap_debug_filename (input_name);
+
+  len = strlen (input_name);
+  na = input_name + len;
+
+  /* NA gets INPUT_NAME sans directory names.  */
+  while (na > input_name)
+    {
+      if (IS_DIR_SEPARATOR (na[-1]))
+       break;
+      na--;
+    }
+
+  targetm.asm_out.output_source_filename (asm_file, na);
+}
+
+/* Create a DEBUG_EXPR_DECL / DEBUG_EXPR pair from RTL expression
+   EXP.  */
+rtx
+make_debug_expr_from_rtl (const_rtx exp)
+{
+  tree ddecl = make_node (DEBUG_EXPR_DECL), type;
+  enum machine_mode mode = GET_MODE (exp);
+  rtx dval;
+
+  DECL_ARTIFICIAL (ddecl) = 1;
+  if (REG_P (exp) && REG_EXPR (exp))
+    type = TREE_TYPE (REG_EXPR (exp));
+  else if (MEM_P (exp) && MEM_EXPR (exp))
+    type = TREE_TYPE (MEM_EXPR (exp));
+  else
+    type = NULL_TREE;
+  if (type && TYPE_MODE (type) == mode)
+    TREE_TYPE (ddecl) = type;
+  else
+    TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
+  DECL_MODE (ddecl) = mode;
+  dval = gen_rtx_DEBUG_EXPR (mode);
+  DEBUG_EXPR_TREE_DECL (dval) = ddecl;
+  SET_DECL_RTL (ddecl, dval);
+  return dval;
+}
+
 #include "gt-varasm.h"