Daily bump.
[gcc.git] / gcc / stor-layout.c
index 85937d070b4cded2e687aca651e99852514fa877..ee1cf55df90e2948df52f6d90b7e3d6741a4d399 100644 (file)
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "attribs.h"
 #include "debug.h"
+#include "calls.h"
 
 /* Data type for the expressions representing sizes of data types.
    It is the first integer type laid out.  */
@@ -392,6 +393,9 @@ int_mode_for_mode (machine_mode mode)
     case MODE_VECTOR_UACCUM:
       return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
 
+    case MODE_OPAQUE:
+       return opt_scalar_int_mode ();
+
     case MODE_RANDOM:
       if (mode == BLKmode)
        return opt_scalar_int_mode ();
@@ -514,18 +518,43 @@ mode_for_vector (scalar_mode innermode, poly_uint64 nunits)
   return opt_machine_mode ();
 }
 
-/* Return the mode for a vector that has NUNITS integer elements of
-   INT_BITS bits each, if such a mode exists.  The mode can be either
-   an integer mode or a vector mode.  */
+/* If a piece of code is using vector mode VECTOR_MODE and also wants
+   to operate on elements of mode ELEMENT_MODE, return the vector mode
+   it should use for those elements.  If NUNITS is nonzero, ensure that
+   the mode has exactly NUNITS elements, otherwise pick whichever vector
+   size pairs the most naturally with VECTOR_MODE; this may mean choosing
+   a mode with a different size and/or number of elements, depending on
+   what the target prefers.  Return an empty opt_machine_mode if there
+   is no supported vector mode with the required properties.
+
+   Unlike mode_for_vector. any returned mode is guaranteed to satisfy
+   both VECTOR_MODE_P and targetm.vector_mode_supported_p.  */
+
+opt_machine_mode
+related_vector_mode (machine_mode vector_mode, scalar_mode element_mode,
+                    poly_uint64 nunits)
+{
+  gcc_assert (VECTOR_MODE_P (vector_mode));
+  return targetm.vectorize.related_mode (vector_mode, element_mode, nunits);
+}
+
+/* If a piece of code is using vector mode VECTOR_MODE and also wants
+   to operate on integer vectors with the same element size and number
+   of elements, return the vector mode it should use.  Return an empty
+   opt_machine_mode if there is no supported vector mode with the
+   required properties.
+
+   Unlike mode_for_vector. any returned mode is guaranteed to satisfy
+   both VECTOR_MODE_P and targetm.vector_mode_supported_p.  */
 
 opt_machine_mode
-mode_for_int_vector (unsigned int int_bits, poly_uint64 nunits)
+related_int_vector_mode (machine_mode vector_mode)
 {
+  gcc_assert (VECTOR_MODE_P (vector_mode));
   scalar_int_mode int_mode;
-  machine_mode vec_mode;
-  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
-      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
-    return vec_mode;
+  if (int_mode_for_mode (GET_MODE_INNER (vector_mode)).exists (&int_mode))
+    return related_vector_mode (vector_mode, int_mode,
+                               GET_MODE_NUNITS (vector_mode));
   return opt_machine_mode ();
 }
 
@@ -755,19 +784,24 @@ layout_decl (tree decl, unsigned int known_align)
     DECL_SIZE_UNIT (decl) = variable_size (DECL_SIZE_UNIT (decl));
 
   /* If requested, warn about definitions of large data objects.  */
