OSDN Git Service

* src/powerpc/ffi.c (ffi_prep_cif_machdep <FFI_LINUX64>): Correct
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index d334374..1272a0c 100644 (file)
@@ -203,10 +203,10 @@ variable_size (tree size)
 #define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
 #endif
 
-/* Return the machine mode to use for a nonscalar of SIZE bits.
-   The mode must be in class CLASS, and have exactly that many bits.
-   If LIMIT is nonzero, modes of wider than MAX_FIXED_MODE_SIZE will not
-   be used.  */
+/* Return the machine mode to use for a nonscalar of SIZE bits.  The
+   mode must be in class CLASS, and have exactly that many value bits;
+   it may have padding as well.  If LIMIT is nonzero, modes of wider
+   than MAX_FIXED_MODE_SIZE will not be used.  */
 
 enum machine_mode
 mode_for_size (unsigned int size, enum mode_class class, int limit)
@@ -219,7 +219,7 @@ mode_for_size (unsigned int size, enum mode_class class, int limit)
   /* Get the first mode which has this size, in the specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_BITSIZE (mode) == size)
+    if (GET_MODE_PRECISION (mode) == size)
       return mode;
 
   return BLKmode;
@@ -242,7 +242,7 @@ mode_for_size_tree (tree size, enum mode_class class, int limit)
 }
 
 /* Similar, but never return BLKmode; return the narrowest mode that
-   contains at least the requested number of bits.  */
+   contains at least the requested number of value bits.  */
 
 enum machine_mode
 smallest_mode_for_size (unsigned int size, enum mode_class class)
@@ -253,7 +253,7 @@ smallest_mode_for_size (unsigned int size, enum mode_class class)
      specified class.  */
   for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
-    if (GET_MODE_BITSIZE (mode) >= size)
+    if (GET_MODE_PRECISION (mode) >= size)
       return mode;
 
   abort ();
@@ -298,20 +298,7 @@ int_mode_for_mode (enum machine_mode mode)
 unsigned int
 get_mode_alignment (enum machine_mode mode)
 {
-  unsigned int alignment;
-
-  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
-      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
-    alignment = GET_MODE_UNIT_SIZE (mode);
-  else
-    alignment = GET_MODE_SIZE (mode);
-
-  /* Extract the LSB of the size.  */
-  alignment = alignment & -alignment;
-  alignment *= BITS_PER_UNIT;
-
-  alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
-  return alignment;
+  return MIN (BIGGEST_ALIGNMENT, MAX (1, mode_base_align[mode]*BITS_PER_UNIT));
 }
 
 /* Return the value of VALUE, rounded up to a multiple of DIVISOR.
@@ -344,7 +331,8 @@ do_type_align (tree type, tree decl)
   if (TYPE_ALIGN (type) > DECL_ALIGN (decl))
     {
       DECL_ALIGN (decl) = TYPE_ALIGN (type);
-      DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
+      if (TREE_CODE (decl) == FIELD_DECL)
+       DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
     }
 }
 
@@ -409,6 +397,8 @@ layout_decl (tree decl, unsigned int known_align)
   else
     /* For fields, it's a bit more complicated...  */
     {
+      bool old_user_align = DECL_USER_ALIGN (decl);
+
       if (DECL_BIT_FIELD (decl))
        {
          DECL_BIT_FIELD_TYPE (decl) = type;
@@ -445,7 +435,9 @@ layout_decl (tree decl, unsigned int known_align)
              enum machine_mode xmode
                = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
 
-             if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
+             if (xmode != BLKmode 
+                 && (known_align == 0
+                     || known_align >= GET_MODE_ALIGNMENT (xmode)))
                {
                  DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
                                           DECL_ALIGN (decl));
@@ -462,16 +454,21 @@ layout_decl (tree decl, unsigned int known_align)
        }
       else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))
        /* Don't touch DECL_ALIGN.  For other packed fields, go ahead and
-          round up; we'll reduce it again below.  */;
+          round up; we'll reduce it again below.  We want packing to
+          supersede USER_ALIGN inherited from the type, but defer to
+          alignment explicitly specified on the field decl.  */;
       else
        do_type_align (type, decl);
 
       /* If the field is of variable size, we can't misalign it since we
         have no way to make a temporary to align the result.  But this
         isn't an issue if the decl is not addressable.  Likewise if it
-        is of unknown size.  */
+        is of unknown size.
+
+        Note that do_type_align may set DECL_USER_ALIGN, so we need to
+        check old_user_align instead.  */
       if (DECL_PACKED (decl)
-         && !DECL_USER_ALIGN (decl)
+         && !old_user_align
          && (DECL_NONADDRESSABLE_P (decl)
              || DECL_SIZE_UNIT (decl) == 0
              || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
@@ -515,10 +512,10 @@ layout_decl (tree decl, unsigned int known_align)
          int size_as_int = TREE_INT_CST_LOW (size);
 
          if (compare_tree_int (size, size_as_int) == 0)
-           warning_with_decl (decl, "size of `%s' is %d bytes", size_as_int);
+           warning ("%Jsize of '%D' is %d bytes", decl, decl, size_as_int);
          else
-           warning_with_decl (decl, "size of `%s' is larger than %d bytes",
-                              larger_than_size);
+           warning ("%Jsize of '%D' is larger than %d bytes",
+                     decl, decl, larger_than_size);
        }
     }
 
