ipa-cp.c (ipcp_cloning_candidate_p): Use opt_for_fn.
[gcc.git] / gcc / varasm.c
index ee42afc8cbdcec0fd98024408672e8966af2cc57..54611f8fd3f17a035eb3befbc606a6ce311fc7de 100644 (file)
@@ -1,7 +1,5 @@
 /* Output variables, constants and external declarations, for GNU compiler.
-   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012  Free Software Foundation, Inc.
+   Copyright (C) 1987-2014 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -33,14 +31,21 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "stor-layout.h"
+#include "stringpool.h"
+#include "varasm.h"
 #include "flags.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
 #include "function.h"
 #include "expr.h"
-#include "hard-reg-set.h"
 #include "regs.h"
 #include "output.h"
 #include "diagnostic-core.h"
-#include "hashtab.h"
 #include "ggc.h"
 #include "langhooks.h"
 #include "tm_p.h"
@@ -48,10 +53,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "common/common-target.h"
 #include "targhooks.h"
-#include "tree-mudflap.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "basic-block.h"
+#include "hash-map.h"
+#include "is-a.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
 #include "cgraph.h"
-#include "pointer-set.h"
 #include "asan.h"
+#include "rtl-iter.h"
+#include "tree-chkp.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"          /* Needed for external data
@@ -93,11 +106,6 @@ tree last_assemble_variable_decl;
 
 bool first_function_block_is_cold;
 
-/* We give all constants their own alias set.  Perhaps redundant with
-   MEM_READONLY_P, but pre-dates it.  */
-
-static alias_set_type const_alias_set;
-
 /* Whether we saw any functions with no_split_stack.  */
 
 static bool saw_no_split_stack;
@@ -108,15 +116,12 @@ static int contains_pointers_p (tree);
 static bool incorporeal_function_p (tree);
 #endif
 static void decode_addr_const (tree, struct addr_const *);
-static hashval_t const_desc_hash (const void *);
-static int const_desc_eq (const void *, const void *);
 static hashval_t const_hash_1 (const tree);
 static int compare_constant (const tree, const tree);
-static tree copy_constant (tree);
 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 unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
+                                              unsigned int);
 static void globalize_decl (tree);
 static bool decl_readonly_section_1 (enum section_category);
 #ifdef BSS_SECTION_ASM_OP
@@ -172,13 +177,29 @@ static GTY(()) section *unnamed_sections;
 /* Return a nonzero value if DECL has a section attribute.  */
 #define IN_NAMED_SECTION(DECL) \
   ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
-   && DECL_SECTION_NAME (DECL) != NULL_TREE)
+   && DECL_SECTION_NAME (DECL) != NULL)
+
+struct section_hasher : ggc_hasher<section *>
+{
+  typedef const char *compare_type;
+
+  static hashval_t hash (section *);
+  static bool equal (section *, const char *);
+};
 
 /* Hash table of named sections.  */
-static GTY((param_is (section))) htab_t section_htab;
+static GTY(()) hash_table<section_hasher> *section_htab;
+
+struct object_block_hasher : ggc_hasher<object_block *>
+{
+  typedef const section *compare_type;
+
+  static hashval_t hash (object_block *);
+  static bool equal (object_block *, const section *);
+};
 
 /* A table of object_blocks, indexed by section.  */
-static GTY((param_is (struct object_block))) htab_t object_block_htab;
+static GTY(()) hash_table<object_block_hasher> *object_block_htab;
 
 /* The next number to use for internal anchor labels.  */
 static GTY(()) int anchor_labelno;
@@ -188,19 +209,15 @@ static GTY(()) struct rtx_constant_pool *shared_constant_pool;
 
 /* Helper routines for maintaining section_htab.  */
 
-static int
-section_entry_eq (const void *p1, const void *p2)
+bool
+section_hasher::equal (section *old, const char *new_name)
 {
-  const section *old = (const section *) p1;
-  const char *new_name = (const char *) p2;
-
   return strcmp (old->named.name, new_name) == 0;
 }
 
-static hashval_t
-section_entry_hash (const void *p)
+hashval_t
+section_hasher::hash (section *old)
 {
-  const section *old = (const section *) p;
   return htab_hash_string (old->named.name);
 }
 
@@ -216,19 +233,15 @@ hash_section (section *sect)
 
 /* Helper routines for maintaining object_block_htab.  */
 
-static int
-object_block_entry_eq (const void *p1, const void *p2)
+inline bool
+object_block_hasher::equal (object_block *old, const section *new_section)
 {
-  const struct object_block *old = (const struct object_block *) p1;
-  const section *new_section = (const section *) p2;
-
   return old->sect == new_section;
 }
 
-static hashval_t
-object_block_entry_hash (const void *p)
+hashval_t
+object_block_hasher::hash (object_block *old)
 {
-  const struct object_block *old = (const struct object_block *) p;
   return hash_section (old->sect);
 }
 
@@ -240,7 +253,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
 {
   section *sect;
 
-  sect = ggc_alloc_section ();
+  sect = ggc_alloc<section> ();
   sect->unnamed.common.flags = flags | SECTION_UNNAMED;
   sect->unnamed.callback = callback;
   sect->unnamed.data = data;
@@ -257,7 +270,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
 {
   section *sect;
 
-  sect = ggc_alloc_section ();
+  sect = ggc_alloc<section> ();
   sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
   sect->noswitch.callback = callback;
 
@@ -272,13 +285,12 @@ get_section (const char *name, unsigned int flags, tree decl)
 {
   section *sect, **slot;
 
-  slot = (section **)
-    htab_find_slot_with_hash (section_htab, name,
-                             htab_hash_string (name), INSERT);
+  slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
+                                           INSERT);
   flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
-      sect = ggc_alloc_section ();
+      sect = ggc_alloc<section> ();
       sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
@@ -309,19 +321,22 @@ get_section (const char *name, unsigned int flags, tree decl)
              return sect;
            }
          /* Sanity check user variables for flag changes.  */
-         if (decl == 0)
-           decl = sect->named.decl;
-         gcc_assert (decl);
-         if (sect->named.decl == NULL)
-           error ("%+D causes a section type conflict", decl);
-         else
+         if (sect->named.decl != NULL
+             && DECL_P (sect->named.decl)
+             && decl != sect->named.decl)
            {
-             error ("%+D causes a section type conflict with %D",
-                    decl, sect->named.decl);
-             if (decl != sect->named.decl)
-               inform (DECL_SOURCE_LOCATION (sect->named.decl),
-                       "%qD was declared here", sect->named.decl);
+             if (decl != NULL && DECL_P (decl))
+               error ("%+D causes a section type conflict with %D",
+                      decl, sect->named.decl);
+             else
+               error ("section type conflict with %D", sect->named.decl);
+             inform (DECL_SOURCE_LOCATION (sect->named.decl),
+                     "%qD was declared here", sect->named.decl);
            }
+         else if (decl != NULL && DECL_P (decl))
+           error ("%+D causes a section type conflict", decl);
+         else
+           error ("section type conflict");
          /* Make sure we don't error about one section multiple times.  */
          sect->common.flags |= SECTION_OVERRIDE;
        }
@@ -346,17 +361,17 @@ static struct object_block *
 get_block_for_section (section *sect)
 {
   struct object_block *block;
-  void **slot;
 
   if (sect == NULL)
     return NULL;
 
-  slot = htab_find_slot_with_hash (object_block_htab, sect,
-                                  hash_section (sect), INSERT);
-  block = (struct object_block *) *slot;
+  object_block **slot
+    = object_block_htab->find_slot_with_hash (sect, hash_section (sect),
+                                             INSERT);
+  block = *slot;
   if (block == NULL)
     {
-      block = ggc_alloc_cleared_object_block ();
+      block = ggc_cleared_alloc<object_block> ();
       block->sect = sect;
       *slot = block;
     }
@@ -376,7 +391,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 = ggc_alloc_zone_rtx_def (size, &rtl_zone);
+  symbol = (rtx) ggc_internal_alloc (size);
 
   /* Initialize the normal SYMBOL_REF fields.  */
   memset (symbol, 0, size);
@@ -404,28 +419,40 @@ get_named_section (tree decl, const char *name, int reloc)
 {
   unsigned int flags;
 
-  gcc_assert (!decl || DECL_P (decl));
   if (name == NULL)
-    name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+    {
+      gcc_assert (decl && DECL_P (decl) && DECL_SECTION_NAME (decl));
+      name = DECL_SECTION_NAME (decl);
+    }
 
   flags = targetm.section_type_flags (decl, name, reloc);
-
   return get_section (name, flags, decl);
 }
 
+/* Worker for resolve_unique_section.  */
+
+static bool
+set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED)
+{
+  n->implicit_section = true;
+  return false;
+}
+
 /* If required, set DECL_SECTION_NAME to a unique name.  */
 
 void
 resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
                        int flag_function_or_data_sections)
 {
-  if (DECL_SECTION_NAME (decl) == NULL_TREE
+  if (DECL_SECTION_NAME (decl) == NULL
       && targetm_common.have_named_sections
       && (flag_function_or_data_sections
-         || DECL_ONE_ONLY (decl)))
+         || DECL_COMDAT_GROUP (decl)))
     {
       targetm.asm_out.unique_section (decl, reloc);
-      DECL_HAS_IMPLICIT_SECTION_NAME_P (decl) = true;
+      if (DECL_SECTION_NAME (decl))
+       symtab_node::get (decl)->call_for_symbol_and_aliases
+         (set_implicit_section, NULL, true);
     }
 }
 
