]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/varasm.c
* doc/extend.texi (Common Function Attributes): Clarify
[thirdparty/gcc.git] / gcc / varasm.c
index 06f41d002fd120e327c2667a083e622e7b47ba67..626a4c9f9a0dfcfc10b6831ed3e9384fe50f5d53 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.
 
@@ -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);
@@ -1858,28 +1865,22 @@ 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 %wu exceeds size %wu",
+                patch_area_entry, patch_area_size);
       patch_area_entry = 0;
     }
 
@@ -1899,7 +1900,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)))
@@ -1974,7 +1976,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)
     {
@@ -2733,10 +2735,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:
@@ -2947,7 +2963,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:
@@ -3051,6 +3069,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;
@@ -3406,6 +3428,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.
 
@@ -3422,24 +3481,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;
 }
@@ -3573,25 +3615,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;
 }
@@ -5331,7 +5356,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;
 
@@ -5363,15 +5388,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
        {
@@ -5388,15 +5411,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;
@@ -5883,7 +5904,7 @@ do_assemble_alias (tree decl, tree target)
       else
 #endif
        error_at (DECL_SOURCE_LOCATION (decl),
-                 "ifunc is not supported on this target");
+                 "%qs is not supported on this target", "ifunc");
     }
 
 # ifdef ASM_OUTPUT_DEF_FROM_DECLS
@@ -5941,9 +5962,9 @@ assemble_alias (tree decl, tree target)
       ultimate_transparent_alias_target (&target);
 
       if (alias == target)
-       error ("weakref %q+D ultimately targets itself", decl);
+       error ("%qs symbol %q+D ultimately targets itself", "weakref", decl);
       if (TREE_PUBLIC (decl))
-       error ("weakref %q+D must have static linkage", decl);
+       error ("%qs symbol %q+D must have static linkage", "weakref", decl);
     }
   else
     {
@@ -5960,7 +5981,7 @@ assemble_alias (tree decl, tree target)
          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");
+                     "%qs is not supported in this configuration", "ifunc");
          else
            error_at (DECL_SOURCE_LOCATION (decl),
                      "only weak aliases are supported in this configuration");
@@ -6995,14 +7016,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.  */
@@ -7611,6 +7631,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