@@ -883,9 +880,11 @@ place_field (record_layout_info rli, tree field)
          if (TYPE_ALIGN (type) > desired_align)
            {
              if (STRICT_ALIGNMENT)
-               warning_with_decl (field, "packed attribute causes inefficient alignment for `%s'");
+               warning ("%Jpacked attribute causes inefficient alignment "
+                         "for '%D'", field, field);
              else
-               warning_with_decl (field, "packed attribute is unnecessary for `%s'");
+               warning ("%Jpacked attribute is unnecessary for '%D'",
+                        field, field);
            }
        }
       else
@@ -900,7 +899,7 @@ place_field (record_layout_info rli, tree field)
         Bump the cumulative size to multiple of field alignment.  */
 
       if (warn_padded)
-       warning_with_decl (field, "padding struct to align `%s'");
+       warning ("%Jpadding struct to align '%D'", field, field);
 
       /* If the alignment is still within offset_align, just align
         the bit position.  */
@@ -1088,6 +1087,7 @@ place_field (record_layout_info rli, tree field)
                rli->prev_field = NULL;
            }
 
+         rli->offset_align = tree_low_cst (TYPE_SIZE (type), 0);
          normalize_rli (rli);
         }
 
@@ -1314,7 +1314,9 @@ compute_record_mode (tree type)
 
       if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK
          || (TYPE_MODE (TREE_TYPE (field)) == BLKmode
-             && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
+             && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field))
+             && !(TYPE_SIZE (TREE_TYPE (field)) != 0
+                  && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))))
          || ! host_integerp (bit_position (field), 1)
          || DECL_SIZE (field) == 0
          || ! host_integerp (DECL_SIZE (field), 1))
@@ -1953,6 +1955,58 @@ set_sizetype (tree type)
   sizetype_set = 1;
 }
 \f
+/* TYPE is an integral type, i.e., an INTEGRAL_TYPE, ENUMERAL_TYPE,
+   BOOLEAN_TYPE, or CHAR_TYPE.  Set TYPE_MIN_VALUE and TYPE_MAX_VALUE
+   for TYPE, based on the PRECISION and whether or not the TYPE
+   IS_UNSIGNED.  PRECISION need not correspond to a width supported
+   natively by the hardware; for example, on a machine with 8-bit,
+   16-bit, and 32-bit register modes, PRECISION might be 7, 23, or
+   61.  */
+
+void
+set_min_and_max_values_for_integral_type (tree type,
+                                         int precision,
+                                         bool is_unsigned)
+{
+  tree min_value;
+  tree max_value;
+
+  if (is_unsigned)
+    {
+      min_value = build_int_2 (0, 0);
+      max_value 
+       = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
+                      ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
+                      precision - HOST_BITS_PER_WIDE_INT > 0
+                      ? ((unsigned HOST_WIDE_INT) ~0
+                         >> (HOST_BITS_PER_WIDE_INT
+                             - (precision - HOST_BITS_PER_WIDE_INT)))
+                      : 0);
+    }
+  else
+    {
+      min_value 
+       = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
+                       ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
+                      (((HOST_WIDE_INT) (-1)
+                        << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
+                            ? precision - HOST_BITS_PER_WIDE_INT - 1
+                            : 0))));    
+      max_value
+       = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
+                       ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
+                      (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
+                       ? (((HOST_WIDE_INT) 1
+                           << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
+                       : 0));
+    }
+
+  TREE_TYPE (min_value) = type;
+  TREE_TYPE (max_value) = type;
+  TYPE_MIN_VALUE (type) = min_value;
+  TYPE_MAX_VALUE (type) = max_value;
+}
+
 /* Set the extreme values of TYPE based on its precision in bits,
    then lay it out.  Used when make_signed_type won't do
    because the tree code is not INTEGER_TYPE.
@@ -1969,23 +2023,8 @@ fixup_signed_type (tree type)
   if (precision > HOST_BITS_PER_WIDE_INT * 2)
     precision = HOST_BITS_PER_WIDE_INT * 2;
 
-  TYPE_MIN_VALUE (type)
-    = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
-                   ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
-                  (((HOST_WIDE_INT) (-1)
-                    << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
-                        ? precision - HOST_BITS_PER_WIDE_INT - 1
-                        : 0))));
-  TYPE_MAX_VALUE (type)
-    = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
-                   ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
-                  (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
-                   ? (((HOST_WIDE_INT) 1
-                       << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
-                   : 0));
-
-  TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
-  TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
+  set_min_and_max_values_for_integral_type (type, precision, 
+                                           /*is_unsigned=*/false);
 
   /* Lay out the type: set its alignment, size, etc.  */
   layout_type (type);
@@ -2006,17 +2045,8 @@ fixup_unsigned_type (tree type)
   if (precision > HOST_BITS_PER_WIDE_INT * 2)
     precision = HOST_BITS_PER_WIDE_INT * 2;
 
-  TYPE_MIN_VALUE (type) = build_int_2 (0, 0);
-  TYPE_MAX_VALUE (type)
-    = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
-                  ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
-                  precision - HOST_BITS_PER_WIDE_INT > 0
-                  ? ((unsigned HOST_WIDE_INT) ~0
-                     >> (HOST_BITS_PER_WIDE_INT
-                         - (precision - HOST_BITS_PER_WIDE_INT)))
-                  : 0);
-  TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
-  TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
+  set_min_and_max_values_for_integral_type (type, precision, 
+                                           /*is_unsigned=*/true);
 
   /* Lay out the type: set its alignment, size, etc.  */
   layout_type (type);