@@ -467,7 +494,7 @@ static section *
 hot_function_section (tree decl)
 {
   if (decl != NULL_TREE
-      && DECL_SECTION_NAME (decl) != NULL_TREE
+      && DECL_SECTION_NAME (decl) != NULL
       && targetm_common.have_named_sections)
     return get_named_section (decl, NULL, 0);
   else
@@ -492,26 +519,26 @@ get_named_text_section (tree decl,
     {
       if (named_section_suffix)
        {
-         tree dsn = DECL_SECTION_NAME (decl);
+         const char *dsn = DECL_SECTION_NAME (decl);
          const char *stripped_name;
          char *name, *buffer;
 
-         name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1);
-         memcpy (name, TREE_STRING_POINTER (dsn),
-                 TREE_STRING_LENGTH (dsn) + 1);
+         name = (char *) alloca (strlen (dsn) + 1);
+         memcpy (name, dsn,
+                 strlen (dsn) + 1);
 
          stripped_name = targetm.strip_name_encoding (name);
 
          buffer = ACONCAT ((stripped_name, named_section_suffix, NULL));
          return get_named_section (decl, buffer, 0);
        }
-      else if (DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+      else if (symtab_node::get (decl)->implicit_section)
        {
          const char *name;
 
          /* Do not try to split gnu_linkonce functions.  This gets somewhat
             slipperly.  */
-         if (DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP)
+         if (DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP)
            return NULL;
          name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
          name = targetm.strip_name_encoding (name);
@@ -534,8 +561,7 @@ default_function_section (tree decl, enum node_frequency freq,
   /* Old GNU linkers have buggy --gc-section support, which sometimes
      results in .gcc_except_table* sections being garbage collected.  */
   if (decl
-      && DECL_SECTION_NAME (decl)
-      && DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
+      && symtab_node::get (decl)->implicit_section)
     return NULL;
 #endif
 
@@ -546,7 +572,14 @@ default_function_section (tree decl, enum node_frequency freq,
      unlikely executed (this happens especially with function splitting
      where we can split away unnecessary parts of static constructors.  */
   if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
-    return get_named_text_section (decl, ".text.startup", NULL);
+  {
+    /* If we do have a profile or(and) LTO phase is executed, we do not need
+       these ELF section.  */
+    if (!in_lto_p || !flag_profile_values)
+      return get_named_text_section (decl, ".text.startup", NULL);
+    else
+      return NULL;
+  }
 
   /* Similarly for exit.  */
   if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
@@ -558,7 +591,10 @@ default_function_section (tree decl, enum node_frequency freq,
       case NODE_FREQUENCY_UNLIKELY_EXECUTED:
        return get_named_text_section (decl, ".text.unlikely", NULL);
       case NODE_FREQUENCY_HOT:
-       return get_named_text_section (decl, ".text.hot", NULL);
+        /* If we do have a profile or(and) LTO phase is executed, we do not need
+           these ELF section.  */
+        if (!in_lto_p || !flag_profile_values)
+          return get_named_text_section (decl, ".text.hot", NULL);
       default:
        return NULL;
     }
@@ -581,7 +617,7 @@ function_section_1 (tree decl, bool force_cold)
 
   if (decl)
     {
-      struct cgraph_node *node = cgraph_get_node (decl);
+      struct cgraph_node *node = cgraph_node::get (decl);
 
       if (node)
        {
@@ -595,7 +631,7 @@ function_section_1 (tree decl, bool force_cold)
 
 #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
   if (decl != NULL_TREE
-      && DECL_SECTION_NAME (decl) != NULL_TREE)
+      && DECL_SECTION_NAME (decl) != NULL)
     {
       if (targetm.asm_out.function_section)
        section = targetm.asm_out.function_section (decl, freq,
@@ -669,9 +705,9 @@ default_function_rodata_section (tree decl)
 {
   if (decl != NULL_TREE && DECL_SECTION_NAME (decl))
     {
-      const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+      const char *name = DECL_SECTION_NAME (decl);
 
-      if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
+      if (DECL_COMDAT_GROUP (decl) && HAVE_COMDAT_GROUP)
         {
          const char *dot;
          size_t len;
@@ -688,7 +724,7 @@ default_function_rodata_section (tree decl)
          return get_section (rname, SECTION_LINKONCE, decl);
        }
       /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo.  */
-      else if (DECL_ONE_ONLY (decl)
+      else if (DECL_COMDAT_GROUP (decl)
               && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
        {
          size_t len = strlen (name) + 1;
@@ -740,7 +776,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
       && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
       && TREE_STRING_LENGTH (decl) >= len)
     {
-      enum machine_mode mode;
+      machine_mode mode;
       unsigned int modesize;
       const char *str;
       HOST_WIDE_INT i;
@@ -784,7 +820,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
 /* Return the section to use for constant merging.  */
 
 section *
-mergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED,
+mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
                            unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
                            unsigned int flags ATTRIBUTE_UNUSED)
 {
@@ -831,7 +867,7 @@ set_user_assembler_name (tree decl, const char *name)
   char *starred = (char *) alloca (strlen (name) + 2);
   starred[0] = '*';
   strcpy (starred + 1, name);
-  change_decl_assembler_name (decl, get_identifier (starred));
+  symtab->change_decl_assembler_name (decl, get_identifier (starred));
   SET_DECL_RTL (decl, NULL_RTX);
 }
 \f
@@ -863,7 +899,7 @@ decode_reg_name_and_count (const char *asmspec, int *pnregs)
       if (asmspec[0] != 0 && i < 0)
        {
          i = atoi (asmspec);
-         if (i < FIRST_PSEUDO_REGISTER && i >= 0)
+         if (i < FIRST_PSEUDO_REGISTER && i >= 0 && reg_names[i][0])
            return i;
          else
            return -2;
@@ -900,7 +936,8 @@ decode_reg_name_and_count (const char *asmspec, int *pnregs)
 
        for (i = 0; i < (int) ARRAY_SIZE (table); i++)
          if (table[i].name[0]
-             && ! strcmp (asmspec, table[i].name))
+             && ! strcmp (asmspec, table[i].name)
+             && reg_names[table[i].number][0])
            return table[i].number;
       }
 #endif /* ADDITIONAL_REGISTER_NAMES */
@@ -927,11 +964,14 @@ decode_reg_name (const char *name)
 \f
 /* Return true if DECL's initializer is suitable for a BSS section.  */
 
-static bool
+bool
 bss_initializer_p (const_tree decl)
 {
   return (DECL_INITIAL (decl) == NULL
-         || DECL_INITIAL (decl) == error_mark_node
+         /* In LTO we have no errors in program; error_mark_node is used
+            to mark offlined constructors.  */
+         || (DECL_INITIAL (decl) == error_mark_node
+             && !in_lto_p)
          || (flag_zero_initialized_in_bss
              /* Leave constant zeroes in .rodata so they
                 can be shared.  */
@@ -958,24 +998,97 @@ align_variable (tree decl, bool dont_output_data)
      In particular, a.out format supports a maximum alignment of 4.  */
   if (align > MAX_OFILE_ALIGNMENT)
     {
-      warning (0, "alignment of %q+D is greater than maximum object "
-               "file alignment.  Using %d", decl,
-              MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
+      error ("alignment of %q+D is greater than maximum object "
+            "file alignment %d", decl,
+            MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
       align = MAX_OFILE_ALIGNMENT;
     }
 
-  /* On some machines, it is good to increase alignment sometimes.  */
   if (! DECL_USER_ALIGN (decl))
     {
+#ifdef DATA_ABI_ALIGNMENT
+      unsigned int data_abi_align
+       = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align);
+      /* For backwards compatibility, don't assume the ABI alignment for
+        TLS variables.  */
+      if (! DECL_THREAD_LOCAL_P (decl) || data_abi_align <= BITS_PER_WORD)
+       align = data_abi_align;
+#endif
+
+      /* On some machines, it is good to increase alignment sometimes.
+        But as DECL_ALIGN is used both for actually emitting the variable
+        and for code accessing the variable as guaranteed alignment, we
+        can only increase the alignment if it is a performance optimization
+        if the references to it must bind to the current definition.  */
+      if (decl_binds_to_current_def_p (decl)
+         && !DECL_VIRTUAL_P (decl))
+       {
+#ifdef DATA_ALIGNMENT
+         unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
+         /* Don't increase alignment too much for TLS variables - TLS space
+            is too precious.  */
+         if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD)
+           align = data_align;
+#endif
+#ifdef CONSTANT_ALIGNMENT
+         if (DECL_INITIAL (decl) != 0
+             /* In LTO we have no errors in program; error_mark_node is used
+                to mark offlined constructors.  */
+             && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
+           {
+             unsigned int const_align
+               = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
+             /* Don't increase alignment too much for TLS variables - TLS
+                space is too precious.  */
+             if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD)
+               align = const_align;
+           }
+#endif
+       }
+    }
+
+  /* Reset the alignment in case we have made it tighter, so we can benefit
+     from it in get_pointer_alignment.  */
+  DECL_ALIGN (decl) = align;
+}
+
+/* Return DECL_ALIGN (decl), possibly increased for optimization purposes
+   beyond what align_variable returned.  */
+
+static unsigned int
+get_variable_align (tree decl)
+{
+  unsigned int align = DECL_ALIGN (decl);
+
+  /* For user aligned vars or static vars align_variable already did
+     everything.  */
+  if (DECL_USER_ALIGN (decl) || !TREE_PUBLIC (decl))
+    return align;
+
+#ifdef DATA_ABI_ALIGNMENT
+  if (DECL_THREAD_LOCAL_P (decl))
+    align = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align);
+#endif
+
+  /* For decls that bind to the current definition, align_variable
+     did also everything, except for not assuming ABI required alignment
+     of TLS variables.  For other vars, increase the alignment here
+     as an optimization.  */
+  if (!decl_binds_to_current_def_p (decl))
+    {
+      /* On some machines, it is good to increase alignment sometimes.  */
 #ifdef DATA_ALIGNMENT
       unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
       /* Don't increase alignment too much for TLS variables - TLS space
-        is too precious.  */
+         is too precious.  */
       if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD)
        align = data_align;
 #endif
 #ifdef CONSTANT_ALIGNMENT
-      if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
+      if (DECL_INITIAL (decl) != 0
+         /* In LTO we have no errors in program; error_mark_node is used
+            to mark offlined constructors.  */
+         && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
        {
          unsigned int const_align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl),
                                                         align);
@@ -987,9 +1100,7 @@ align_variable (tree decl, bool dont_output_data)
 #endif
     }
 
-  /* Reset the alignment in case we have made it tighter, so we can benefit
-     from it in get_pointer_alignment.  */
-  DECL_ALIGN (decl) = align;
+  return align;
 }
 
 /* Return the section into which the given VAR_DECL or CONST_DECL
@@ -1001,10 +1112,20 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
 {
   addr_space_t as = ADDR_SPACE_GENERIC;
   int reloc;
+  varpool_node *vnode = varpool_node::get (decl);
+  if (vnode)
+    {
+      vnode = vnode->ultimate_alias_target ();
+      decl = vnode->decl;
+    }
 
   if (TREE_TYPE (decl) != error_mark_node)
     as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
 
+  /* We need the constructor to figure out reloc flag.  */
+  if (vnode)
+    vnode->get_constructor ();
+
   if (DECL_COMMON (decl))
     {
       /* If the decl has been given an explicit section name, or it resides
@@ -1034,13 +1155,16 @@ get_variable_section (tree decl, bool prefer_noswitch_p)
       && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
       && bss_initializer_p (decl))
     {
-      if (!TREE_PUBLIC (decl))
+      if (!TREE_PUBLIC (decl)
+         && !((flag_sanitize & SANITIZE_ADDRESS)
+              && asan_protect_global (decl)))
        return lcomm_section;
       if (bss_noswitch_section)
        return bss_noswitch_section;
     }
 
-  return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
+  return targetm.asm_out.select_section (decl, reloc,
+                                        get_variable_align (decl));
 }
 
 /* Return the block into which object_block DECL should be placed.  */
@@ -1058,7 +1182,7 @@ get_block_for_decl (tree decl)
 
       /* There's no point using object blocks for something that is
         isolated by definition.  */
-      if (DECL_ONE_ONLY (decl))
+      if (DECL_COMDAT_GROUP (decl))
        return NULL;
     }
 
@@ -1066,7 +1190,7 @@ get_block_for_decl (tree decl)
      constant size.  */
   if (DECL_SIZE_UNIT (decl) == NULL)
     return NULL;
-  if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
+  if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (decl)))
     return NULL;
 
   /* Find out which section should contain DECL.  We cannot put it into
@@ -1097,6 +1221,8 @@ change_symbol_block (rtx symbol, struct object_block *block)
 static bool
 use_blocks_for_decl_p (tree decl)
 {
+  struct symtab_node *snode;
+
   /* Only data DECLs can be placed into object blocks.  */
   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL)
     return false;
@@ -1110,12 +1236,38 @@ use_blocks_for_decl_p (tree decl)
 
   /* If this decl is an alias, then we don't want to emit a
      definition.  */
-  if (lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
+  if (TREE_CODE (decl) == VAR_DECL
+      && (snode = symtab_node::get (decl)) != NULL
+      && snode->alias)
     return false;
 
   return targetm.use_blocks_for_decl_p (decl);
 }
 
+/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
+   until we find an identifier that is not itself a transparent alias.
+   Modify the alias passed to it by reference (and all aliases on the
+   way to the ultimate target), such that they do not have to be
+   followed again, and return the ultimate target of the alias
+   chain.  */
+
+static inline tree
+ultimate_transparent_alias_target (tree *alias)
+{
+  tree target = *alias;
+
+  if (IDENTIFIER_TRANSPARENT_ALIAS (target))
+    {
+      gcc_assert (TREE_CHAIN (target));
+      target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
+      gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
+                 && ! TREE_CHAIN (target));
+      *alias = target;
+    }
+
+  return target;
+}
+
 /* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL.  DECL should
    have static storage duration.  In other words, it should not be an
    automatic variable, including PARM_DECLs.
@@ -1130,6 +1282,7 @@ make_decl_rtl (tree decl)
 {
   const char *name = 0;
   int reg_number;
+  tree id;
   rtx x;
 
   /* Check that we are not being given an automatic variable.  */
@@ -1176,10 +1329,6 @@ make_decl_rtl (tree decl)
          && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0)))
        change_symbol_block (XEXP (x, 0), get_block_for_decl (decl));
 
-      /* Make this function static known to the mudflap runtime.  */
-      if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
-       mudflap_enqueue_decl (decl);
-
       return;
     }
 
@@ -1191,7 +1340,12 @@ make_decl_rtl (tree decl)
       return;
     }
 
-  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  id = DECL_ASSEMBLER_NAME (decl);
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node::get (decl)
+      && cgraph_node::get (decl)->instrumentation_clone)
+    ultimate_transparent_alias_target (&id);
+  name = IDENTIFIER_POINTER (id);
 
   if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
       && DECL_REGISTER (decl))
@@ -1201,7 +1355,7 @@ make_decl_rtl (tree decl)
   else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
     {
       const char *asmspec = name+1;
-      enum machine_mode mode = DECL_MODE (decl);
+      machine_mode mode = DECL_MODE (decl);
       reg_number = decode_reg_name (asmspec);
       /* First detect errors in declaring global registers.  */
       if (reg_number == -1)
@@ -1260,6 +1414,11 @@ make_decl_rtl (tree decl)
          /* As a register variable, it has no section.  */
          return;
        }
+      /* Avoid internal errors from invalid register
+        specifications.  */
+      SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
+      DECL_HARD_REGISTER (decl) = 0;
+      return;
     }
   /* Now handle ordinary static variables and functions (in memory).
      Also handle vars declared register invalidly.  */
@@ -1282,7 +1441,8 @@ make_decl_rtl (tree decl)
      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
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+      && DECL_SECTION_NAME (decl) != NULL
       && DECL_INITIAL (decl) == NULL_TREE
       && DECL_COMMON (decl))
     DECL_COMMON (decl) = 0;
