]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/varasm.c
PR c++/87554 - ICE with extern template and reference member.
[thirdparty/gcc.git] / gcc / varasm.c
index 85296b4a2ec44b3b59226cb484ba875986d7efa1..cb43248ec492d8eb3287f24947b9c17b70cd18ac 100644 (file)
@@ -1,5 +1,5 @@
 /* Output variables, constants and external declarations, for GNU compiler.
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -111,7 +111,7 @@ static int compare_constant (const tree, const tree);
 static void output_constant_def_contents (rtx);
 static void output_addressed_constants (tree);
 static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
-                                              unsigned int, bool);
+                                              unsigned int, bool, bool);
 static void globalize_decl (tree);
 static bool decl_readonly_section_1 (enum section_category);
 #ifdef BSS_SECTION_ASM_OP
@@ -363,7 +363,11 @@ use_object_blocks_p (void)
 
 /* Return the object_block structure for section SECT.  Create a new
    structure if we haven't created one already.  Return null if SECT
-   itself is null.  */
+   itself is null.  Return also null for mergeable sections since
+   section anchors can't be used in mergeable sections anyway,
+   because the linker might move objects around, and using the
+   object blocks infrastructure in that case is both a waste and a
+   maintenance burden.  */
 
 static struct object_block *
 get_block_for_section (section *sect)
@@ -373,6 +377,9 @@ get_block_for_section (section *sect)
   if (sect == NULL)
     return NULL;
 
+  if (sect->common.flags & SECTION_MERGE)
+    return NULL;
+
   object_block **slot
     = object_block_htab->find_slot_with_hash (sect, hash_section (sect),
                                              INSERT);
@@ -805,7 +812,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
       && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
       && align <= 256
       && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
-      && TREE_STRING_LENGTH (decl) >= len)
+      && TREE_STRING_LENGTH (decl) == len)
     {
       scalar_int_mode mode;
       unsigned int modesize;
@@ -823,6 +830,9 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
          if (align < modesize)
            align = modesize;
 
+         if (!HAVE_LD_ALIGNED_SHF_MERGE && align > 8)
+           return readonly_data_section;
+
          str = TREE_STRING_POINTER (decl);
          unit = GET_MODE_SIZE (mode);
 
@@ -835,7 +845,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
              if (j == unit)
                break;
            }
-         if (i == len - unit)
+         if (i == len - unit || (unit == 1 && i == len))
            {
              sprintf (name, "%s.str%d.%d", prefix,
                       modesize / 8, (int) (align / 8));
@@ -861,7 +871,8 @@ mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
       && known_le (GET_MODE_BITSIZE (mode), align)
       && align >= 8
       && align <= 256
-      && (align & (align - 1)) == 0)
+      && (align & (align - 1)) == 0
+      && (HAVE_LD_ALIGNED_SHF_MERGE ? 1 : align == 8))
     {
       const char *prefix = function_mergeable_rodata_prefix ();
       char *name = (char *) alloca (strlen (prefix) + 30);
@@ -1377,10 +1388,6 @@ make_decl_rtl (tree 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
@@ -1805,21 +1812,25 @@ assemble_start_function (tree decl, const char *fnname)
      Note that we still need to align to DECL_ALIGN, as above,
      because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all.  */
   if (! DECL_USER_ALIGN (decl)
-      && align_functions_log > align
+      && align_functions.levels[0].log > align
       && optimize_function_for_speed_p (cfun))
     {
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
-      int align_log = align_functions_log;
+      int align_log = align_functions.levels[0].log;
 #endif
-      int max_skip = align_functions - 1;
+      int max_skip = align_functions.levels[0].maxskip;
       if (flag_limit_function_alignment && crtl->max_insn_address > 0
          && max_skip >= crtl->max_insn_address)
        max_skip = crtl->max_insn_address - 1;
 
 #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
       ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, align_log, max_skip);
+      if (max_skip == align_functions.levels[0].maxskip)
+       ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
+                                  align_functions.levels[1].log,
+                                  align_functions.levels[1].maxskip);
 #else
-      ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
+      ASM_OUTPUT_ALIGN (asm_out_file, align_functions.levels[0].log);
 #endif
     }
 