-  if ((code == VAR_DECL || code == PARM_DECL)
-      && ! DECL_EXTERNAL (decl))
+  if ((code == PARM_DECL || (code == VAR_DECL && !DECL_NONLOCAL_FRAME (decl)))
+      && !DECL_EXTERNAL (decl))
     {
       tree size = DECL_SIZE_UNIT (decl);
 
-      if (size != 0 && TREE_CODE (size) == INTEGER_CST
-         && compare_tree_int (size, warn_larger_than_size) > 0)
+      if (size != 0 && TREE_CODE (size) == INTEGER_CST)
        {
-         unsigned HOST_WIDE_INT uhwisize = tree_to_uhwi (size);
-
-         warning (OPT_Wlarger_than_, "size of %q+D %wu bytes exceeds "
-                  "maximum object size %wu",
-                  decl, uhwisize, warn_larger_than_size);
+         /* -Wlarger-than= argument of HOST_WIDE_INT_MAX is treated
+            as if PTRDIFF_MAX had been specified, with the value
+            being that on the target rather than the host.  */
+         unsigned HOST_WIDE_INT max_size = warn_larger_than_size;
+         if (max_size == HOST_WIDE_INT_MAX)
+           max_size = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+
+         if (compare_tree_int (size, max_size) > 0)
+           warning (OPT_Wlarger_than_, "size of %q+D %E bytes exceeds "
+                    "maximum object size %wu",
+                    decl, size, max_size);
        }
     }
 
@@ -1310,7 +1344,8 @@ place_field (record_layout_info rli, tree field)
         Bump the cumulative size to multiple of field alignment.  */
 
       if (!targetm.ms_bitfield_layout_p (rli->t)
-          && DECL_SOURCE_LOCATION (field) != BUILTINS_LOCATION)
+         && DECL_SOURCE_LOCATION (field) != BUILTINS_LOCATION
+         && !TYPE_ARTIFICIAL (rli->t))
        warning (OPT_Wpadded, "padding struct to align %q+D", field);
 
       /* If the alignment is still within offset_align, just align
@@ -1681,14 +1716,21 @@ place_field (record_layout_info rli, tree field)
     {
       rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
 
-      /* If we ended a bitfield before the full length of the type then
-        pad the struct out to the full length of the last type.  */
-      if ((DECL_CHAIN (field) == NULL
-          || TREE_CODE (DECL_CHAIN (field)) != FIELD_DECL)
-         && DECL_BIT_FIELD_TYPE (field)
+      /* If FIELD is the last field and doesn't end at the full length
+        of the type then pad the struct out to the full length of the
+        last type.  */
+      if (DECL_BIT_FIELD_TYPE (field)
          && !integer_zerop (DECL_SIZE (field)))
-       rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
-                                 bitsize_int (rli->remaining_in_alignment));
+       {
+         /* We have to scan, because non-field DECLS are also here.  */
+         tree probe = field;
+         while ((probe = DECL_CHAIN (probe)))
+           if (TREE_CODE (probe) == FIELD_DECL)
+             break;
+         if (!probe)
+           rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
+                                     bitsize_int (rli->remaining_in_alignment));
+       }
 
       normalize_rli (rli);
     }
@@ -1737,7 +1779,8 @@ finalize_record_size (record_layout_info rli)
 
   if (TREE_CONSTANT (unpadded_size)
       && simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0
-      && input_location != BUILTINS_LOCATION)
+      && input_location != BUILTINS_LOCATION
+      && !TYPE_ARTIFICIAL (rli->t))
     warning (OPT_Wpadded, "padding struct size to alignment boundary");
 
   if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
@@ -1798,7 +1841,8 @@ compute_record_mode (tree type)
      line.  */
   SET_TYPE_MODE (type, BLKmode);
 
-  if (! tree_fits_uhwi_p (TYPE_SIZE (type)))
+  poly_uint64 type_size;
+  if (!poly_int_tree_p (TYPE_SIZE (type), &type_size))
     return;
 
   /* A record which has any BLKmode members must itself be
@@ -1809,20 +1853,27 @@ compute_record_mode (tree type)
       if (TREE_CODE (field) != FIELD_DECL)
        continue;
 
+      poly_uint64 field_size;
       if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK
          || (TYPE_MODE (TREE_TYPE (field)) == BLKmode
              && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))
              && !(TYPE_SIZE (TREE_TYPE (field)) != 0
                   && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
-         || ! tree_fits_uhwi_p (bit_position (field))
+         || !tree_fits_poly_uint64_p (bit_position (field))
          || DECL_SIZE (field) == 0
-         || ! tree_fits_uhwi_p (DECL_SIZE (field)))
+         || !poly_int_tree_p (DECL_SIZE (field), &field_size))
        return;
 
       /* If this field is the whole struct, remember its mode so
         that, say, we can put a double in a class into a DF
         register instead of forcing it to live in the stack.  */