@@ -1295,7 +1455,7 @@ make_decl_rtl (tree decl)
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
     {
-      enum machine_mode address_mode = Pmode;
+      machine_mode address_mode = Pmode;
       if (TREE_TYPE (decl) != error_mark_node)
        {
          addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
@@ -1316,10 +1476,6 @@ make_decl_rtl (tree decl)
      If the name is changed, the macro ASM_OUTPUT_LABELREF
      will have to know how to strip this information.  */
   targetm.encode_section_info (decl, DECL_RTL (decl), true);
-
-  /* Make this function static known to the mudflap runtime.  */
-  if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
-    mudflap_enqueue_decl (decl);
 }
 
 /* Like make_decl_rtl, but inhibit creation of new alias sets when
@@ -1329,7 +1485,7 @@ make_decl_rtl (tree decl)
 rtx
 make_decl_rtl_for_debug (tree decl)
 {
-  unsigned int save_aliasing_flag, save_mudflap_flag;
+  unsigned int save_aliasing_flag;
   rtx rtl;
 
   if (DECL_RTL_SET_P (decl))
@@ -1340,12 +1496,9 @@ make_decl_rtl_for_debug (tree decl)
      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.  */
+     new set.  */
   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
@@ -1353,8 +1506,6 @@ make_decl_rtl_for_debug (tree decl)
   SET_DECL_RTL (decl, NULL);
 
   flag_strict_aliasing = save_aliasing_flag;
-  flag_mudflap = save_mudflap_flag;
-
   return rtl;
 }
 \f
@@ -1380,7 +1531,7 @@ assemble_addr_to_section (rtx symbol, section *sec)
 {
   switch_to_section (sec);
   assemble_align (POINTER_SIZE);
-  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+  assemble_integer (symbol, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
 }
 
 /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
@@ -1511,7 +1662,7 @@ decide_function_section (tree decl)
 
  if (DECL_SECTION_NAME (decl))
     {
-      struct cgraph_node *node = cgraph_get_node (current_function_decl);
+      struct cgraph_node *node = cgraph_node::get (current_function_decl);
       /* Calls to function_section rely on first_function_block_is_cold
         being accurate.  */
       first_function_block_is_cold = (node
@@ -1522,6 +1673,18 @@ decide_function_section (tree decl)
   in_cold_section_p = first_function_block_is_cold;
 }
 
+/* Get the function's name, as described by its RTL.  This may be
+   different from the DECL_NAME name used in the source file.  */
+const char *
+get_fnname_from_decl (tree decl)
+{
+  rtx x = DECL_RTL (decl);
+  gcc_assert (MEM_P (x));
+  x = XEXP (x, 0);
+  gcc_assert (GET_CODE (x) == SYMBOL_REF);
+  return XSTR (x, 0);
+}
+
 /* Output assembler code for the constant pool of a function and associated
    with defining the name of the function.  DECL describes the function.
    NAME is the function's name.  For the constant pool, we use the current
@@ -1578,7 +1741,7 @@ assemble_start_function (tree decl, const char *fnname)
         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 (!cfun->is_thunk
-         && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
+         && BB_PARTITION (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb) == BB_COLD_PARTITION)
        {
          switch_to_section (text_section);
          assemble_align (DECL_ALIGN (decl));
@@ -1628,7 +1791,10 @@ assemble_start_function (tree decl, const char *fnname)
 
   /* Make function name accessible from other files, if appropriate.  */
 
-  if (TREE_PUBLIC (decl))
+  if (TREE_PUBLIC (decl)
+      || (cgraph_node::get (decl)->instrumentation_clone
+         && cgraph_node::get (decl)->instrumented_version
+         && TREE_PUBLIC (cgraph_node::get (decl)->instrumented_version->decl)))
     {
       notice_global_symbol (decl);
 
@@ -1777,7 +1943,8 @@ emit_bss (tree decl ATTRIBUTE_UNUSED,
          unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
 {
 #if defined ASM_OUTPUT_ALIGNED_BSS
-  ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl));
+  ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size,
+                         get_variable_align (decl));
   return true;
 #endif
 }
@@ -1793,10 +1960,11 @@ emit_common (tree decl ATTRIBUTE_UNUSED,
 {
 #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
   ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name,
-                                 size, DECL_ALIGN (decl));
+                                 size, get_variable_align (decl));
   return true;
 #elif defined ASM_OUTPUT_ALIGNED_COMMON
-  ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl));
+  ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
+                            get_variable_align (decl));
   return true;
 #else
   ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
@@ -1825,14 +1993,15 @@ emit_tls_common (tree decl ATTRIBUTE_UNUSED,
    NAME is the name of DECL's SYMBOL_REF.  */
 
 static void
-assemble_noswitch_variable (tree decl, const char *name, section *sect)
+assemble_noswitch_variable (tree decl, const char *name, section *sect,
+                           unsigned int align)
 {
   unsigned HOST_WIDE_INT size, rounded;
 
-  size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+  size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
   rounded = size;
 
-  if (flag_asan && asan_protect_global (decl))
+  if ((flag_sanitize & SANITIZE_ADDRESS) && asan_protect_global (decl))
     size += asan_red_zone_size (size);
 
   /* Don't allocate zero bytes of common,
@@ -1847,9 +2016,9 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect)
             * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
 
   if (!sect->noswitch.callback (decl, name, size, rounded)
-      && (unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded)
-    warning (0, "requested alignment for %q+D is greater than "
-            "implemented alignment of %wu", decl, rounded);
+      && (unsigned HOST_WIDE_INT) (align / BITS_PER_UNIT) > rounded)
+    error ("requested alignment for %q+D is greater than "
+          "implemented alignment of %wu", decl, rounded);
 }
 
 /* A subroutine of assemble_variable.  Output the label and contents of
@@ -1871,19 +2040,32 @@ assemble_variable_contents (tree decl, const char *name,
 
   if (!dont_output_data)
     {
+      /* Caller is supposed to use varpool_get_constructor when it wants
+        to output the body.  */
+      gcc_assert (!in_lto_p || DECL_INITIAL (decl) != error_mark_node);
       if (DECL_INITIAL (decl)
          && DECL_INITIAL (decl) != error_mark_node
          && !initializer_zerop (DECL_INITIAL (decl)))
        /* Output the actual data.  */
        output_constant (DECL_INITIAL (decl),
-                        tree_low_cst (DECL_SIZE_UNIT (decl), 1),
-                        DECL_ALIGN (decl));
+                        tree_to_uhwi (DECL_SIZE_UNIT (decl)),
+                        get_variable_align (decl));
       else
        /* Leave space for it.  */
-       assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
+       assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
+      targetm.asm_out.decl_end ();
     }
 }
 
+/* Write out assembly for the variable DECL, which is not defined in
+   the current translation unit.  */
+void
+assemble_undefined_decl (tree decl)
+{
+  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+  targetm.asm_out.assemble_undefined_decl (asm_out_file, name, decl);
+}
+
 /* 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.
@@ -1901,6 +2083,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
   const char *name;
   rtx decl_rtl, symbol;
   section *sect;
+  unsigned int align;
   bool asan_protected = false;
 
   /* This function is supposed to handle VARIABLES.  Ensure we have one.  */
@@ -1990,7 +2173,7 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
 
   align_variable (decl, dont_output_data);
 
-  if (flag_asan
+  if ((flag_sanitize & SANITIZE_ADDRESS)
       && asan_protect_global (decl))
     {
       asan_protected = true;
@@ -2000,6 +2183,8 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
 
   set_mem_align (decl_rtl, DECL_ALIGN (decl));
 
+  align = get_variable_align (decl);
+
   if (TREE_PUBLIC (decl))
     maybe_assemble_visibility (decl);
 
@@ -2029,22 +2214,63 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
       place_block_symbol (symbol);
     }
   else if (SECTION_STYLE (sect) == SECTION_NOSWITCH)
-    assemble_noswitch_variable (decl, name, sect);
+    assemble_noswitch_variable (decl, name, sect, align);
   else
     {
-      switch_to_section (sect);
-      if (DECL_ALIGN (decl) > BITS_PER_UNIT)
-       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl)));
+      /* The following bit of code ensures that vtable_map 
+         variables are not only in the comdat section, but that
+         each variable has its own unique comdat name.  If this
+         code is removed, the variables end up in the same section
+         with a single comdat name.
+
+         FIXME:  resolve_unique_section needs to deal better with
+         decls with both DECL_SECTION_NAME and DECL_ONE_ONLY.  Once
+         that is fixed, this if-else statement can be replaced with
+         a single call to "switch_to_section (sect)".  */
+      if (sect->named.name
+         && (strcmp (sect->named.name, ".vtable_map_vars") == 0))
+       {
+#if defined (OBJECT_FORMAT_ELF)
+          targetm.asm_out.named_section (sect->named.name,
+                                        sect->named.common.flags
+                                        | SECTION_LINKONCE,
+                                        DECL_NAME (decl));
+          in_section = sect;
+#else
+          switch_to_section (sect);
+#endif
+        }
+      else
+       switch_to_section (sect);
+      if (align > BITS_PER_UNIT)
+       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
       assemble_variable_contents (decl, name, dont_output_data);
       if (asan_protected)
        {
          unsigned HOST_WIDE_INT int size
-           = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+           = tree_to_uhwi (DECL_SIZE_UNIT (decl));
          assemble_zeros (asan_red_zone_size (size));
        }
     }
 }
 
+
+/* Given a function declaration (FN_DECL), this function assembles the
+   function into the .preinit_array section.  */
+
+void
+assemble_vtv_preinit_initializer (tree fn_decl)
+{
+  section *sect;
+  unsigned flags = SECTION_WRITE;
+  rtx symbol = XEXP (DECL_RTL (fn_decl), 0);
+
+  flags |= SECTION_NOTYPE;
+  sect = get_section (".preinit_array", flags, fn_decl);
+  switch_to_section (sect);
+  assemble_addr_to_section (symbol, sect);
+}
+
 /* Return 1 if type TYPE contains any pointers.  */
 
 static int
@@ -2088,6 +2314,15 @@ contains_pointers_p (tree type)
 static GTY(()) tree pending_assemble_externals;
 
 #ifdef ASM_OUTPUT_EXTERNAL
+/* Some targets delay some output to final using TARGET_ASM_FILE_END.
+   As a result, assemble_external can be called after the list of externals
+   is processed and the pointer set destroyed.  */
+static bool pending_assemble_externals_processed;
+
+/* Avoid O(external_decls**2) lookups in the pending_assemble_externals
+   TREE_LIST in assemble_external.  */
+static hash_set<tree> *pending_assemble_externals_set;
+
 /* True if DECL is a function decl for which no out-of-line copy exists.
    It is assumed that DECL's assembler name has been set.  */
 
@@ -2139,6 +2374,8 @@ process_pending_assemble_externals (void)
     assemble_external_real (TREE_VALUE (list));
 
   pending_assemble_externals = 0;
+  pending_assemble_externals_processed = true;
+  delete pending_assemble_externals_set;
 #endif
 }
 
@@ -2167,8 +2404,8 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
      Ideally, only final.c would be calling this function, but it is
      not clear whether that would break things somehow.  See PR 17982
      for further discussion.  */
-  gcc_assert (cgraph_state == CGRAPH_STATE_EXPANSION
-             || cgraph_state == CGRAPH_STATE_FINISHED);
+  gcc_assert (state == EXPANSION
+             || state == FINISHED);
 #endif
 
   if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
@@ -2190,7 +2427,13 @@ assemble_external (tree decl ATTRIBUTE_UNUSED)
     weak_decls = tree_cons (NULL, decl, weak_decls);
 
 #ifdef ASM_OUTPUT_EXTERNAL
-  if (value_member (decl, pending_assemble_externals) == NULL_TREE)
+  if (pending_assemble_externals_processed)
+    {
+      assemble_external_real (decl);
+      return;
+    }
+
+  if (! pending_assemble_externals_set->add (decl))
     pending_assemble_externals = tree_cons (NULL, decl,
                                            pending_assemble_externals);
 #endif
@@ -2234,47 +2477,23 @@ mark_decl_referenced (tree decl)
         If we know a method will be emitted in other TU and no new
         functions can be marked reachable, just use the external
         definition.  */
-      struct cgraph_node *node = cgraph_get_create_node (decl);
+      struct cgraph_node *node = cgraph_node::get_create (decl);
       if (!DECL_EXTERNAL (decl)
-         && !node->local.finalized)
-       cgraph_mark_force_output_node (node);
+         && !node->definition)
+       node->mark_force_output ();
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     {
-      struct varpool_node *node = varpool_node_for_decl (decl);
+      varpool_node *node = varpool_node::get_create (decl);
       /* C++ frontend use mark_decl_references to force COMDAT variables
          to be output that might appear dead otherwise.  */
-      node->symbol.force_output = true;
+      node->force_output = true;
     }
   /* else do nothing - we can get various sorts of CST nodes here,
      which do not need to be marked.  */
 }
 
 
