/* C-compiler utilities for types and variables storage layout
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
+#include "output.h"
#include "toplev.h"
#include "ggc.h"
#include "target.h"
/* ... and its original value in bytes, specified via -fpack-struct=<value>. */
unsigned int initial_max_fld_align = TARGET_DEFAULT_PACK_STRUCT;
-/* If nonzero, the alignment of a bitstring or (power-)set value, in bits.
- May be overridden by front-ends. */
-unsigned int set_alignment = 0;
-
/* Nonzero if all REFERENCE_TYPEs are internal and hence should be
allocated in Pmode, not ptr_mode. Set only by internal_reference_types
called only by a front end. */
}
else if (DECL_SIZE_UNIT (decl) == 0)
DECL_SIZE_UNIT (decl)
- = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
- bitsize_unit_node));
+ = fold_convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
+ bitsize_unit_node));
if (code != FIELD_DECL)
/* For non-fields, update the alignment from the type. */
int size_as_int = TREE_INT_CST_LOW (size);
if (compare_tree_int (size, size_as_int) == 0)
- warning ("%Jsize of %qD is %d bytes", decl, decl, size_as_int);
+ warning (0, "size of %q+D is %d bytes", decl, size_as_int);
else
- warning ("%Jsize of %qD is larger than %d bytes",
- decl, decl, larger_than_size);
+ warning (0, "size of %q+D is larger than %wd bytes",
+ decl, larger_than_size);
}
}
/* Hook for a front-end function that can modify the record layout as needed
immediately before it is finalized. */
-void (*lang_adjust_rli) (record_layout_info) = 0;
+static void (*lang_adjust_rli) (record_layout_info) = 0;
void
set_lang_adjust_rli (void (*f) (record_layout_info))
bit_from_pos (tree offset, tree bitpos)
{
return size_binop (PLUS_EXPR, bitpos,
- size_binop (MULT_EXPR, convert (bitsizetype, offset),
+ size_binop (MULT_EXPR,
+ fold_convert (bitsizetype, offset),
bitsize_unit_node));
}
byte_from_pos (tree offset, tree bitpos)
{
return size_binop (PLUS_EXPR, offset,
- convert (sizetype,
- size_binop (TRUNC_DIV_EXPR, bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (TRUNC_DIV_EXPR, bitpos,
+ bitsize_unit_node)));
}
void
tree pos)
{
*poffset = size_binop (MULT_EXPR,
- convert (sizetype,
- size_binop (FLOOR_DIV_EXPR, pos,
- bitsize_int (off_align))),
+ fold_convert (sizetype,
+ size_binop (FLOOR_DIV_EXPR, pos,
+ bitsize_int (off_align))),
size_int (off_align / BITS_PER_UNIT));
*pbitpos = size_binop (FLOOR_MOD_EXPR, pos, bitsize_int (off_align));
}
*poffset
= size_binop (PLUS_EXPR, *poffset,
- size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
+ size_binop (MULT_EXPR,
+ fold_convert (sizetype, extra_aligns),
size_int (off_align / BITS_PER_UNIT)));
*pbitpos
}
/* FIELD is about to be added to RLI->T. The alignment (in bits) of
- the next available location is given by KNOWN_ALIGN. Update the
- variable alignment fields in RLI, and return the alignment to give
- the FIELD. */
+ the next available location within the record is given by KNOWN_ALIGN.
+ Update the variable alignment fields in RLI, and return the alignment
+ to give the FIELD. */
unsigned int
update_alignment_for_field (record_layout_info rli, tree field,
type_align = MIN (type_align, maximum_field_alignment);
rli->record_align = MAX (rli->record_align, type_align);
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ /* If we start a new run, make sure we start it properly aligned. */
+ if ((!rli->prev_field
+ || integer_zerop (DECL_SIZE (field))
+ || integer_zerop (DECL_SIZE (rli->prev_field))
+ || !host_integerp (DECL_SIZE (rli->prev_field), 0)
+ || !host_integerp (TYPE_SIZE (type), 0)
+ || !simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (rli->prev_field)))
+ || (rli->remaining_in_alignment
+ < tree_low_cst (DECL_SIZE (field), 0)))
+ && desired_align < type_align)
+ desired_align = type_align;
}
}
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (TREE_CODE (rli->t) == UNION_TYPE)
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
- rli->offset = fold (build3 (COND_EXPR, sizetype,
- DECL_QUALIFIER (field),
- DECL_SIZE_UNIT (field), rli->offset));
+ rli->offset = fold_build3 (COND_EXPR, sizetype,
+ DECL_QUALIFIER (field),
+ DECL_SIZE_UNIT (field), rli->offset);
}
#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
known_align = (tree_low_cst (rli->bitpos, 1)
& - tree_low_cst (rli->bitpos, 1));
else if (integer_zerop (rli->offset))
- known_align = BIGGEST_ALIGNMENT;
+ known_align = 0;
else if (host_integerp (rli->offset, 1))
known_align = (BITS_PER_UNIT
* (tree_low_cst (rli->offset, 1)
known_align = rli->offset_align;
desired_align = update_alignment_for_field (rli, field, known_align);
+ if (known_align == 0)
+ known_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
if (warn_packed && DECL_PACKED (field))
{
if (TYPE_ALIGN (type) > desired_align)
{
if (STRICT_ALIGNMENT)
- warning ("%Jpacked attribute causes inefficient alignment "
- "for %qD", field, field);
+ warning (OPT_Wattributes, "packed attribute causes "
+ "inefficient alignment for %q+D", field);
else
- warning ("%Jpacked attribute is unnecessary for %qD",
- field, field);
+ warning (OPT_Wattributes, "packed attribute is "
+ "unnecessary for %q+D", field);
}
}
else
/* No, we need to skip space before this field.
Bump the cumulative size to multiple of field alignment. */
- if (warn_padded)
- warning ("%Jpadding struct to align %qD", field, field);
+ warning (OPT_Wpadded, "padding struct to align %q+D", field);
/* If the alignment is still within offset_align, just align
the bit position. */
/* First adjust OFFSET by the partial bits, then align. */
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
- convert (sizetype,
- size_binop (CEIL_DIV_EXPR, rli->bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (CEIL_DIV_EXPR, rli->bitpos,
+ bitsize_unit_node)));
rli->bitpos = bitsize_zero_node;
rli->offset = round_up (rli->offset, desired_align / BITS_PER_UNIT);
if (rli->remaining_in_alignment < bitsize)
{
- /* out of bits; bump up to next 'word'. */
- rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
- rli->bitpos
- = size_binop (PLUS_EXPR, TYPE_SIZE (type),
- DECL_FIELD_BIT_OFFSET (rli->prev_field));
- rli->prev_field = field;
- rli->remaining_in_alignment
- = tree_low_cst (TYPE_SIZE (type), 0);
+ /* If PREV_FIELD is packed, and we haven't lumped
+ non-packed bitfields with it, treat this as if PREV_FIELD
+ was not a bitfield. This avoids anomalies where a packed
+ bitfield with long long base type can take up more
+ space than a same-size bitfield with base type short. */
+ if (rli->prev_packed)
+ rli->prev_field = prev_saved = NULL;
+ else
+ {
+ /* out of bits; bump up to next 'word'. */
+ rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
+ rli->bitpos
+ = size_binop (PLUS_EXPR, TYPE_SIZE (type),
+ DECL_FIELD_BIT_OFFSET (rli->prev_field));
+ rli->prev_field = field;
+ rli->remaining_in_alignment
+ = tree_low_cst (TYPE_SIZE (type), 0) - bitsize;
+ }
}
-
- rli->remaining_in_alignment -= bitsize;
+ else
+ rli->remaining_in_alignment -= bitsize;
}
+ else if (rli->prev_packed)
+ rli->prev_field = prev_saved = NULL;
else
{
/* End of a run: if leaving a run of bitfields of the same type
{
tree type_size = TYPE_SIZE (TREE_TYPE (rli->prev_field));
- rli->bitpos
- = size_binop (PLUS_EXPR, type_size,
- DECL_FIELD_BIT_OFFSET (rli->prev_field));
+ /* If the desired alignment is greater or equal to TYPE_SIZE,
+ we have already adjusted rli->bitpos / rli->offset above.
+ */
+ if ((unsigned HOST_WIDE_INT) tree_low_cst (type_size, 0)
+ > desired_align)
+ rli->bitpos
+ = size_binop (PLUS_EXPR, type_size,
+ DECL_FIELD_BIT_OFFSET (rli->prev_field));
}
else
/* We "use up" size zero fields; the code below should behave
rli->prev_field = NULL;
}
+ rli->prev_packed = 0;
normalize_rli (rli);
}
actual_align = (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1));
else if (integer_zerop (DECL_FIELD_OFFSET (field)))
- actual_align = BIGGEST_ALIGNMENT;
+ actual_align = MAX (BIGGEST_ALIGNMENT, rli->record_align);
else if (host_integerp (DECL_FIELD_OFFSET (field), 1))
actual_align = (BITS_PER_UNIT
* (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_OFFSET (field), 1)));
else
actual_align = DECL_OFFSET_ALIGN (field);
+ /* ACTUAL_ALIGN is still the actual alignment *within the record* .
+ store / extract bit field operations will check the alignment of the
+ record against the mode of bit fields. */
if (known_align != actual_align)
layout_decl (field, actual_align);
- /* Only the MS bitfields use this. */
- if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
- rli->prev_field = field;
+ if (DECL_BIT_FIELD_TYPE (field))
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
+
+ /* Only the MS bitfields use this. We used to also put any kind of
+ packed bit fields into prev_field, but that makes no sense, because
+ an 8 bit packed bit field shouldn't impose more restriction on
+ following fields than a char field, and the alignment requirements
+ are also not fulfilled.
+ There is no sane value to set rli->remaining_in_alignment to when
+ a packed bitfield in prev_field is unaligned. */
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
+ gcc_assert (rli->prev_field
+ || actual_align >= type_align || DECL_PACKED (field)
+ || integer_zerop (DECL_SIZE (field))
+ || !targetm.ms_bitfield_layout_p (rli->t));
+ if (rli->prev_field == NULL && actual_align >= type_align
+ && !integer_zerop (DECL_SIZE (field)))
+ {
+ rli->prev_field = field;
+ /* rli->remaining_in_alignment has not been set if the bitfield
+ has size zero, or if it is a packed bitfield. */
+ rli->remaining_in_alignment
+ = (tree_low_cst (TYPE_SIZE (TREE_TYPE (field)), 0)
+ - tree_low_cst (DECL_SIZE (field), 0));
+ rli->prev_packed = DECL_PACKED (field);
+
+ }
+ else if (rli->prev_field && DECL_PACKED (field))
+ {
+ HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 0);
+
+ if (rli->remaining_in_alignment < bitsize)
+ rli->prev_field = NULL;
+ else
+ rli->remaining_in_alignment -= bitsize;
+ }
+ }
/* Now add size of this field to the size of the record. If the size is
not constant, treat the field as being a multiple of bytes and just
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
- convert (sizetype,
- size_binop (CEIL_DIV_EXPR, rli->bitpos,
- bitsize_unit_node)));
+ fold_convert (sizetype,
+ size_binop (CEIL_DIV_EXPR, rli->bitpos,
+ bitsize_unit_node)));
rli->offset
= size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
rli->bitpos = bitsize_zero_node;
TYPE_SIZE_UNIT (rli->t)
= round_up (unpadded_size_unit, TYPE_ALIGN_UNIT (rli->t));
- if (warn_padded && TREE_CONSTANT (unpadded_size)
+ if (TREE_CONSTANT (unpadded_size)
&& simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
- warning ("padding struct size to alignment boundary");
+ warning (OPT_Wpadded, "padding struct size to alignment boundary");
if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
&& TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary
name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rli->t)));
if (STRICT_ALIGNMENT)
- warning ("packed attribute causes inefficient "
+ warning (OPT_Wpacked, "packed attribute causes inefficient "
"alignment for %qs", name);
else
- warning ("packed attribute is unnecessary for %qs", name);
+ warning (OPT_Wpacked,
+ "packed attribute is unnecessary for %qs", name);
}
else
{
if (STRICT_ALIGNMENT)
- warning ("packed attribute causes inefficient alignment");
+ warning (OPT_Wpacked,
+ "packed attribute causes inefficient alignment");
else
- warning ("packed attribute is unnecessary");
+ warning (OPT_Wpacked, "packed attribute is unnecessary");
}
}
}
&& TREE_CODE (type) != QUAL_UNION_TYPE
&& TREE_CODE (type) != ARRAY_TYPE)))
{
- TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
- TYPE_USER_ALIGN (type) = 0;
+ unsigned mode_align = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+
+ /* Don't override a larger alignment requirement coming from a user
+ alignment of one of the fields. */
+ if (mode_align >= TYPE_ALIGN (type))
+ {
+ TYPE_ALIGN (type) = mode_align;
+ TYPE_USER_ALIGN (type) = 0;
+ }
}
/* Do machine-dependent extra alignment. */
result will fit in sizetype. We will get more efficient code using
sizetype, so we force a conversion. */
TYPE_SIZE_UNIT (type)
- = convert (sizetype,
- size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
- bitsize_unit_node));
+ = fold_convert (sizetype,
+ size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+ bitsize_unit_node));
if (TYPE_SIZE (type) != 0)
{
void
finish_record_layout (record_layout_info rli, int free_p)
{
+ tree field;
+
/* Compute the final size. */
finalize_record_size (rli);
/* Perform any last tweaks to the TYPE_SIZE, etc. */
finalize_type_size (rli->t);
+ /* We might be able to clear DECL_PACKED on any members that happen
+ to be suitably aligned (not forgetting the alignment of the type
+ itself). */
+ for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL && DECL_PACKED (field)
+ && DECL_OFFSET_ALIGN (field) >= TYPE_ALIGN (TREE_TYPE (field))
+ && TYPE_ALIGN (rli->t) >= TYPE_ALIGN (TREE_TYPE (field)))
+ DECL_PACKED (field) = 0;
+
/* Lay out any static members. This is done now because their type
may use the record's type. */
while (rli->pending_statics)
nunits_tree, 0);
TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype),
nunits_tree, 0);
+
+ /* Always naturally align vectors. This prevents ABI changes
+ depending on whether or not native vector modes are supported. */
+ TYPE_ALIGN (type) = tree_low_cst (TYPE_SIZE (type), 0);
break;
}
/* The initial subtraction should happen in the original type so
that (possible) negative values are handled appropriately. */
length = size_binop (PLUS_EXPR, size_one_node,
- convert (sizetype,
- fold (build2 (MINUS_EXPR,
- TREE_TYPE (lb),
- ub, lb))));
+ fold_convert (sizetype,
+ fold_build2 (MINUS_EXPR,
+ TREE_TYPE (lb),
+ ub, lb)));
/* Special handling for arrays of bits (for Chill). */
element_size = TYPE_SIZE (element);
length = size_binop (MAX_EXPR, length, size_zero_node);
TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
- convert (bitsizetype, length));
+ fold_convert (bitsizetype,
+ length));
/* If we know the size of the element, calculate the total
size directly, rather than do some division thing below.
}
break;
- case SET_TYPE: /* Used by Chill and Pascal. */
- {
- unsigned int alignment;
- HOST_WIDE_INT size_in_bits;
- HOST_WIDE_INT rounded_size;
-
- gcc_assert (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
- == INTEGER_CST);
- gcc_assert (TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type)))
- == INTEGER_CST);
-
-#ifndef SET_WORD_SIZE
-#define SET_WORD_SIZE BITS_PER_WORD
-#endif
- alignment = set_alignment ? set_alignment : SET_WORD_SIZE;
- size_in_bits
- = (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
- - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1);
- rounded_size
- = ((size_in_bits + alignment - 1) / alignment) * alignment;
-
- if (rounded_size > (int) alignment)
- TYPE_MODE (type) = BLKmode;
- else
- TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
-
- TYPE_SIZE (type) = bitsize_int (rounded_size);
- TYPE_SIZE_UNIT (type) = size_int (rounded_size / BITS_PER_UNIT);
- TYPE_ALIGN (type) = alignment;
- TYPE_USER_ALIGN (type) = 0;
- TYPE_PRECISION (type) = size_in_bits;
- }
- break;
-
- case FILE_TYPE:
- /* The size may vary in different languages, so the language front end
- should fill in the size. */
- TYPE_ALIGN (type) = BIGGEST_ALIGNMENT;
- TYPE_USER_ALIGN (type) = 0;
- TYPE_MODE (type) = BLKmode;
- break;
-
default:
gcc_unreachable ();
}
max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1) << 1) - 1;
}
- *mmin = GEN_INT (trunc_int_for_mode (min_val, target_mode));
- *mmax = GEN_INT (trunc_int_for_mode (max_val, target_mode));
+ *mmin = gen_int_mode (min_val, target_mode);
+ *mmax = gen_int_mode (max_val, target_mode);
}
#include "gt-stor-layout.h"