@@ -1832,10 +1843,7 @@ assemble_start_function (tree decl, const char *fnname)
 
   /* Make function name accessible from other files, if appropriate.  */
 
-  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)))
+  if (TREE_PUBLIC (decl))
     {
       notice_global_symbol (decl);
 
@@ -1857,28 +1865,20 @@ assemble_start_function (tree decl, const char *fnname)
       tree pp_val = TREE_VALUE (patchable_function_entry_attr);
       tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
 
-      if (tree_fits_uhwi_p (patchable_function_entry_value1))
-       patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
-      else
-       gcc_unreachable ();
-
+      patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
       patch_area_entry = 0;
-      if (list_length (pp_val) > 1)
+      if (TREE_CHAIN (pp_val) != NULL_TREE)
        {
-         tree patchable_function_entry_value2 =
-           TREE_VALUE (TREE_CHAIN (pp_val));
-
-         if (tree_fits_uhwi_p (patchable_function_entry_value2))
-           patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
-         else
-           gcc_unreachable ();
+         tree patchable_function_entry_value2
+           = TREE_VALUE (TREE_CHAIN (pp_val));
+         patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
        }
     }
 
   if (patch_area_entry > patch_area_size)
     {
       if (patch_area_size > 0)
-       warning (OPT_Wattributes, "Patchable function entry > size");
+       warning (OPT_Wattributes, "patchable function entry > size");
       patch_area_entry = 0;
     }
 
@@ -1898,7 +1898,8 @@ assemble_start_function (tree decl, const char *fnname)
   /* And the area after the label.  Record it if we haven't done so yet.  */
   if (patch_area_size > patch_area_entry)
     targetm.asm_out.print_patchable_function_entry (asm_out_file,
-                                            patch_area_size-patch_area_entry,
+                                                   patch_area_size
+                                                   - patch_area_entry,
                                                    patch_area_entry == 0);
 
   if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl)))
@@ -1973,7 +1974,7 @@ assemble_zeros (unsigned HOST_WIDE_INT size)
 /* Assemble an alignment pseudo op for an ALIGN-bit boundary.  */
 
 void