-/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
-   until we find an identifier that is not itself a transparent alias.
-   Modify the alias passed to it by reference (and all aliases on the
-   way to the ultimate target), such that they do not have to be
-   followed again, and return the ultimate target of the alias
-   chain.  */
-
-static inline tree
-ultimate_transparent_alias_target (tree *alias)
-{
-  tree target = *alias;
-
-  if (IDENTIFIER_TRANSPARENT_ALIAS (target))
-    {
-      gcc_assert (TREE_CHAIN (target));
-      target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
-      gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
-                 && ! TREE_CHAIN (target));
-      *alias = target;
-    }
-
-  return target;
-}
-
 /* Output to FILE (an assembly file) a reference to NAME.  If NAME
    starts with a *, the rest of NAME is output verbatim.  Otherwise
    NAME is transformed in a target-specific way (usually by the
@@ -2469,7 +2688,7 @@ default_assemble_integer (rtx x ATTRIBUTE_UNUSED,
   const char *op = integer_asm_op (size, aligned_p);
   /* Avoid GAS bugs for large values.  Specifically negative values whose
      absolute value fits in a bfd_vma, but not in a bfd_signed_vma.  */
-  if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT)
+  if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
     return false;
   return op && (assemble_integer_with_op (op, x), true);
 }
@@ -2494,7 +2713,7 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
      it into words it if is multi-word, otherwise split it into bytes.  */
   if (size > 1)
     {
-      enum machine_mode omode, imode;
+      machine_mode omode, imode;
       unsigned int subalign;
       unsigned int subsize, i;
       enum mode_class mclass;
@@ -2529,7 +2748,7 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
 }
 \f
 void
-assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
+assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
 {
   long data[4] = {0, 0, 0, 0};
   int i;
@@ -2588,7 +2807,7 @@ decode_addr_const (tree exp, struct addr_const *value)
   while (1)
     {
       if (TREE_CODE (target) == COMPONENT_REF
-         && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
+         && tree_fits_shwi_p (byte_position (TREE_OPERAND (target, 1))))
        {
          offset += int_byte_position (TREE_OPERAND (target, 1));
          target = TREE_OPERAND (target, 0);
@@ -2596,14 +2815,14 @@ decode_addr_const (tree exp, struct addr_const *value)
       else if (TREE_CODE (target) == ARRAY_REF
               || TREE_CODE (target) == ARRAY_RANGE_REF)
        {
-         offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
-                    * tree_low_cst (TREE_OPERAND (target, 1), 0));
+         offset += (tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (target)))
+                    * tree_to_shwi (TREE_OPERAND (target, 1)));
          target = TREE_OPERAND (target, 0);
        }
       else if (TREE_CODE (target) == MEM_REF
               && TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR)
        {
-         offset += mem_ref_offset (target).low;
+         offset += mem_ref_offset (target).to_short_addr ();
          target = TREE_OPERAND (TREE_OPERAND (target, 0), 0);
        }
       else if (TREE_CODE (target) == INDIRECT_REF
@@ -2647,15 +2866,13 @@ decode_addr_const (tree exp, struct addr_const *value)
   value->offset = offset;
 }
 \f
-
-static GTY((param_is (struct constant_descriptor_tree)))
-     htab_t const_desc_htab;
+static GTY(()) hash_table<tree_descriptor_hasher> *const_desc_htab;
 
 static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
 
 /* Constant pool accessor function.  */
 
-htab_t
+hash_table<tree_descriptor_hasher> *
 constant_pool_htab (void)
 {
   return const_desc_htab;
@@ -2663,10 +2880,10 @@ constant_pool_htab (void)
 
 /* Compute a hash code for a constant expression.  */
 
-static hashval_t
-const_desc_hash (const void *ptr)
+hashval_t
+tree_descriptor_hasher::hash (constant_descriptor_tree *ptr)
 {
-  return ((const struct constant_descriptor_tree *)ptr)->hash;
+  return ptr->hash;
 }
 
 static hashval_t
@@ -2683,8 +2900,8 @@ const_hash_1 (const tree exp)
   switch (code)
     {
     case INTEGER_CST:
-      p = (char *) &TREE_INT_CST (exp);
-      len = sizeof TREE_INT_CST (exp);
+      p = (char *) &TREE_INT_CST_ELT (exp, 0);
+      len = TREE_INT_CST_NUNITS (exp) * sizeof (HOST_WIDE_INT);
       break;
 
     case REAL_CST:
@@ -2746,7 +2963,8 @@ const_hash_1 (const tree exp)
            break;
 
          case LABEL_REF:
-           hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
+           hi = (value.offset
+                 + CODE_LABEL_NUMBER (LABEL_REF_LABEL (value.base)) * 13);
            break;
 
          default:
@@ -2778,13 +2996,10 @@ const_hash_1 (const tree exp)
 }
 
 /* Wrapper of compare_constant, for the htab interface.  */
-static int
-const_desc_eq (const void *p1, const void *p2)
+bool
+tree_descriptor_hasher::equal (constant_descriptor_tree *c1,
+                              constant_descriptor_tree *c2)
 {
-  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);
@@ -2936,8 +3151,8 @@ compare_constant (const tree t1, const tree t2)
            break;
 
          case LABEL_REF:
-           ret = (CODE_LABEL_NUMBER (XEXP (value1.base, 0))
-                  == CODE_LABEL_NUMBER (XEXP (value2.base, 0)));
+           ret = (CODE_LABEL_NUMBER (LABEL_REF_LABEL (value1.base))
+                  == CODE_LABEL_NUMBER (LABEL_REF_LABEL (value2.base)));
            break;
 
          default:
@@ -2951,7 +3166,7 @@ compare_constant (const tree t1, const tree t2)
     case MINUS_EXPR:
     case RANGE_EXPR:
       return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
-             && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
+             && compare_constant (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
 
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
@@ -2964,71 +3179,6 @@ compare_constant (const tree t1, const tree t2)
   gcc_unreachable ();
 }
 \f
-/* Make a copy of the whole tree structure for a constant.  This
-   handles the same types of nodes that compare_constant handles.  */
-
-static tree
-copy_constant (tree exp)
-{
-  switch (TREE_CODE (exp))
-    {
-    case ADDR_EXPR:
-      /* For ADDR_EXPR, we do not want to copy the decl whose address
-        is requested.  We do want to copy constants though.  */
-      if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
-       return build1 (TREE_CODE (exp), TREE_TYPE (exp),
-                      copy_constant (TREE_OPERAND (exp, 0)));
-      else
-       return copy_node (exp);
-
-    case INTEGER_CST:
-    case REAL_CST:
-    case FIXED_CST:
-    case STRING_CST:
-      return copy_node (exp);
-
-    case COMPLEX_CST:
-      return build_complex (TREE_TYPE (exp),
-                           copy_constant (TREE_REALPART (exp)),
-                           copy_constant (TREE_IMAGPART (exp)));
-
-    case PLUS_EXPR:
-    case POINTER_PLUS_EXPR:
-    case MINUS_EXPR:
-      return build2 (TREE_CODE (exp), TREE_TYPE (exp),
-                    copy_constant (TREE_OPERAND (exp, 0)),
-                    copy_constant (TREE_OPERAND (exp, 1)));
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      return build1 (TREE_CODE (exp), TREE_TYPE (exp),
-                    copy_constant (TREE_OPERAND (exp, 0)));
-
-    case VECTOR_CST:
-      return build_vector (TREE_TYPE (exp), VECTOR_CST_ELTS (exp));
-
-    case CONSTRUCTOR:
-      {
-       tree copy = copy_node (exp);
-       vec<constructor_elt, va_gc> *v;
-       unsigned HOST_WIDE_INT idx;
-       tree purpose, value;
-
-       vec_alloc (v, vec_safe_length (CONSTRUCTOR_ELTS (exp)));
-       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), idx, purpose, value)
-         {
-           constructor_elt ce = {purpose, copy_constant (value)};
-           v->quick_push (ce);
-         }
-       CONSTRUCTOR_ELTS (copy) = v;
-       return copy;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-}
-\f
 /* Return the section into which constant EXP should be placed.  */
 
 static section *
@@ -3068,12 +3218,8 @@ build_constant_desc (tree exp)
   int labelno;
   tree decl;
 
-  desc = ggc_alloc_constant_descriptor_tree ();
-  desc->value = copy_constant (exp);
-
-  /* Propagate marked-ness to copied constant.  */
-  if (flag_mudflap && mf_marked_p (exp))
-    mf_mark (desc->value);
+  desc = ggc_alloc<constant_descriptor_tree> ();
+  desc->value = exp;
 
   /* Create a string containing the label name, in LABEL.  */
   labelno = const_labelno++;
@@ -3119,7 +3265,6 @@ build_constant_desc (tree exp)
   rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
   set_mem_attributes (rtl, exp, 1);
   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.  */
@@ -3155,15 +3300,15 @@ output_constant_def (tree exp, int defer)
 {
   struct constant_descriptor_tree *desc;
   struct constant_descriptor_tree key;
-  void **loc;
 
   /* 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);
+  constant_descriptor_tree **loc
+    = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
 
-  desc = (struct constant_descriptor_tree *) *loc;
+  desc = *loc;
   if (desc == 0)
     {
       desc = build_constant_desc (exp);
@@ -3224,6 +3369,8 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
 
   /* Output the value of EXP.  */
   output_constant (exp, size, align);
+
+  targetm.asm_out.decl_end ();
 }
 
 /* We must output the constant data referred to by SYMBOL; do so.  */
@@ -3234,6 +3381,7 @@ output_constant_def_contents (rtx symbol)
   tree decl = SYMBOL_REF_DECL (symbol);
   tree exp = DECL_INITIAL (decl);
   unsigned int align;
+  bool asan_protected = false;
 
   /* Make sure any other constants whose addresses appear in EXP
      are assigned label numbers.  */
@@ -3242,6 +3390,15 @@ output_constant_def_contents (rtx symbol)
   /* We are no longer deferring this constant.  */
   TREE_ASM_WRITTEN (decl) = TREE_ASM_WRITTEN (exp) = 1;
 
+  if ((flag_sanitize & SANITIZE_ADDRESS)
+      && TREE_CODE (exp) == STRING_CST
+      && asan_protect_global (exp))
+    {
+      asan_protected = true;
+      DECL_ALIGN (decl) = MAX (DECL_ALIGN (decl),
+                              ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
+    }
+
   /* If the constant is part of an object block, make sure that the
      decl has been positioned within its block, but do not write out
      its definition yet.  output_object_blocks will do that later.  */
@@ -3254,9 +3411,12 @@ output_constant_def_contents (rtx symbol)
       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);
+      if (asan_protected)
+       {
+         HOST_WIDE_INT size = get_constant_size (exp);
+         assemble_zeros (asan_red_zone_size (size));
+       }
     }
-  if (flag_mudflap)
-    mudflap_enqueue_constant (exp);
 }
 
 /* Look up EXP in the table of constant descriptors.  Return the rtl
@@ -3265,13 +3425,12 @@ output_constant_def_contents (rtx symbol)
 rtx
 lookup_constant_def (tree exp)
 {
-  struct constant_descriptor_tree *desc;
   struct constant_descriptor_tree key;
 
   key.value = exp;
   key.hash = const_hash_1 (exp);
-  desc = (struct constant_descriptor_tree *)
-    htab_find_with_hash (const_desc_htab, &key, key.hash);
+  constant_descriptor_tree *desc
+    = const_desc_htab->find_with_hash (&key, key.hash);
 
   return (desc ? desc->rtl : NULL_RTX);
 }
@@ -3285,16 +3444,16 @@ 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);
+  constant_descriptor_tree **loc
+    = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
 
-  desc = (struct constant_descriptor_tree *) *loc;
+  desc = *loc;
   if (desc == 0)
     {
       desc = build_constant_desc (exp);
@@ -3303,10 +3462,29 @@ tree_output_constant_def (tree exp)
     }
 
   decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
-  varpool_finalize_decl (decl);
+  varpool_node::finalize_decl (decl);
   return decl;
 }
 \f
+struct GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx {
+  struct constant_descriptor_rtx *next;
+  rtx mem;
+  rtx sym;
+  rtx constant;
+  HOST_WIDE_INT offset;
+  hashval_t hash;
+  machine_mode mode;
+  unsigned int align;
+  int labelno;
+  int mark;
+};
+
+struct const_rtx_desc_hasher : ggc_hasher<constant_descriptor_rtx *>
+{
+  static hashval_t hash (constant_descriptor_rtx *);
+  static bool equal (constant_descriptor_rtx *, constant_descriptor_rtx *);
+};
+
 /* Used in the hash tables to avoid outputting the same constant
    twice.  Unlike 'struct constant_descriptor_tree', RTX constants
    are output once per function, not once per file.  */
@@ -3323,61 +3501,41 @@ struct GTY(()) rtx_constant_pool {
      It is used on RISC machines where immediate integer arguments and
      constant addresses are restricted so that such constants must be stored
      in memory.  */
-  htab_t GTY((param_is (struct constant_descriptor_rtx))) const_rtx_htab;
+  hash_table<const_rtx_desc_hasher> *const_rtx_htab;
 
   /* Current offset in constant pool (does not include any
      machine-specific header).  */
   HOST_WIDE_INT offset;
 };
 
