#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)
/* 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;
}
/* 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)
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 ();
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.
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;
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));
}
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))
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"