-assemble_align (int align)
+assemble_align (unsigned int align)
 {
   if (align > BITS_PER_UNIT)
     {
@@ -2120,7 +2121,7 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect,
 
 static void
 assemble_variable_contents (tree decl, const char *name,
-                           bool dont_output_data)
+                           bool dont_output_data, bool merge_strings)
 {
   /* Do any machine/system dependent processing of the object.  */
 #ifdef ASM_DECLARE_OBJECT_NAME
@@ -2143,7 +2144,7 @@ assemble_variable_contents (tree decl, const char *name,
        output_constant (DECL_INITIAL (decl),
                         tree_to_uhwi (DECL_SIZE_UNIT (decl)),
                         get_variable_align (decl),
-                        false);
+                        false, merge_strings);
       else
        /* Leave space for it.  */
        assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
@@ -2319,7 +2320,9 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
        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);
+      assemble_variable_contents (decl, name, dont_output_data,
+                                 (sect->common.flags & SECTION_MERGE)
+                                 && (sect->common.flags & SECTION_STRINGS));
       if (asan_protected)
        {
          unsigned HOST_WIDE_INT int size
@@ -2404,7 +2407,7 @@ static hash_set<tree> *pending_assemble_externals_set;
 static bool
 incorporeal_function_p (tree decl)
 {
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
+  if (TREE_CODE (decl) == FUNCTION_DECL && fndecl_built_in_p (decl))
     {
       const char *name;
 
@@ -2730,10 +2733,24 @@ integer_asm_op (int size, int aligned_p)
       return targetm.asm_out.byte_op;
     case 2:
       return ops->hi;
+    case 3:
+      return ops->psi;
     case 4:
       return ops->si;
+    case 5:
+    case 6:
+    case 7:
+      return ops->pdi;
     case 8:
       return ops->di;
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+      return ops->pti;
     case 16:
       return ops->ti;
     default:
@@ -2944,7 +2961,9 @@ decode_addr_const (tree exp, struct addr_const *value)
     case COMPLEX_CST:
     case CONSTRUCTOR:
     case INTEGER_CST:
-      x = output_constant_def (target, 1);
+      x = lookup_constant_def (target);
+      /* Should have been added by output_addressed_constants.  */
+      gcc_assert (x);
       break;
 
     case INDIRECT_REF:
@@ -2954,6 +2973,11 @@ decode_addr_const (tree exp, struct addr_const *value)
                       gen_rtx_SYMBOL_REF (Pmode, "origin of addresses"));
       break;
 
+    case COMPOUND_LITERAL_EXPR:
+      gcc_assert (COMPOUND_LITERAL_EXPR_DECL (target));
+      x = DECL_RTL (COMPOUND_LITERAL_EXPR_DECL (target));
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -3043,6 +3067,10 @@ const_hash_1 (const tree exp)
       }
 
     case ADDR_EXPR:
+      if (CONSTANT_CLASS_P (TREE_OPERAND (exp, 0)))
+       return const_hash_1 (TREE_OPERAND (exp, 0));
+
+      /* Fallthru.  */
     case FDESC_EXPR:
       {
        struct addr_const value;
@@ -3149,7 +3177,9 @@ compare_constant (const tree t1, const tree t2)
       return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
 
     case STRING_CST:
-      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
+      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
+         || int_size_in_bytes (TREE_TYPE (t1))
+            != int_size_in_bytes (TREE_TYPE (t2)))
        return 0;
 
       return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
@@ -3306,8 +3336,9 @@ get_constant_size (tree exp)
   HOST_WIDE_INT size;
 
   size = int_size_in_bytes (TREE_TYPE (exp));
-  if (TREE_CODE (exp) == STRING_CST)
-    size = MAX (TREE_STRING_LENGTH (exp), size);
+  gcc_checking_assert (size >= 0);
+  gcc_checking_assert (TREE_CODE (exp) != STRING_CST
+                      || size >= TREE_STRING_LENGTH (exp));
   return size;
 }
 
@@ -3395,6 +3426,43 @@ build_constant_desc (tree exp)
   return desc;
 }
 
+/* Subroutine of output_constant_def and tree_output_constant_def:
+   Add a constant to the hash table that tracks which constants
+   already have labels.  */
+
+static constant_descriptor_tree *
+add_constant_to_table (tree exp)
+{
+  /* The hash table methods may call output_constant_def for addressed
+     constants, so handle them first.  */
+  output_addressed_constants (exp);
+
+  /* Sanity check to catch recursive insertion.  */
+  static bool inserting;
+  gcc_assert (!inserting);
+  inserting = true;
+
+  /* Look up EXP in the table of constant descriptors.  If we didn't
+     find it, create a new one.  */
+  struct constant_descriptor_tree key;
+  key.value = exp;
+  key.hash = const_hash_1 (exp);
+  constant_descriptor_tree **loc
+    = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
+
+  inserting = false;
+
+  struct constant_descriptor_tree *desc = *loc;
+  if (!desc)
+    {
+      desc = build_constant_desc (exp);
+      desc->hash = key.hash;
+      *loc = desc;
+    }
+
+  return desc;
+}
+
 /* Return an rtx representing a reference to constant data in memory
    for the constant expression EXP.
 
@@ -3411,24 +3479,7 @@ build_constant_desc (tree exp)
 rtx
 output_constant_def (tree exp, int defer)
 {
-  struct constant_descriptor_tree *desc;
-  struct constant_descriptor_tree key;
-
-  /* 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);
-  constant_descriptor_tree **loc
-    = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
-
-  desc = *loc;
-  if (desc == 0)
-    {
-      desc = build_constant_desc (exp);
-      desc->hash = key.hash;
-      *loc = desc;
-    }
-
+  struct constant_descriptor_tree *desc = add_constant_to_table (exp);
   maybe_output_constant_def_contents (desc, defer);
   return desc->rtl;
 }
@@ -3471,7 +3522,8 @@ maybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
    constant's alignment in bits.  */
 
 static void