-struct GTY((chain_next ("%h.next"))) constant_descriptor_rtx {
-  struct constant_descriptor_rtx *next;
-  rtx mem;
-  rtx sym;
-  rtx constant;
-  HOST_WIDE_INT offset;
-  hashval_t hash;
-  enum machine_mode mode;
-  unsigned int align;
-  int labelno;
-  int mark;
-};
-
 /* Hash and compare functions for const_rtx_htab.  */
 
-static hashval_t
-const_desc_rtx_hash (const void *ptr)
+hashval_t
+const_rtx_desc_hasher::hash (constant_descriptor_rtx *desc)
 {
-  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)
+bool
+const_rtx_desc_hasher::equal (constant_descriptor_rtx *x,
+                             constant_descriptor_rtx *y)
 {
-  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;
   return rtx_equal_p (x->constant, y->constant);
 }
 
-/* This is the worker function for const_rtx_hash, called via for_each_rtx.  */
+/* Hash one component of a constant.  */
 
-static int
-const_rtx_hash_1 (rtx *xp, void *data)
+static hashval_t
+const_rtx_hash_1 (const_rtx x)
 {
   unsigned HOST_WIDE_INT hwi;
-  enum machine_mode mode;
+  machine_mode mode;
   enum rtx_code code;
-  hashval_t h, *hp;
-  rtx x;
+  hashval_t h;
+  int i;
 
-  x = *xp;
   code = GET_CODE (x);
   mode = GET_MODE (x);
   h = (hashval_t) code * 1048573 + mode;
@@ -3386,11 +3544,11 @@ const_rtx_hash_1 (rtx *xp, void *data)
     {
     case CONST_INT:
       hwi = INTVAL (x);
+
     fold_hwi:
       {
        int shift = sizeof (hashval_t) * CHAR_BIT;
        const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
-       int i;
 
        h ^= (hashval_t) hwi;
        for (i = 1; i < n; ++i)
@@ -3401,8 +3559,16 @@ const_rtx_hash_1 (rtx *xp, void *data)
       }
       break;
 
+    case CONST_WIDE_INT:
+      hwi = GET_MODE_PRECISION (mode);
+      {
+       for (i = 0; i < CONST_WIDE_INT_NUNITS (x); i++)
+         hwi ^= CONST_WIDE_INT_ELT (x, i);
+       goto fold_hwi;
+      }
+
     case CONST_DOUBLE:
-      if (mode == VOIDmode)
+      if (TARGET_SUPPORTS_WIDE_INT == 0 && mode == VOIDmode)
        {
          hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
          goto fold_hwi;
@@ -3415,20 +3581,12 @@ const_rtx_hash_1 (rtx *xp, void *data)
       h ^= fixed_hash (CONST_FIXED_VALUE (x));
       break;
 
-    case CONST_VECTOR:
-      {
-       int i;
-       for (i = XVECLEN (x, 0); i-- > 0; )
-         h = h * 251 + const_rtx_hash_1 (&XVECEXP (x, 0, i), data);
-      }
-      break;
-
     case SYMBOL_REF:
       h ^= htab_hash_string (XSTR (x, 0));
       break;
 
     case LABEL_REF:
-      h = h * 251 + CODE_LABEL_NUMBER (XEXP (x, 0));
+      h = h * 251 + CODE_LABEL_NUMBER (LABEL_REF_LABEL (x));
       break;
 
     case UNSPEC:
@@ -3440,9 +3598,7 @@ const_rtx_hash_1 (rtx *xp, void *data)
       break;
     }
 
-  hp = (hashval_t *) data;
-  *hp = *hp * 509 + h;
-  return 0;
+  return h;
 }
 
 /* Compute a hash value for X, which should be a constant.  */
@@ -3451,7 +3607,9 @@ static hashval_t
 const_rtx_hash (rtx x)
 {
   hashval_t h = 0;
-  for_each_rtx (&x, const_rtx_hash_1, &h);
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, ALL)
+    h = h * 509 + const_rtx_hash_1 (*iter);
   return h;
 }
 
@@ -3463,9 +3621,8 @@ create_constant_pool (void)
 {
   struct rtx_constant_pool *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 = ggc_alloc<rtx_constant_pool> ();
+  pool->const_rtx_htab = hash_table<const_rtx_desc_hasher>::create_ggc (31);
   pool->first = NULL;
   pool->last = NULL;
   pool->offset = 0;
@@ -3495,7 +3652,7 @@ simplify_subtraction (rtx x)
    and return a MEM rtx to refer to it in memory.  */
 
 rtx
-force_const_mem (enum machine_mode mode, rtx x)
+force_const_mem (machine_mode mode, rtx x)
 {
   struct constant_descriptor_rtx *desc, tmp;
   struct rtx_constant_pool *pool;
@@ -3503,7 +3660,7 @@ force_const_mem (enum machine_mode mode, rtx x)
   rtx def, symbol;
   hashval_t hash;
   unsigned int align;
-  void **slot;
+  constant_descriptor_rtx **slot;
 
   /* If we're not allowed to drop X into the constant pool, don't.  */
   if (targetm.cannot_force_const_mem (mode, x))
@@ -3521,15 +3678,15 @@ force_const_mem (enum machine_mode mode, rtx x)
   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 = (struct constant_descriptor_rtx *) *slot;
+  slot = pool->const_rtx_htab->find_slot_with_hash (&tmp, hash, INSERT);
+  desc = *slot;
 
   /* If the constant was already present, return its memory.  */
   if (desc)
     return copy_rtx (desc->mem);
 
   /* Otherwise, create a new descriptor.  */
-  desc = ggc_alloc_constant_descriptor_rtx ();
+  desc = ggc_alloc<constant_descriptor_rtx> ();
   *slot = desc;
 
   /* Align the location counter as required by EXP's data type.  */
@@ -3596,7 +3753,7 @@ force_const_mem (enum machine_mode mode, rtx x)
 /* Given a constant pool SYMBOL_REF, return the corresponding constant.  */
 
 rtx
-get_pool_constant (rtx addr)
+get_pool_constant (const_rtx addr)
 {
   return SYMBOL_REF_CONSTANT (addr)->constant;
 }
@@ -3616,7 +3773,7 @@ get_pool_constant_mark (rtx addr, bool *pmarked)
 
 /* Similar, return the mode.  */
 
-enum machine_mode
+machine_mode
 get_pool_mode (const_rtx addr)
 {
   return SYMBOL_REF_CONSTANT (addr)->mode;
@@ -3634,7 +3791,7 @@ get_pool_size (void)
    in MODE with known alignment ALIGN.  */
 
 static void
-output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
+output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
 {
   switch (GET_MODE_CLASS (mode))
     {
@@ -3655,6 +3812,7 @@ output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
     case MODE_UFRACT:
     case MODE_ACCUM:
     case MODE_UACCUM:
+    case MODE_POINTER_BOUNDS:
       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
       break;
 
@@ -3666,7 +3824,7 @@ output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align)
     case MODE_VECTOR_UACCUM:
       {
        int i, units;
-        enum machine_mode submode = GET_MODE_INNER (mode);
+        machine_mode submode = GET_MODE_INNER (mode);
        unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode));
 
        gcc_assert (GET_CODE (x) == CONST_VECTOR);
@@ -3703,7 +3861,7 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc,
      CODE_LABEL into a NOTE.  */
   /* ??? This seems completely and utterly wrong.  Certainly it's
      not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
-     functioning even with INSN_DELETED_P and friends.  */
+     functioning even with rtx_insn::deleted and friends.  */
 
   tmp = x;
   switch (GET_CODE (tmp))
@@ -3716,8 +3874,8 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc,
       /* FALLTHRU  */
 
     case LABEL_REF:
-      tmp = XEXP (tmp, 0);
-      gcc_assert (!INSN_DELETED_P (tmp));
+      tmp = LABEL_REF_LABEL (tmp);
+      gcc_assert (!as_a<rtx_insn *> (tmp)->deleted ());
       gcc_assert (!NOTE_P (tmp)
                  || NOTE_KIND (tmp) != NOTE_INSN_DELETED);
       break;
@@ -3752,38 +3910,38 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc,
   return;
 }
 
-/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
-   to as used.  Emit referenced deferred strings.  This function can
-   be used with for_each_rtx to mark all SYMBOL_REFs in an rtx.  */
+/* Mark all constants that are referenced by SYMBOL_REFs in X.
+   Emit referenced deferred strings.  */
 
-static int
-mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
+static void
+mark_constants_in_pattern (rtx insn)
 {
-  rtx x = *current_rtx;
-
-  if (x == NULL_RTX || GET_CODE (x) != SYMBOL_REF)
-    return 0;
-
-  if (CONSTANT_POOL_ADDRESS_P (x))
-    {
-      struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
-      if (desc->mark == 0)
-       {
-         desc->mark = 1;
-         for_each_rtx (&desc->constant, mark_constant, NULL);
-       }
-    }
-  else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
     {
-      tree decl = SYMBOL_REF_DECL (x);
-      if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
+      const_rtx x = *iter;
+      if (GET_CODE (x) == SYMBOL_REF)
        {
-         n_deferred_constants--;
-         output_constant_def_contents (x);
+         if (CONSTANT_POOL_ADDRESS_P (x))
+           {
+             struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
+             if (desc->mark == 0)
+               {
+                 desc->mark = 1;
+                 iter.substitute (desc->constant);
+               }
+           }
+         else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
+           {
+             tree decl = SYMBOL_REF_DECL (x);
+             if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
+               {
+                 n_deferred_constants--;
+                 output_constant_def_contents (CONST_CAST_RTX (x));
+               }
+           }
        }
     }
-
-  return -1;
 }
 
 /* Look through appropriate parts of INSN, marking all entries in the
@@ -3792,7 +3950,7 @@ mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
    deferred strings that are used.  */
 
 static void
-mark_constants (rtx insn)
+mark_constants (rtx_insn *insn)
 {
   if (!INSN_P (insn))
     return;
@@ -3800,19 +3958,18 @@ mark_constants (rtx insn)
   /* Insns may appear inside a SEQUENCE.  Only check the patterns of
      insns, not any notes that may be attached.  We don't want to mark
      a constant just because it happens to appear in a REG_EQUIV note.  */
-  if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+  if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
     {
-      rtx seq = PATTERN (insn);
-      int i, n = XVECLEN (seq, 0);
+      int i, n = seq->len ();
       for (i = 0; i < n; ++i)
        {
-         rtx subinsn = XVECEXP (seq, 0, i);
+         rtx subinsn = seq->element (i);
          if (INSN_P (subinsn))
-           for_each_rtx (&PATTERN (subinsn), mark_constant, NULL);
+           mark_constants_in_pattern (subinsn);
        }
     }
   else
-    for_each_rtx (&PATTERN (insn), mark_constant, NULL);
+    mark_constants_in_pattern (insn);
 }
 
 /* Look through the instructions for this function, and mark all the
@@ -3822,7 +3979,7 @@ mark_constants (rtx insn)
 static void
 mark_constant_pool (void)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   if (!crtl->uses_const_pool && n_deferred_constants == 0)
     return;
@@ -3916,7 +4073,7 @@ compute_reloc_for_constant (tree exp)
          break;
        }
 
-      if (TREE_PUBLIC (tem))
+      if (!targetm.binds_local_p (tem))
        reloc |= 2;
       else
        reloc |= 1;
@@ -4436,12 +4593,14 @@ 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.
+/* Output assembler code for constant EXP, 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.
 
-   Generate exactly SIZE bytes of assembler data, padding at the end
-   with zeros if necessary.  SIZE must always be specified.
+   Generate at least SIZE bytes of assembler data, padding at the end
+   with zeros if necessary.  SIZE must always be specified.  The returned
+   value is the actual number of bytes of assembler data generated, which
+   may be bigger than SIZE if the object contains a variable length field.
 
    SIZE is important for structure constructors,
    since trailing members may have been omitted from the constructor.
@@ -4456,14 +4615,14 @@ static unsigned HOST_WIDE_INT
 
    ALIGN is the alignment of the data in bits.  */
 
-void
+static unsigned HOST_WIDE_INT
 output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
 {
   enum tree_code code;
   unsigned HOST_WIDE_INT thissize;
 
   if (size == 0 || flag_syntax_only)
-    return;
+    return size;
 
   /* See if we're trying to initialize a pointer in a non-default mode
      to the address of some declaration somewhere.  If the target says
@@ -4493,8 +4652,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
        exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
       /* Likewise for constant ints.  */
       else if (TREE_CODE (exp) == INTEGER_CST)
-       exp = build_int_cst_wide (saved_type, TREE_INT_CST_LOW (exp),
-                                 TREE_INT_CST_HIGH (exp));
+       exp = wide_int_to_tree (saved_type, exp);
 
     }
 
@@ -4528,19 +4686,19 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
       && vec_safe_is_empty (CONSTRUCTOR_ELTS (exp)))
     {
       assemble_zeros (size);
-      return;
+      return size;
     }
 
   if (TREE_CODE (exp) == FDESC_EXPR)
     {
 #ifdef ASM_OUTPUT_FDESC
-      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
+      HOST_WIDE_INT part = tree_to_shwi (TREE_OPERAND (exp, 1));
       tree decl = TREE_OPERAND (exp, 0);
       ASM_OUTPUT_FDESC (asm_out_file, decl, part);
 #else
       gcc_unreachable ();
 #endif
-      return;
+      return size;
     }
 
   /* Now output the underlying data.  If we've handling the padding, return.
@@ -4554,6 +4712,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
     case FIXED_POINT_TYPE:
+    case POINTER_BOUNDS_TYPE:
+    case NULLPTR_TYPE:
       if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
                                           EXPAND_INITIALIZER),
                              MIN (size, thissize), align, 0))
@@ -4578,28 +4738,20 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
       switch (TREE_CODE (exp))
        {
        case CONSTRUCTOR:
-           output_constructor (exp, size, align, NULL);
-         return;
+         return output_constructor (exp, size, align, NULL);
        case STRING_CST:
-         thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
-                         size);
+         thissize
+           = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
          assemble_string (TREE_STRING_POINTER (exp), thissize);
          break;
-
        case VECTOR_CST:
          {
-           int elt_size;
-           unsigned int i, nalign;
-           enum machine_mode inner;
-
-           inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
-           nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
-
-           elt_size = GET_MODE_SIZE (inner);
-
+           machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
+           unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
+           int elt_size = GET_MODE_SIZE (inner);
            output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align);
            thissize = elt_size;
-           for (i = 1; i < VECTOR_CST_NELTS (exp); ++i)
+           for (unsigned int i = 1; i < VECTOR_CST_NELTS (exp); i++)
              {
                output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign);
                thissize += elt_size;
@@ -4614,11 +4766,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
     case RECORD_TYPE:
     case UNION_TYPE:
       gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
-      output_constructor (exp, size, align, NULL);
-      return;
+      return output_constructor (exp, size, align, NULL);
 
     case ERROR_MARK:
-      return;
+      return 0;
 
     default:
       gcc_unreachable ();
@@ -4626,6 +4777,8 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
 
   if (size > thissize)
     assemble_zeros (size - thissize);
+
+  return size;
 }
 
 \f
@@ -4639,7 +4792,7 @@ array_size_for_constructor (tree val)
   tree max_index;
   unsigned HOST_WIDE_INT cnt;
   tree index, value, tmp;
-  double_int i;
+  offset_int i;
 
   /* This code used to attempt to handle string constants that are not
      arrays of single-bytes, but nothing else does, so there's no point in
@@ -4661,14 +4814,13 @@ array_size_for_constructor (tree val)
 
   /* Compute the total number of array elements.  */
   tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
-  i = tree_to_double_int (max_index) - tree_to_double_int (tmp);
-  i += double_int_one;
+  i = wi::to_offset (max_index) - wi::to_offset (tmp) + 1;
 
   /* Multiply by the array element unit size to find number of bytes.  */
-  i *= tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
+  i *= wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
 
-  gcc_assert (i.fits_uhwi ());
-  return i.low;
+  gcc_assert (wi::fits_uhwi_p (i));
+  return i.to_uhwi ();
 }
 
 /* Other datastructures + helpers for output_constructor.  */