-      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+      if (known_eq (field_size, type_size)
+         /* Partial int types (e.g. __int20) may have TYPE_SIZE equal to
+            wider types (e.g. int32), despite precision being less.  Ensure
+            that the TYPE_MODE of the struct does not get set to the partial
+            int mode if there is a wider type also in the struct.  */
+         && known_gt (GET_MODE_PRECISION (DECL_MODE (field)),
+                      GET_MODE_PRECISION (mode)))
        mode = DECL_MODE (field);
 
       /* With some targets, it is sub-optimal to access an aligned
@@ -1832,12 +1883,18 @@ compute_record_mode (tree type)
     }
 
   /* If we only have one real field; use its mode if that mode's size
-     matches the type's size.  This only applies to RECORD_TYPE.  This
-     does not apply to unions.  */
-  poly_uint64 type_size;
-  if (TREE_CODE (type) == RECORD_TYPE
+     matches the type's size.  This generally only applies to RECORD_TYPE.
+     For UNION_TYPE, if the widest field is MODE_INT then use that mode.
+     If the widest field is MODE_PARTIAL_INT, and the union will be passed
+     by reference, then use that mode.  */
+  if ((TREE_CODE (type) == RECORD_TYPE
+       || (TREE_CODE (type) == UNION_TYPE
+          && (GET_MODE_CLASS (mode) == MODE_INT
+              || (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+                  && (targetm.calls.pass_by_reference
+                      (pack_cumulative_args (0),
+                       function_arg_info (type, mode, /*named=*/false)))))))
       && mode != VOIDmode
-      && poly_int_tree_p (TYPE_SIZE (type), &type_size)
       && known_eq (GET_MODE_BITSIZE (mode), type_size))
     ;
   else
@@ -2525,10 +2582,19 @@ layout_type (tree type)
            /* If TYPE_SIZE_UNIT overflowed, then it is certainly larger than
               TYPE_ALIGN_UNIT.  */
            && !TREE_OVERFLOW (TYPE_SIZE_UNIT (element))
-           && !integer_zerop (TYPE_SIZE_UNIT (element))
-           && compare_tree_int (TYPE_SIZE_UNIT (element),
-                                TYPE_ALIGN_UNIT (element)) < 0)
-         error ("alignment of array elements is greater than element size");
+           && !integer_zerop (TYPE_SIZE_UNIT (element)))
+         {
+           if (compare_tree_int (TYPE_SIZE_UNIT (element),
+                                 TYPE_ALIGN_UNIT (element)) < 0)
+             error ("alignment of array elements is greater than "
+                    "element size");
+           else if (TYPE_ALIGN_UNIT (element) > 1
+                    && (wi::zext (wi::to_wide (TYPE_SIZE_UNIT (element)),
+                                 ffs_hwi (TYPE_ALIGN_UNIT (element)) - 1)
+                        != 0))
+             error ("size of array element is not a multiple of its "
+                    "alignment");
+         }
        break;
       }
 
@@ -2691,10 +2757,12 @@ initialize_sizetypes (void)
       for (i = 0; i < NUM_INT_N_ENTS; i++)
        if (int_n_enabled_p[i])
          {
-           char name[50];
+           char name[50], altname[50];
            sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+           sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
 
-           if (strcmp (name, SIZETYPE) == 0)
+           if (strcmp (name, SIZETYPE) == 0
+               || strcmp (altname, SIZETYPE) == 0)
              {
                precision = int_n_data[i].bitsize;
              }