-assemble_constant_contents (tree exp, const char *label, unsigned int align)
+assemble_constant_contents (tree exp, const char *label, unsigned int align,
+                           bool merge_strings)
 {
   HOST_WIDE_INT size;
 
@@ -3481,7 +3533,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
   targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
 
   /* Output the value of EXP.  */
-  output_constant (exp, size, align, false);
+  output_constant (exp, size, align, false, merge_strings);
 
   targetm.asm_out.decl_end ();
 }
@@ -3522,10 +3574,13 @@ output_constant_def_contents (rtx symbol)
                   || (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
                   ? DECL_ALIGN (decl)
                   : symtab_node::get (decl)->definition_alignment ());
-      switch_to_section (get_constant_section (exp, align));
+      section *sect = get_constant_section (exp, align);
+      switch_to_section (sect);
       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);
+      assemble_constant_contents (exp, XSTR (symbol, 0), align,
+                                 (sect->common.flags & SECTION_MERGE)
+                                 && (sect->common.flags & SECTION_STRINGS));
       if (asan_protected)
        {
          HOST_WIDE_INT size = get_constant_size (exp);
@@ -3558,25 +3613,8 @@ lookup_constant_def (tree exp)
 tree
 tree_output_constant_def (tree exp)
 {
-  struct constant_descriptor_tree *desc, key;
-  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);
-  constant_descriptor_tree **loc
-    = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
-
-  desc = *loc;
-  if (desc == 0)
-    {
-      desc = build_constant_desc (exp);
-      desc->hash = key.hash;
-      *loc = desc;
-    }
-
-  decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
+  struct constant_descriptor_tree *desc = add_constant_to_table (exp);
+  tree decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
   varpool_node::finalize_decl (decl);
   return decl;
 }
@@ -3926,7 +3964,6 @@ output_constant_pool_2 (fixed_size_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;
 
@@ -4777,6 +4814,30 @@ initializer_constant_valid_for_bitfield_p (tree value)
   return false;
 }
 
+/* Check if a STRING_CST fits into the field.
+   Tolerate only the case when the NUL termination
+   does not fit into the field.   */
+
+static bool
+check_string_literal (tree string, unsigned HOST_WIDE_INT size)
+{
+  tree type = TREE_TYPE (string);
+  tree eltype = TREE_TYPE (type);
+  unsigned HOST_WIDE_INT elts = tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
+  unsigned HOST_WIDE_INT mem_size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+  int len = TREE_STRING_LENGTH (string);
+
+  if (elts != 1 && elts != 2 && elts != 4)
+    return false;
+  if (len < 0 || len % elts != 0)
+    return false;
+  if (size < (unsigned)len)
+    return false;
+  if (mem_size != size)
+    return false;
+  return true;
+}
+
 /* output_constructor outer state of relevance in recursive calls, typically
    for nested aggregate bitfields.  */
 
@@ -4815,7 +4876,7 @@ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool,
 
 static unsigned HOST_WIDE_INT
 output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