@@ -4679,25 +4831,22 @@ typedef struct {
 
   /* Received arguments.  */
   tree exp;                     /* Constructor expression.  */
+  tree type;                    /* Type of constructor expression.  */
   unsigned HOST_WIDE_INT size;  /* # bytes to output - pad if necessary.  */
   unsigned int align;           /* Known initial alignment.  */
-
-  /* Constructor expression data.  */
-  tree type;       /* Expression type.  */
-  tree field;      /* Current field decl in a record.  */
-  tree min_index;  /* Lower bound if specified for an array.  */
+  tree min_index;               /* Lower bound if specified for an array.  */
 
   /* Output processing state.  */
   HOST_WIDE_INT total_bytes;  /* # bytes output so far / current position.  */
-  bool byte_buffer_in_use;    /* Whether byte ...  */
-  int byte;                   /* ... contains part of a bitfield byte yet to
-                                be output.  */
-
+  int byte;                   /* Part of a bitfield byte yet to be output.  */
   int last_relative_index;    /* Implicit or explicit index of the last
                                 array element output within a bitfield.  */
+  bool byte_buffer_in_use;    /* Whether BYTE is in use.  */
+
   /* Current element.  */
-  tree val;    /* Current element value.  */
-  tree index;  /* Current element index.  */
+  tree field;      /* Current field decl in a record.  */
+  tree val;        /* Current element value.  */
+  tree index;      /* Current element index.  */
 
 } oc_local_state;
 
@@ -4711,9 +4860,9 @@ output_constructor_array_range (oc_local_state *local)
     = int_size_in_bytes (TREE_TYPE (local->type));
 
   HOST_WIDE_INT lo_index
-    = tree_low_cst (TREE_OPERAND (local->index, 0), 0);
+    = tree_to_shwi (TREE_OPERAND (local->index, 0));
   HOST_WIDE_INT hi_index
-    = tree_low_cst (TREE_OPERAND (local->index, 1), 0);
+    = tree_to_shwi (TREE_OPERAND (local->index, 1));
   HOST_WIDE_INT index;
 
   unsigned int align2
@@ -4725,7 +4874,7 @@ output_constructor_array_range (oc_local_state *local)
       if (local->val == NULL_TREE)
        assemble_zeros (fieldsize);
       else
-       output_constant (local->val, fieldsize, align2);
+       fieldsize = output_constant (local->val, fieldsize, align2);
 
       /* Count its size.  */
       local->total_bytes += fieldsize;
@@ -4751,11 +4900,10 @@ output_constructor_regular_field (oc_local_state *local)
         sign-extend the result because Ada has negative DECL_FIELD_OFFSETs
         but we are using an unsigned sizetype.  */
       unsigned prec = TYPE_PRECISION (sizetype);
-      double_int idx = tree_to_double_int (local->index)
-                      - tree_to_double_int (local->min_index);
-      idx = idx.sext (prec);
-      fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
-                 * idx.low);
+      offset_int idx = wi::sext (wi::to_offset (local->index)
+                                - wi::to_offset (local->min_index), prec);
+      fieldpos = (idx * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (local->val))))
+       .to_short_addr ();
     }
   else if (local->field != NULL_TREE)
     fieldpos = int_byte_position (local->field);
@@ -4774,9 +4922,8 @@ output_constructor_regular_field (oc_local_state *local)
      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)
+      && fieldpos > local->total_bytes)
     {
-      gcc_assert (fieldpos >= local->total_bytes);
       assemble_zeros (fieldpos - local->total_bytes);
       local->total_bytes = fieldpos;
     }
@@ -4804,7 +4951,7 @@ output_constructor_regular_field (oc_local_state *local)
          gcc_assert (!fieldsize || !DECL_CHAIN (local->field));
        }
       else
-       fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
+       fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
     }
   else
     fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
@@ -4813,30 +4960,31 @@ output_constructor_regular_field (oc_local_state *local)
   if (local->val == NULL_TREE)
     assemble_zeros (fieldsize);
   else
-    output_constant (local->val, fieldsize, align2);
+    fieldsize = output_constant (local->val, fieldsize, align2);
 
   /* Count its size.  */
   local->total_bytes += fieldsize;
 }
 
-/* Helper for output_constructor.  From the current LOCAL and OUTER states,
-   output an element that is a true bitfield or part of an outer one.  */
+/* Helper for output_constructor.  From the LOCAL state, output an element
+   that is a true bitfield or part of an outer one.  BIT_OFFSET is the offset
+   from the start of a possibly ongoing outer byte buffer.  */
 
 static void
