OSDN Git Service

* config/h8300/h8300.md (*one_complsi2_h8300): Change to
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index a7ffd4c..98420fb 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.
@@ -410,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;
@@ -446,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));
@@ -463,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))
@@ -2122,4 +2118,27 @@ get_best_mode (int bitsize, int bitpos, unsigned int align,
   return mode;
 }
 
+/* Gets minimal and maximal values for MODE (signed or unsigned depending on
+   SIGN).  */
+
+void
+get_mode_bounds (enum machine_mode mode, int sign, rtx *mmin, rtx *mmax)
+{
+  int size = GET_MODE_BITSIZE (mode);
+
+  if (size > HOST_BITS_PER_WIDE_INT)
+    abort ();
+
+  if (sign)
+    {
+      *mmin = GEN_INT (-((unsigned HOST_WIDE_INT) 1 << (size - 1)));
+      *mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1);
+    }
+  else
+    {
+      *mmin = const0_rtx;
+      *mmax = GEN_INT (((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1);
+    }
+}
+
 #include "gt-stor-layout.h"