-                bool reverse)
+                bool reverse, bool merge_strings)
 {
   enum tree_code code;
   unsigned HOST_WIDE_INT thissize;
@@ -4912,7 +4973,6 @@ 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:
       cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
       if (reverse)
@@ -4931,10 +4991,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
       break;
 
     case COMPLEX_TYPE:
-      output_constant (TREE_REALPART (exp), thissize / 2, align, reverse);
+      output_constant (TREE_REALPART (exp), thissize / 2, align,
+                      reverse, false);
       output_constant (TREE_IMAGPART (exp), thissize / 2,
                       min_align (align, BITS_PER_UNIT * (thissize / 2)),
-                      reverse);
+                      reverse, false);
       break;
 
     case ARRAY_TYPE:
@@ -4944,8 +5005,12 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
        case CONSTRUCTOR:
          return output_constructor (exp, size, align, reverse, NULL);
        case STRING_CST:
-         thissize
-           = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
+         thissize = (unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp);
+         if (merge_strings
+             && (thissize == 0
+                 || TREE_STRING_POINTER (exp) [thissize - 1] != '\0'))
+           thissize++;
+         gcc_checking_assert (check_string_literal (exp, size));
          assemble_string (TREE_STRING_POINTER (exp), thissize);
          break;
        case VECTOR_CST:
@@ -4954,14 +5019,14 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
            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,
-                            reverse);
+                            reverse, false);
            thissize = elt_size;
            /* Static constants must have a fixed size.  */
            unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant ();
            for (unsigned int i = 1; i < nunits; i++)
              {
                output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
-                                reverse);
+                                reverse, false);
                thissize += elt_size;
              }
            break;
@@ -5082,8 +5147,8 @@ output_constructor_array_range (oc_local_state *local)
       if (local->val == NULL_TREE)
        assemble_zeros (fieldsize);
       else
-       fieldsize
-         = output_constant (local->val, fieldsize, align2, local->reverse);
+       fieldsize = output_constant (local->val, fieldsize, align2,
+                                    local->reverse, false);
 
       /* Count its size.  */
       local->total_bytes += fieldsize;
@@ -5165,6 +5230,8 @@ output_constructor_regular_field (oc_local_state *local)
             on the chain is a TYPE_DECL of the enclosing struct.  */
          const_tree next = DECL_CHAIN (local->field);
          gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
+         tree size = TYPE_SIZE_UNIT (TREE_TYPE (local->val));
+         gcc_checking_assert (compare_tree_int (size, fieldsize) == 0);
        }
       else
        fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
@@ -5176,8 +5243,8 @@ output_constructor_regular_field (oc_local_state *local)
   if (local->val == NULL_TREE)
     assemble_zeros (fieldsize);
   else
-    fieldsize
-      = output_constant (local->val, fieldsize, align2, local->reverse);
+    fieldsize = output_constant (local->val, fieldsize, align2,
+                                local->reverse, false);
 
   /* Count its size.  */
   local->total_bytes += fieldsize;
@@ -5287,7 +5354,7 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
     {
       int this_time;
       int shift;
-      HOST_WIDE_INT value;
+      unsigned HOST_WIDE_INT value;
       HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
       HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
 
@@ -5319,15 +5386,13 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
              this_time = end - shift + 1;
            }
 
-         /* Now get the bits from the appropriate constant word.  */
-         value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
-         shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+         /* Now get the bits we want to insert.  */
+         value = wi::extract_uhwi (wi::to_widest (local->val),
+                                   shift, this_time);
 
          /* Get the result.  This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-         local->byte |= (((value >> shift)
-                          & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-                         << (BITS_PER_UNIT - this_time - next_bit));
+         local->byte |= value << (BITS_PER_UNIT - this_time - next_bit);
        }
       else
        {
@@ -5344,15 +5409,13 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
            this_time
              = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
 
-         /* Now get the bits from the appropriate constant word.  */
-         value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
-         shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
+         /* Now get the bits we want to insert.  */
+         value = wi::extract_uhwi (wi::to_widest (local->val),
+                                   shift, this_time);
 
          /* Get the result.  This works only when:
             1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
-         local->byte |= (((value >> shift)
-                          & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
-                         << next_bit);
+         local->byte |= value << next_bit;
        }
 
       next_offset += this_time;
@@ -5652,7 +5715,8 @@ weak_finish (void)
       tree alias_decl = TREE_PURPOSE (t);
       tree target = ultimate_transparent_alias_target (&TREE_VALUE (t));
 
-      if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl)))
+      if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl))
+         || TREE_SYMBOL_REFERENCED (target))
        /* Remove alias_decl from the weak list, but leave entries for
           the target alone.  */
        target = NULL_TREE;