-output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
+output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
 {
   /* 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));
+       ? tree_to_uhwi (DECL_SIZE (local->field))
+       : tree_to_uhwi (TYPE_SIZE (TREE_TYPE (local->type))));
 
   /* 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))
+         ? (tree_to_shwi (local->index)
+            - tree_to_shwi (local->min_index))
          : local->last_relative_index + 1)
        : 0);
 
@@ -4850,7 +4998,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
   /* 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);
+    = bit_offset + 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
@@ -4874,8 +5022,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       return;
     }
 
-  /* If this field does not start in this (or, next) byte,
-     skip some bytes.  */
+  /* 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.  */
@@ -4907,13 +5054,12 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
      pending data, then retrieve the new pending data afterwards.  */
   if (TREE_CODE (local->val) == CONSTRUCTOR)
     {
-      oc_outer_state output_state;
-
-      output_state.bit_offset = next_offset % BITS_PER_UNIT;
-      output_state.byte = local->byte;
+      oc_outer_state temp_state;
+      temp_state.bit_offset = next_offset % BITS_PER_UNIT;
+      temp_state.byte = local->byte;
       local->total_bytes
-         += output_constructor (local->val, 0, 0, &output_state);
-      local->byte = output_state.byte;
+         += output_constructor (local->val, 0, 0, &temp_state);
+      local->byte = temp_state.byte;
       return;
     }
 
@@ -4928,8 +5074,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
       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.  */
+      /* 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);
@@ -4937,39 +5082,31 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
          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);
+      /* 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.  */
+         /* On big-endian machine, take the most significant bits (of the
+            bits that are significant) first 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)
+            the word boundary in the INTEGER_CST.  We can
+            only select bits from one element.  */
+         if ((shift / HOST_BITS_PER_WIDE_INT)
+             != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
            {
-             this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
-             shift = HOST_BITS_PER_WIDE_INT;
+             const int end = shift + this_time - 1;
+             shift = end & -HOST_BITS_PER_WIDE_INT;
+             this_time = end - shift + 1;
            }
 
          /* 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 < HOST_BITS_PER_DOUBLE_INT);
-             value = TREE_INT_CST_HIGH (local->val);
-             shift -= HOST_BITS_PER_WIDE_INT;
-           }
+         value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
+         shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
 
-         /* Get the result. This works only when:
+         /* 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))
@@ -4977,31 +5114,24 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
        }
       else
        {
-         /* On little-endian machines,
-            take first the least significant bits of the value
-            and pack them starting at the least significant
+         /* On little-endian machines, take the least significant bits of
+            the value first 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);
+            the word boundary in the INTEGER_CST.  We can
+            only select bits from one element.  */
+         if ((shift / HOST_BITS_PER_WIDE_INT)
+             != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
+           this_time
+             = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
 
          /* 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 < HOST_BITS_PER_DOUBLE_INT);
-             value = TREE_INT_CST_HIGH (local->val);
-             shift -= HOST_BITS_PER_WIDE_INT;
-           }
+         value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
+         shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
 
-         /* Get the result. This works only when:
+         /* 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))
@@ -5019,7 +5149,7 @@ output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
 
 static unsigned HOST_WIDE_INT
 output_constructor (tree exp, unsigned HOST_WIDE_INT size,
-                   unsigned int align, oc_outer_state * outer)
+                   unsigned int align, oc_outer_state *outer)
 {
   unsigned HOST_WIDE_INT cnt;
   constructor_elt *ce;
@@ -5028,22 +5158,19 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
 
   /* Setup our local state to communicate with helpers.  */
   local.exp = exp;
+  local.type = TREE_TYPE (exp);
   local.size = size;
   local.align = align;
+  if (TREE_CODE (local.type) == ARRAY_TYPE && TYPE_DOMAIN (local.type))
+    local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
+  else
+    local.min_index = NULL_TREE;
 
   local.total_bytes = 0;
   local.byte_buffer_in_use = outer != NULL;
   local.byte = outer ? outer->byte : 0;
-
-  local.type = TREE_TYPE (exp);
-
   local.last_relative_index = -1;
 
-  local.min_index = NULL_TREE;
-  if (TREE_CODE (local.type) == ARRAY_TYPE
-      && TYPE_DOMAIN (local.type) != NULL_TREE)
-    local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
-
   gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
 
   /* As CE goes through the elements of the constant, FIELD goes through the
@@ -5055,9 +5182,10 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
      (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);
+  else
+    local.field = NULL_TREE;
 
   for (cnt = 0;
        vec_safe_iterate (CONSTRUCTOR_ELTS (exp), cnt, &ce);
@@ -5110,7 +5238,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
                            build_nonstandard_integer_type
                            (TYPE_PRECISION (TREE_TYPE (local.val)), 0),
                            local.val);
-         output_constructor_bitfield (&local, outer);
+         output_constructor_bitfield (&local, outer ? outer->bit_offset : 0);
        }
     }
 
@@ -5141,6 +5269,12 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
 static void
 mark_weak (tree decl)
 {
+  if (DECL_WEAK (decl))
+    return;
+
+  struct symtab_node *n = symtab_node::get (decl);
+  if (n && n->refuse_visibility_changes)
+    error ("%+D declared weak after being used", decl);
   DECL_WEAK (decl) = 1;
 
   if (DECL_RTL_SET_P (decl)
@@ -5267,9 +5401,9 @@ weak_finish_1 (tree decl)
 static tree
 find_decl (tree target)
 {
-  symtab_node node = symtab_node_for_asm (target);
+  symtab_node *node = symtab_node::get_for_asmname (target);
   if (node)
-    return node->symbol.decl;
+    return node->decl;
   return NULL_TREE;
 }
 
@@ -5412,20 +5546,26 @@ vec<alias_pair, va_gc> *alias_pairs;
 void
 do_assemble_alias (tree decl, tree target)
 {
+  tree id;
+
   /* Emulated TLS had better not get this var.  */
-  gcc_assert(!(!targetm.have_tls
-              && TREE_CODE (decl) == VAR_DECL
-              && DECL_THREAD_LOCAL_P (decl)));
+  gcc_assert (!(!targetm.have_tls
+               && TREE_CODE (decl) == VAR_DECL
+               && DECL_THREAD_LOCAL_P (decl)));
 
   if (TREE_ASM_WRITTEN (decl))
     return;
 
+  id = DECL_ASSEMBLER_NAME (decl);
+  ultimate_transparent_alias_target (&id);
+
   /* 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 (id) = 1;
 
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
     {
@@ -5436,7 +5576,7 @@ do_assemble_alias (tree decl, tree target)
 
 #ifdef ASM_OUTPUT_WEAKREF
       ASM_OUTPUT_WEAKREF (asm_out_file, decl,
-                         IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+                         IDENTIFIER_POINTER (id),
                          IDENTIFIER_POINTER (target));
 #else
       if (!TARGET_SUPPORTS_WEAK)
@@ -5450,30 +5590,38 @@ do_assemble_alias (tree decl, tree target)
     }
 
 #ifdef ASM_OUTPUT_DEF
+  tree orig_decl = decl;
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node::get (decl)->instrumentation_clone
+      && cgraph_node::get (decl)->instrumented_version)
+    orig_decl = cgraph_node::get (decl)->instrumented_version->decl;
+
   /* Make name accessible from other files, if appropriate.  */
 
-  if (TREE_PUBLIC (decl))
+  if (TREE_PUBLIC (decl) || TREE_PUBLIC (orig_decl))
     {
       globalize_decl (decl);
       maybe_assemble_visibility (decl);
     }
   if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
     {
-#if defined (ASM_OUTPUT_TYPE_DIRECTIVE) && HAVE_GNU_INDIRECT_FUNCTION
-      ASM_OUTPUT_TYPE_DIRECTIVE
-       (asm_out_file, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
-        IFUNC_ASM_TYPE);
-#else
-      error_at (DECL_SOURCE_LOCATION (decl),
-               "ifunc is not supported in this configuration");
+#if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
+      if (targetm.has_ifunc_p ())
+       ASM_OUTPUT_TYPE_DIRECTIVE
+         (asm_out_file, IDENTIFIER_POINTER (id),
+          IFUNC_ASM_TYPE);
+      else
 #endif
+       error_at (DECL_SOURCE_LOCATION (decl),
+                 "ifunc is not supported on this target");
     }
 
 # ifdef ASM_OUTPUT_DEF_FROM_DECLS
   ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
 # else
   ASM_OUTPUT_DEF (asm_out_file,
-                 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+                 IDENTIFIER_POINTER (id),
                  IDENTIFIER_POINTER (target));
 # endif
 #elif defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
@@ -5481,7 +5629,7 @@ do_assemble_alias (tree decl, tree target)
     const char *name;
     tree *p, t;
 
-    name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+    name = IDENTIFIER_POINTER (id);
 # ifdef ASM_WEAKEN_DECL
     ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
 # else
@@ -5490,7 +5638,8 @@ do_assemble_alias (tree decl, tree target)
     /* Remove this function from the pending weak list so that
        we do not emit multiple .weak directives for it.  */
     for (p = &weak_decls; (t = *p) ; )
-      if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
+      if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t))
+         || id == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
        *p = TREE_CHAIN (t);
       else
        p = &TREE_CHAIN (t);
@@ -5499,8 +5648,7 @@ do_assemble_alias (tree decl, tree target)
        list, for the same reason.  */
     for (p = &weakref_targets; (t = *p) ; )
       {
-       if (DECL_ASSEMBLER_NAME (decl)
-           == ultimate_transparent_alias_target (&TREE_VALUE (t)))
+       if (id == ultimate_transparent_alias_target (&TREE_VALUE (t)))
          *p = TREE_CHAIN (t);
        else
          p = &TREE_CHAIN (t);
@@ -5525,13 +5673,6 @@ assemble_alias (tree decl, tree target)
 
       if (alias == target)
        error ("weakref %q+D ultimately targets itself", decl);
-      else
-       {
-#ifndef ASM_OUTPUT_WEAKREF
-         IDENTIFIER_TRANSPARENT_ALIAS (alias) = 1;
-         TREE_CHAIN (alias) = target;
-#endif
-       }
       if (TREE_PUBLIC (decl))
        error ("weakref %q+D must have static linkage", decl);
     }
@@ -5541,6 +5682,7 @@ assemble_alias (tree decl, tree target)
 # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
       error_at (DECL_SOURCE_LOCATION (decl),
                "alias definitions not supported in this configuration");
+      TREE_ASM_WRITTEN (decl) = 1;
       return;
 # else
       if (!DECL_WEAK (decl))
@@ -5551,6 +5693,7 @@ assemble_alias (tree decl, tree target)
          else
            error_at (DECL_SOURCE_LOCATION (decl),
                      "only weak aliases are supported in this configuration");
+         TREE_ASM_WRITTEN (decl) = 1;
          return;
        }
 # endif
@@ -5560,18 +5703,18 @@ assemble_alias (tree decl, tree target)
 
   /* Allow aliases to aliases.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    cgraph_get_create_node (decl)->alias = true;
+    cgraph_node::get_create (decl)->alias = true;
   else
-    varpool_node_for_decl (decl)->alias = true;
+    varpool_node::get_create (decl)->alias = true;
 
   /* If the target has already been emitted, we don't have to queue the
      alias.  This saves a tad of memory.  */
-  if (cgraph_global_info_ready)
+  if (symtab->global_info_ready)
     target_decl = find_decl (target);
   else
     target_decl= NULL;
   if ((target_decl && TREE_ASM_WRITTEN (target_decl))
-      || cgraph_state >= CGRAPH_STATE_EXPANSION)
+      || symtab->state >= EXPANSION)
     do_assemble_alias (decl, target);
   else
     {
@@ -5595,7 +5738,7 @@ record_tm_clone_pair (tree o, tree n)
   if (tm_clone_hash == NULL)
     tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
 
-  h = ggc_alloc_tree_map ();
+  h = ggc_alloc<tree_map> ();
   h->hash = htab_hash_pointer (o);
   h->base.from = o;
   h->to = n;
@@ -5656,8 +5799,8 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
     {
       tree src = p->from;
       tree dst = p->to;
-      struct cgraph_node *src_n = cgraph_get_node (src);
-      struct cgraph_node *dst_n = cgraph_get_node (dst);
+      struct cgraph_node *src_n = cgraph_node::get (src);
+      struct cgraph_node *dst_n = cgraph_node::get (dst);
 
       /* The function ipa_tm_create_version() marks the clone as needed if
         the original function was needed.  But we also mark the clone as
@@ -5665,12 +5808,12 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
         TM_GETTMCLONE.  If neither of these are true, we didn't generate
         a clone, and we didn't call it indirectly... no sense keeping it
         in the clone table.  */
-      if (!dst_n || !dst_n->analyzed)
+      if (!dst_n || !dst_n->definition)
        continue;
 
       /* This covers the case where we have optimized the original
         function away, and only access the transactional clone.  */
-      if (!src_n || !src_n->analyzed)
+      if (!src_n || !src_n->definition)
        continue;
 
       if (!switched)
@@ -5681,9 +5824,9 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
        }
 
       assemble_integer (XEXP (DECL_RTL (src), 0),
-                       POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+                       POINTER_SIZE_UNITS, POINTER_SIZE, 1);
       assemble_integer (XEXP (DECL_RTL (dst), 0),
-                       POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+                       POINTER_SIZE_UNITS, POINTER_SIZE, 1);
     }
 }
 
@@ -5758,8 +5901,9 @@ default_assemble_visibility (tree decl ATTRIBUTE_UNUSED,
   assemble_name (asm_out_file, name);
   fprintf (asm_out_file, "\n");
 #else
-  warning (OPT_Wattributes, "visibility attribute not supported "
-          "in this configuration; ignored");
+  if (!DECL_ARTIFICIAL (decl))
+    warning (OPT_Wattributes, "visibility attribute not supported "
+            "in this configuration; ignored");
 #endif
 }
 
@@ -5770,6 +5914,12 @@ maybe_assemble_visibility (tree decl)
 {
   enum symbol_visibility vis = DECL_VISIBILITY (decl);
 
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node::get (decl)
+      && cgraph_node::get (decl)->instrumentation_clone
+      && cgraph_node::get (decl)->instrumented_version)
+    vis = DECL_VISIBILITY (cgraph_node::get (decl)->instrumented_version->decl);
+
   if (vis != VISIBILITY_DEFAULT)
     {
       targetm.asm_out.assemble_visibility (decl, vis);
@@ -5798,20 +5948,27 @@ supports_one_only (void)
 void
 make_decl_one_only (tree decl, tree comdat_group)
 {
+  struct symtab_node *symbol;
   gcc_assert (TREE_CODE (decl) == VAR_DECL
              || TREE_CODE (decl) == FUNCTION_DECL);
 
   TREE_PUBLIC (decl) = 1;
 
+  if (TREE_CODE (decl) == VAR_DECL)
+    symbol = varpool_node::get_create (decl);
+  else
+    symbol = cgraph_node::get_create (decl);
+
   if (SUPPORTS_ONE_ONLY)
     {
 #ifdef MAKE_DECL_ONE_ONLY
       MAKE_DECL_ONE_ONLY (decl);
 #endif
-      DECL_COMDAT_GROUP (decl) = comdat_group;
+      symbol->set_comdat_group (comdat_group);
     }
   else if (TREE_CODE (decl) == VAR_DECL
-      && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+           && (DECL_INITIAL (decl) == 0
+              || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
     DECL_COMMON (decl) = 1;
   else
     {
@@ -5823,14 +5980,10 @@ make_decl_one_only (tree decl, tree comdat_group)
 void
 init_varasm_once (void)
 {
-  section_htab = htab_create_ggc (31, section_entry_hash,
-                                 section_entry_eq, NULL);
-  object_block_htab = htab_create_ggc (31, object_block_entry_hash,
-                                      object_block_entry_eq, NULL);
-  const_desc_htab = htab_create_ggc (1009, const_desc_hash,
-                                    const_desc_eq, NULL);
+  section_htab = hash_table<section_hasher>::create_ggc (31);
+  object_block_htab = hash_table<object_block_hasher>::create_ggc (31);
+  const_desc_htab = hash_table<tree_descriptor_hasher>::create_ggc (1009);
 
-  const_alias_set = new_alias_set ();
   shared_constant_pool = create_constant_pool ();
 
 #ifdef TEXT_SECTION_ASM_OP
@@ -5891,6 +6044,10 @@ init_varasm_once (void)
 
   if (readonly_data_section == NULL)
     readonly_data_section = text_section;
+
+#ifdef ASM_OUTPUT_EXTERNAL
+  pending_assemble_externals_set = new hash_set<tree>;
+#endif
 }
 
 enum tls_model
@@ -5954,7 +6111,10 @@ default_section_type_flags (tree decl, const char *name, int reloc)
        flags |= SECTION_RELRO;
     }
 
-  if (decl && DECL_ONE_ONLY (decl))
+  if (decl && DECL_P (decl) && DECL_COMDAT_GROUP (decl))
+    flags |= SECTION_LINKONCE;
+
+  if (strcmp (name, ".vtable_map_vars") == 0)
     flags |= SECTION_LINKONCE;
 
   if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
@@ -5963,6 +6123,7 @@ default_section_type_flags (tree decl, const char *name, int reloc)
   if (strcmp (name, ".bss") == 0
       || strncmp (name, ".bss.", 5) == 0
       || strncmp (name, ".gnu.linkonce.b.", 16) == 0
+      || strcmp (name, ".persistent.bss") == 0
       || strcmp (name, ".sbss") == 0
       || strncmp (name, ".sbss.", 6) == 0
       || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
@@ -6038,8 +6199,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
 
   if (!(flags & SECTION_DEBUG))
     *f++ = 'a';
+#if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
   if (flags & SECTION_EXCLUDE)
     *f++ = 'e';
+#endif
   if (flags & SECTION_WRITE)
     *f++ = 'w';
   if (flags & SECTION_CODE)
@@ -6157,7 +6320,9 @@ categorize_decl_for_section (const_tree decl, int reloc)
     return SECCAT_TEXT;
   else if (TREE_CODE (decl) == STRING_CST)
     {
-      if (flag_mudflap) /* or !flag_merge_constants */
+      if ((flag_sanitize & SANITIZE_ADDRESS)
+         && asan_protect_global (CONST_CAST_TREE (decl)))
+      /* or !flag_merge_constants */
         return SECCAT_RODATA;
       else
        return SECCAT_RODATA_MERGE_STR;
@@ -6181,7 +6346,9 @@ categorize_decl_for_section (const_tree decl, int reloc)
        }
       else if (reloc & targetm.asm_out.reloc_rw_mask ())
        ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
-      else if (reloc || flag_merge_constants < 2)
+      else if (reloc || flag_merge_constants < 2
+              || ((flag_sanitize & SANITIZE_ADDRESS)
+                  && asan_protect_global (CONST_CAST_TREE (decl))))
        /* C and C++ don't allow different variables to share the same
           location.  -fmerge-all-constants allows even that (at the
           expense of not conforming).  */
@@ -6310,8 +6477,6 @@ default_elf_select_section (tree decl, int reloc,
       gcc_unreachable ();
     }
 
-  if (!DECL_P (decl))
-    decl = NULL_TREE;
   return get_named_section (decl, sname, reloc);
 }
 
@@ -6325,6 +6490,7 @@ default_unique_section (tree decl, int reloc)
   bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
   const char *prefix, *name, *linkonce;
   char *string;
+  tree id;
 
   switch (categorize_decl_for_section (decl, reloc))
     {
@@ -6374,7 +6540,9 @@ default_unique_section (tree decl, int reloc)
       gcc_unreachable ();
     }
 
-  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  id = DECL_ASSEMBLER_NAME (decl);
+  ultimate_transparent_alias_target (&id);
+  name = IDENTIFIER_POINTER (id);
   name = targetm.strip_name_encoding (name);
 
   /* If we're using one_only, then there needs to be a .gnu.linkonce
@@ -6383,47 +6551,46 @@ default_unique_section (tree decl, int reloc)
 
   string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
-  DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
+  set_decl_section_name (decl, string);
 }
 
-/* Like compute_reloc_for_constant, except for an RTX.  The return value
-   is a mask for which bit 1 indicates a global relocation, and bit 0
-   indicates a local relocation.  */
+/* Subroutine of compute_reloc_for_rtx for leaf rtxes.  */
 
 static int
-compute_reloc_for_rtx_1 (rtx *xp, void *data)
+compute_reloc_for_rtx_1 (const_rtx x)
 {
-  int *preloc = (int *) data;
-  rtx x = *xp;
-
   switch (GET_CODE (x))
     {
     case SYMBOL_REF:
-      *preloc |= SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
-      break;
+      return SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
     case LABEL_REF:
-      *preloc |= 1;
-      break;
+      return 1;
     default:
-      break;
+      return 0;
     }
-
-  return 0;
 }
 
+/* Like compute_reloc_for_constant, except for an RTX.  The return value
+   is a mask for which bit 1 indicates a global relocation, and bit 0
+   indicates a local relocation.  */
+
 static int
-compute_reloc_for_rtx (rtx x)
+compute_reloc_for_rtx (const_rtx x)
 {
-  int reloc;
-
   switch (GET_CODE (x))
     {
-    case CONST:
     case SYMBOL_REF:
     case LABEL_REF:
-      reloc = 0;
-      for_each_rtx (&x, compute_reloc_for_rtx_1, &reloc);
-      return reloc;
+      return compute_reloc_for_rtx_1 (x);
+
+    case CONST:
+      {
+       int reloc = 0;
+       subrtx_iterator::array_type array;
+       FOR_EACH_SUBRTX (iter, array, x, ALL)
+         reloc |= compute_reloc_for_rtx_1 (*iter);
+       return reloc;
+      }
 
     default:
       return 0;
@@ -6431,7 +6598,7 @@ compute_reloc_for_rtx (rtx x)
 }
 
 section *
-default_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
+default_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
                            rtx x,
                            unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
 {
@@ -6442,7 +6609,7 @@ default_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
 }
 
 section *
-default_elf_select_rtx_section (enum machine_mode mode, rtx x,
+default_elf_select_rtx_section (machine_mode mode, rtx x,
                                unsigned HOST_WIDE_INT align)
 {
   int reloc = compute_reloc_for_rtx (x);
@@ -6539,9 +6706,9 @@ default_use_anchors_for_symbol_p (const_rtx symbol)
   decl = SYMBOL_REF_DECL (symbol);
   if (decl && DECL_P (decl))
     {
-      /* Don't use section anchors for decls that might be defined by
-        other modules.  */
-      if (!targetm.binds_local_p (decl))
+      /* Don't use section anchors for decls that might be defined or
+        usurped by other modules.  */
+      if (TREE_PUBLIC (decl) && !decl_binds_to_current_def_p (decl))
        return false;
 
       /* Don't use section anchors for decls that will be placed in a
@@ -6604,21 +6771,21 @@ default_binds_local_p_1 (const_tree exp, int shlib)
   if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
       && (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
     {
-      struct varpool_node *vnode = varpool_get_node (exp);
-      if (vnode && resolution_local_p (vnode->symbol.resolution))
+      varpool_node *vnode = varpool_node::get (exp);
+      if (vnode && (resolution_local_p (vnode->resolution) || vnode->in_other_partition))
        resolved_locally = true;
       if (vnode
-         && resolution_to_local_definition_p (vnode->symbol.resolution))
+         && resolution_to_local_definition_p (vnode->resolution))
        resolved_to_local_def = true;
     }
   else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
     {
-      struct cgraph_node *node = cgraph_get_node (exp);
+      struct cgraph_node *node = cgraph_node::get (exp);
       if (node
-         && resolution_local_p (node->symbol.resolution))
+         && (resolution_local_p (node->resolution) || node->in_other_partition))
        resolved_locally = true;
       if (node
-         && resolution_to_local_definition_p (node->symbol.resolution))
+         && resolution_to_local_definition_p (node->resolution))
        resolved_to_local_def = true;
     }
 
@@ -6664,7 +6831,7 @@ default_binds_local_p_1 (const_tree exp, int shlib)
   else if (DECL_COMMON (exp)
           && !resolved_locally
           && (DECL_INITIAL (exp) == NULL
-              || DECL_INITIAL (exp) == error_mark_node))
+              || (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
     local_p = false;
   /* Otherwise we're left with initialized (or non-common) global data
      which is of necessity defined locally.  */
@@ -6686,34 +6853,44 @@ default_binds_local_p_1 (const_tree exp, int shlib)
    definition from different object file) and when resolution info is available
    we simply use the knowledge passed to us by linker plugin.  */
 bool
-decl_binds_to_current_def_p (tree decl)
+decl_binds_to_current_def_p (const_tree decl)
 {
   gcc_assert (DECL_P (decl));
-  if (!TREE_PUBLIC (decl))
-    return true;
   if (!targetm.binds_local_p (decl))
     return false;
+  if (!TREE_PUBLIC (decl))
+    return true;
   /* When resolution is available, just use it.  */
   if (TREE_CODE (decl) == VAR_DECL
       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
     {
-      struct varpool_node *vnode = varpool_get_node (decl);
+      varpool_node *vnode = varpool_node::get (decl);
       if (vnode
-         && vnode->symbol.resolution != LDPR_UNKNOWN)
-       return resolution_to_local_definition_p (vnode->symbol.resolution);
+         && vnode->resolution != LDPR_UNKNOWN)
+       return resolution_to_local_definition_p (vnode->resolution);
     }
   else if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      struct cgraph_node *node = cgraph_get_node (decl);
+      struct cgraph_node *node = cgraph_node::get (decl);
       if (node
-         && node->symbol.resolution != LDPR_UNKNOWN)
-       return resolution_to_local_definition_p (node->symbol.resolution);
+         && node->resolution != LDPR_UNKNOWN)
+       return resolution_to_local_definition_p (node->resolution);
     }
   /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
-     binds locally but still can be overwritten).
+     binds locally but still can be overwritten), DECL_COMMON (can be merged
+     with a non-common definition somewhere in the same module) or
+     DECL_EXTERNAL.
      This rely on fact that binds_local_p behave as decl_replaceable_p
      for all other declaration types.  */
-  return !DECL_WEAK (decl);
+  if (DECL_WEAK (decl))
+    return false;
+  if (DECL_COMMON (decl)
+      && (DECL_INITIAL (decl) == NULL
+         || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
+    return false;
+  if (DECL_EXTERNAL (decl))
+    return false;
+  return true;
 }
 
 /* A replaceable function or variable is one which may be replaced
@@ -6732,6 +6909,9 @@ decl_replaceable_p (tree decl)
   gcc_assert (DECL_P (decl));
   if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl))
     return false;
+  if (!flag_semantic_interposition
+      && !DECL_WEAK (decl))
+    return false;
   return !decl_binds_to_current_def_p (decl);
 }
 
@@ -6931,14 +7111,34 @@ place_block_symbol (rtx symbol)
       decl = SYMBOL_REF_DECL (symbol);
       alignment = DECL_ALIGN (decl);
       size = get_constant_size (DECL_INITIAL (decl));
+      if ((flag_sanitize & SANITIZE_ADDRESS)
+         && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+         && asan_protect_global (DECL_INITIAL (decl)))
+       size += asan_red_zone_size (size);
     }
   else
     {
+      struct symtab_node *snode;
       decl = SYMBOL_REF_DECL (symbol);
-      alignment = DECL_ALIGN (decl);
-      size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
-      if (flag_asan && asan_protect_global (decl))
-       size += asan_red_zone_size (size);
+
+      snode = symtab_node::get (decl);
+      if (snode->alias)
+       {
+         rtx target = DECL_RTL (snode->ultimate_alias_target ()->decl);
+
+         place_block_symbol (target);
+         SYMBOL_REF_BLOCK_OFFSET (symbol) = SYMBOL_REF_BLOCK_OFFSET (target);
+         return;
+       }
+      alignment = get_variable_align (decl);
+      size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
+      if ((flag_sanitize & SANITIZE_ADDRESS)
+         && asan_protect_global (decl))
+       {
+         size += asan_red_zone_size (size);
+         alignment = MAX (alignment,
+                          ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
+       }
     }
 
   /* Calculate the object's offset from the start of the block.  */
@@ -7077,16 +7277,35 @@ output_object_block (struct object_block *block)
        }
       else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
        {
+         HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
          assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
                                      DECL_ALIGN (decl));
-         offset += get_constant_size (DECL_INITIAL (decl));
+         size = get_constant_size (DECL_INITIAL (decl));
+         offset += size;
+         if ((flag_sanitize & SANITIZE_ADDRESS)
+             && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+             && asan_protect_global (DECL_INITIAL (decl)))
+           {
+             size = asan_red_zone_size (size);
+             assemble_zeros (size);
+             offset += size;
+           }
        }
       else
        {
+         HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
          assemble_variable_contents (decl, XSTR (symbol, 0), false);
-         offset += tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+         size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
+         offset += size;
+         if ((flag_sanitize & SANITIZE_ADDRESS)
+             && asan_protect_global (decl))
+           {
+             size = asan_red_zone_size (size);
+             assemble_zeros (size);
+             offset += size;
+           }
        }
     }
 }
@@ -7094,10 +7313,10 @@ output_object_block (struct object_block *block)
 /* A htab_traverse callback used to call output_object_block for
    each member of object_block_htab.  */
 
-static int
-output_object_block_htab (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+output_object_block_htab (object_block **slot, void *)
 {
-  output_object_block ((struct object_block *) (*slot));
+  output_object_block (*slot);
   return 1;
 }
 
@@ -7106,7 +7325,7 @@ output_object_block_htab (void **slot, void *data ATTRIBUTE_UNUSED)
 void
 output_object_blocks (void)
 {
-  htab_traverse (object_block_htab, output_object_block_htab, NULL);
+  object_block_htab->traverse<void *, output_object_block_htab> (NULL);
 }
 
 /* This function provides a possible implementation of the
@@ -7225,7 +7444,7 @@ rtx
 make_debug_expr_from_rtl (const_rtx exp)
 {
   tree ddecl = make_node (DEBUG_EXPR_DECL), type;
-  enum machine_mode mode = GET_MODE (exp);
+  machine_mode mode = GET_MODE (exp);
   rtx dval;
 
   DECL_ARTIFICIAL (ddecl) = 1;
@@ -7432,10 +7651,10 @@ default_asm_output_ident_directive (const char *ident_str)
      to asm_out_file.  Instead, add a fake top-level asm statement.
      This allows the front ends to use this hook without actually
      writing to asm_out_file, to handle #ident or Pragma Ident.  */
-  if (cgraph_state == CGRAPH_STATE_PARSING)
+  if (symtab->state == PARSING)
     {
       char *buf = ACONCAT ((ident_asm_op, "\"", ident_str, "\"\n", NULL));
-      add_asm_node (build_string (strlen (buf), buf));
+      symtab->finalize_toplevel_asm (build_string (strlen (buf), buf));
     }
   else
     fprintf (asm_out_file, "%s\"%s\"\n", ident_asm_op, ident_str);