@@ -5820,11 +5884,6 @@ 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) || TREE_PUBLIC (orig_decl))
@@ -5832,7 +5891,8 @@ do_assemble_alias (tree decl, tree target)
       globalize_decl (decl);
       maybe_assemble_visibility (decl);
     }
-  if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && cgraph_node::get (decl)->ifunc_resolver)
     {
 #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
       if (targetm.has_ifunc_p ())
@@ -5915,7 +5975,9 @@ assemble_alias (tree decl, tree target)
 # else
       if (!DECL_WEAK (decl))
        {
-         if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
+         /* NB: ifunc_resolver isn't set when an error is detected.  */
+         if (TREE_CODE (decl) == FUNCTION_DECL
+             && lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
            error_at (DECL_SOURCE_LOCATION (decl),
                      "ifunc is not supported in this configuration");
          else
@@ -6146,13 +6208,6 @@ int
 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);
@@ -6446,7 +6501,7 @@ 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 HAVE_GAS_SECTION_EXCLUDE
       if (flags & SECTION_EXCLUDE)
        *f++ = 'e';
 #endif
@@ -6959,14 +7014,13 @@ default_asm_output_anchor (rtx symbol)
 bool
 default_use_anchors_for_symbol_p (const_rtx symbol)
 {
-  section *sect;
   tree decl;
+  section *sect = SYMBOL_REF_BLOCK (symbol)->sect;
 
-  /* Don't use anchors for mergeable sections.  The linker might move
-     the objects around.  */
-  sect = SYMBOL_REF_BLOCK (symbol)->sect;
-  if (sect->common.flags & SECTION_MERGE)
-    return false;
+  /* This function should only be called with non-zero SYMBOL_REF_BLOCK,
+     furthermore get_block_for_section should not create object blocks
+     for mergeable sections.  */
+  gcc_checking_assert (sect && !(sect->common.flags & SECTION_MERGE));
 
   /* Don't use anchors for small data sections.  The small data register
      acts as an anchor for such sections.  */
@@ -7047,7 +7101,8 @@ default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
      weakref alias.  */
   if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
       || (TREE_CODE (exp) == FUNCTION_DECL
-         && lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
+         && cgraph_node::get (exp)
+         && cgraph_node::get (exp)->ifunc_resolver))
     return false;
 
   /* Static variables are always local.  */
@@ -7574,6 +7629,7 @@ output_object_block (struct object_block *block)
   else
     switch_to_section (block->sect);
 
+  gcc_checking_assert (!(block->sect->common.flags & SECTION_MERGE));
   assemble_align (block->alignment);
 
   /* Define the values of all anchors relative to the current section
@@ -7600,8 +7656,8 @@ output_object_block (struct object_block *block)
        {
          HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
-         assemble_constant_contents
-              (DECL_INITIAL (decl), XSTR (symbol, 0), DECL_ALIGN (decl));
+         assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
+                                     DECL_ALIGN (decl), false);
 
          size = get_constant_size (DECL_INITIAL (decl));
          offset += size;
@@ -7618,7 +7674,7 @@ output_object_block (struct object_block *block)
        {
          HOST_WIDE_INT size;
          decl = SYMBOL_REF_DECL (symbol);
-         assemble_variable_contents (decl, XSTR (symbol, 0), false);
+         assemble_variable_contents (decl, XSTR (symbol, 0), false, false);
          size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
          offset += size;
          if ((flag_sanitize & SANITIZE_ADDRESS)