/* 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, 2006
+ 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. */
enum machine_mode
mode_for_size_tree (tree size, enum mode_class class, int limit)
{
- if (TREE_CODE (size) != INTEGER_CST
- || TREE_OVERFLOW (size)
- /* What we really want to say here is that the size can fit in a
- host integer, but we know there's no way we'd find a mode for
- this many bits, so there's no point in doing the precise test. */
- || compare_tree_int (size, 1000) > 0)
+ unsigned HOST_WIDE_INT uhwi;
+ unsigned int ui;
+
+ if (!host_integerp (size, 1))
return BLKmode;
- else
- return mode_for_size (tree_low_cst (size, 1), class, limit);
+ uhwi = tree_low_cst (size, 1);
+ ui = uhwi;
+ if (uhwi != ui)
+ return BLKmode;
+ return mode_for_size (ui, class, limit);
}
/* Similar, but never return BLKmode; return the narrowest mode that
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
if (code == CONST_DECL)
return;
-
+
gcc_assert (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL
|| code == TYPE_DECL ||code == FIELD_DECL);
-
+
rtl = DECL_RTL_IF_SET (decl);
if (type == error_mark_node)
if (DECL_SIZE (decl) == 0)
{
- DECL_SIZE (decl) = unsave_expr (TYPE_SIZE (type));
- DECL_SIZE_UNIT (decl) = unsave_expr (TYPE_SIZE_UNIT (type));
+ DECL_SIZE (decl) = TYPE_SIZE (type);
+ DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
}
else if (DECL_SIZE_UNIT (decl) == 0)
DECL_SIZE_UNIT (decl)
/* For fields, it's a bit more complicated... */
{
bool old_user_align = DECL_USER_ALIGN (decl);
+ bool zero_bitfield = false;
+ bool packed_p = DECL_PACKED (decl);
+ unsigned int mfa;
if (DECL_BIT_FIELD (decl))
{
DECL_BIT_FIELD_TYPE (decl) = type;
/* A zero-length bit-field affects the alignment of the next
- field. */
+ field. In essence such bit-fields are not influenced by
+ any packing due to #pragma pack or attribute packed. */
if (integer_zerop (DECL_SIZE (decl))
- && ! DECL_PACKED (decl)
&& ! targetm.ms_bitfield_layout_p (DECL_FIELD_CONTEXT (decl)))
{
+ zero_bitfield = true;
+ packed_p = false;
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS)
do_type_align (type, decl);
&& DECL_ALIGN (decl) >= TYPE_ALIGN (type))
DECL_BIT_FIELD (decl) = 0;
}
- else if (DECL_PACKED (decl) && DECL_USER_ALIGN (decl))
+ else if (packed_p && DECL_USER_ALIGN (decl))
/* Don't touch DECL_ALIGN. For other packed fields, go ahead and
round up; we'll reduce it again below. We want packing to
supersede USER_ALIGN inherited from the type, but defer to
Note that do_type_align may set DECL_USER_ALIGN, so we need to
check old_user_align instead. */
- if (DECL_PACKED (decl)
+ if (packed_p
&& !old_user_align
&& (DECL_NONADDRESSABLE_P (decl)
|| DECL_SIZE_UNIT (decl) == 0
|| TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
- if (! DECL_USER_ALIGN (decl) && ! DECL_PACKED (decl))
+ if (! packed_p && ! DECL_USER_ALIGN (decl))
{
/* Some targets (i.e. i386, VMS) limit struct field alignment
to a lower boundary than alignment of variables unless
#endif
}
+ if (zero_bitfield)
+ mfa = initial_max_fld_align * BITS_PER_UNIT;
+ else
+ mfa = maximum_field_alignment;
/* Should this be controlled by DECL_USER_ALIGN, too? */
- if (maximum_field_alignment != 0)
- DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
+ if (mfa != 0)
+ DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), mfa);
}
/* Evaluate nonconstant size only once, either now or as soon as safe. */
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);
}
}
{
DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
DECL_MODE (decl) = VOIDmode;
- DECL_ALIGN (decl) = 0;
+ if (!DECL_USER_ALIGN (decl))
+ DECL_ALIGN (decl) = 0;
SET_DECL_RTL (decl, 0);
layout_decl (decl, 0);
/* 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))
rli->prev_field = 0;
rli->pending_statics = 0;
rli->packed_maybe_necessary = 0;
+ rli->remaining_in_alignment = 0;
return rli;
}
bit_from_pos (tree offset, tree bitpos)
{
return size_binop (PLUS_EXPR, bitpos,
- size_binop (MULT_EXPR,
+ size_binop (MULT_EXPR,
fold_convert (bitsizetype, offset),
bitsize_unit_node));
}
*poffset
= size_binop (PLUS_EXPR, *poffset,
- size_binop (MULT_EXPR,
+ size_binop (MULT_EXPR,
fold_convert (sizetype, extra_aligns),
size_int (off_align / BITS_PER_UNIT)));
fprintf (stderr, "\naligns: rec = %u, unpack = %u, off = %u\n",
rli->record_align, rli->unpacked_align,
rli->offset_align);
+
+ /* The ms_struct code is the only that uses this. */
+ if (targetm.ms_bitfield_layout_p (rli->t))
+ fprintf (stderr, "remaining in alignment = %u\n", rli->remaining_in_alignment);
+
if (rli->packed_maybe_necessary)
fprintf (stderr, "packed may be necessary\n");
}
/* 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,
bool user_align;
bool is_bitfield;
+ /* Do not attempt to align an ERROR_MARK node */
+ if (TREE_CODE (type) == ERROR_MARK)
+ return 0;
+
/* Lay out the field so we know what alignment it needs. */
layout_decl (field, known_align);
desired_align = DECL_ALIGN (field);
/* Record must have at least as much alignment as any field.
Otherwise, the alignment of the field within the record is
meaningless. */
- if (is_bitfield && targetm.ms_bitfield_layout_p (rli->t))
+ if (targetm.ms_bitfield_layout_p (rli->t))
{
/* Here, the alignment of the underlying type of a bitfield can
affect the alignment of a record; even a zero-sized field
the type, except that for zero-size bitfields this only
applies if there was an immediately prior, nonzero-size
bitfield. (That's the way it is, experimentally.) */
- if (! integer_zerop (DECL_SIZE (field))
- ? ! DECL_PACKED (field)
- : (rli->prev_field
- && DECL_BIT_FIELD_TYPE (rli->prev_field)
- && ! integer_zerop (DECL_SIZE (rli->prev_field))))
+ if ((!is_bitfield && !DECL_PACKED (field))
+ || (!integer_zerop (DECL_SIZE (field))
+ ? !DECL_PACKED (field)
+ : (rli->prev_field
+ && DECL_BIT_FIELD_TYPE (rli->prev_field)
+ && ! integer_zerop (DECL_SIZE (rli->prev_field)))))
{
unsigned int type_align = TYPE_ALIGN (type);
type_align = MAX (type_align, desired_align);
type_align = ADJUST_FIELD_ALIGN (field, type_align);
#endif
- if (maximum_field_alignment != 0)
+ /* Targets might chose to handle unnamed and hence possibly
+ zero-width bitfield. Those are not influenced by #pragmas
+ or packed attributes. */
+ if (integer_zerop (DECL_SIZE (field)))
+ {
+ if (initial_max_fld_align)
+ type_align = MIN (type_align,
+ initial_max_fld_align * BITS_PER_UNIT);
+ }
+ else if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
+ /* If this is an ERROR_MARK return *after* having set the
+ field at the start of the union. This helps when parsing
+ invalid fields. */
+ if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK)
+ return;
+
/* We assume the union's size will be a multiple of a byte so we don't
bother with BITPOS. */
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)
/* The type of this field. */
tree type = TREE_TYPE (field);
- if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
- return;
+ gcc_assert (TREE_CODE (field) != ERROR_MARK);
/* If FIELD is static, then treat it like a separate variable, not
really like a structure field. If it is a FUNCTION_DECL, it's a
return;
}
+ else if (TREE_CODE (type) == ERROR_MARK)
+ {
+ /* Place this field at the current allocation position, so we
+ maintain monotonicity. */
+ DECL_FIELD_OFFSET (field) = rli->offset;
+ DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
+ SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
+ return;
+ }
+
/* Work out the known alignment so far. Note that A & (-A) is the
value of the least-significant bit in A that is one. */
if (! integer_zerop (rli->bitpos))
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
}
/* Does this field automatically have alignment it needs by virtue
- of the fields that precede it and the record's own alignment? */
- if (known_align < desired_align)
+ of the fields that precede it and the record's own alignment?
+ We already align ms_struct fields, so don't re-align them. */
+ if (known_align < desired_align
+ && !targetm.ms_bitfield_layout_p (rli->t))
{
/* 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. */
Note: for compatibility, we use the type size, not the type alignment
to determine alignment, since that matches the documentation */
- if (targetm.ms_bitfield_layout_p (rli->t)
- && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field))
- || (rli->prev_field && ! DECL_PACKED (rli->prev_field))))
+ if (targetm.ms_bitfield_layout_p (rli->t))
{
- /* At this point, either the prior or current are bitfields,
- (possibly both), and we're dealing with MS packing. */
tree prev_saved = rli->prev_field;
+ tree prev_type = prev_saved ? DECL_BIT_FIELD_TYPE (prev_saved) : NULL;
- /* Is the prior field a bitfield? If so, handle "runs" of same
- type size fields. */
- if (rli->prev_field /* necessarily a bitfield if it exists. */)
+ /* This is a bitfield if it exists. */
+ if (rli->prev_field)
{
/* If both are bitfields, nonzero, and the same size, this is
the middle of a run. Zero declared size fields are special
&& !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))))
+ && simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type)))
{
/* We're in the middle of a run of equal type size fields; make
sure we realign if we run out of bits. (Not decl size,
type size!) */
- HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 0);
+ HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 1);
if (rli->remaining_in_alignment < bitsize)
{
+ HOST_WIDE_INT typesize = tree_low_cst (TYPE_SIZE (type), 1);
+
/* 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));
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (rli->remaining_in_alignment));
rli->prev_field = field;
- rli->remaining_in_alignment
- = tree_low_cst (TYPE_SIZE (type), 0);
+ if (typesize < bitsize)
+ rli->remaining_in_alignment = 0;
+ else
+ rli->remaining_in_alignment = typesize - bitsize;
}
-
- rli->remaining_in_alignment -= bitsize;
+ else
+ rli->remaining_in_alignment -= bitsize;
}
else
{
if (!integer_zerop (DECL_SIZE (rli->prev_field)))
{
- 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));
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (rli->remaining_in_alignment));
}
else
/* We "use up" size zero fields; the code below should behave
/* Cause a new bitfield to be captured, either this time (if
currently a bitfield) or next time we see one. */
if (!DECL_BIT_FIELD_TYPE(field)
- || integer_zerop (DECL_SIZE (field)))
+ || integer_zerop (DECL_SIZE (field)))
rli->prev_field = NULL;
}
there wasn't. */
if (!DECL_BIT_FIELD_TYPE (field)
- || ( prev_saved != NULL
- ? !simple_cst_equal (TYPE_SIZE (type),
- TYPE_SIZE (TREE_TYPE (prev_saved)))
+ || (prev_saved != NULL
+ ? !simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type))
: !integer_zerop (DECL_SIZE (field)) ))
{
/* Never smaller than a byte for compatibility. */
if (DECL_SIZE (field) != NULL
&& host_integerp (TYPE_SIZE (TREE_TYPE (field)), 0)
&& host_integerp (DECL_SIZE (field), 0))
- rli->remaining_in_alignment
- = tree_low_cst (TYPE_SIZE (TREE_TYPE(field)), 0)
- - tree_low_cst (DECL_SIZE (field), 0);
+ {
+ HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 1);
+ HOST_WIDE_INT typesize
+ = tree_low_cst (TYPE_SIZE (TREE_TYPE (field)), 1);
+
+ if (typesize < bitsize)
+ rli->remaining_in_alignment = 0;
+ else
+ rli->remaining_in_alignment = typesize - bitsize;
+ }
/* Now align (conventionally) for the new type. */
- if (!DECL_PACKED(field))
- type_align = MAX(TYPE_ALIGN (type), type_align);
-
- if (prev_saved
- && DECL_BIT_FIELD_TYPE (prev_saved)
- /* If the previous bit-field is zero-sized, we've already
- accounted for its alignment needs (or ignored it, if
- appropriate) while placing it. */
- && ! integer_zerop (DECL_SIZE (prev_saved)))
- type_align = MAX (type_align,
- TYPE_ALIGN (TREE_TYPE (prev_saved)));
+ type_align = TYPE_ALIGN (TREE_TYPE (field));
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
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 (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE (field))
+ rli->prev_field = field;
/* 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
is printed in finish_struct. */
if (DECL_SIZE (field) == 0)
/* Do nothing. */;
- else if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST
- || TREE_CONSTANT_OVERFLOW (DECL_SIZE_UNIT (field)))
+ else if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST
+ || TREE_CONSTANT_OVERFLOW (DECL_SIZE (field)))
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
rli->bitpos = bitsize_zero_node;
rli->offset_align = MIN (rli->offset_align, desired_align);
}
+ else if (targetm.ms_bitfield_layout_p (rli->t))
+ {
+ 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 ((TREE_CHAIN (field) == NULL
+ || TREE_CODE (TREE_CHAIN (field)) != FIELD_DECL)
+ && DECL_BIT_FIELD_TYPE (field)
+ && !integer_zerop (DECL_SIZE (field)))
+ rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (rli->remaining_in_alignment));
+
+ normalize_rli (rli);
+ }
else
{
rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
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");
}
}
}
#endif /* MEMBER_TYPE_FORCES_BLK */
}
- TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
-
/* 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. */
if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode
- && GET_MODE_SIZE (mode) == GET_MODE_SIZE (TYPE_MODE (type)))
+ && host_integerp (TYPE_SIZE (type), 1)
+ && GET_MODE_BITSIZE (mode) == TREE_INT_CST_LOW (TYPE_SIZE (type)))
TYPE_MODE (type) = mode;
+ else
+ TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
/* If structure's known alignment is less than what the scalar
mode would need, and it matters, then stick with BLKmode. */
&& 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. */
void
finish_record_layout (record_layout_info rli, int free_p)
{
+ tree variant;
+
/* Compute the final size. */
finalize_record_size (rli);
/* Perform any last tweaks to the TYPE_SIZE, etc. */
finalize_type_size (rli->t);
+ /* Propagate TYPE_PACKED to variants. With C++ templates,
+ handle_packed_attribute is too early to do this. */
+ for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
+ variant = TYPE_NEXT_VARIANT (variant))
+ TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
+
/* Lay out any static members. This is done now because their type
may use the record's type. */
while (rli->pending_statics)
case INTEGER_TYPE:
case ENUMERAL_TYPE:
- case CHAR_TYPE:
if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
TYPE_UNSIGNED (type) = 1;
enum machine_mode mode;
/* First, look for a supported vector type. */
- if (GET_MODE_CLASS (innermode) == MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (innermode))
mode = MIN_MODE_VECTOR_FLOAT;
else
mode = MIN_MODE_VECTOR_INT;
that (possible) negative values are handled appropriately. */
length = size_binop (PLUS_EXPR, size_one_node,
fold_convert (sizetype,
- fold (build2 (MINUS_EXPR,
- TREE_TYPE (lb),
- ub, lb))));
+ 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,
- fold_convert (bitsizetype,
+ fold_convert (bitsizetype,
length));
/* If we know the size of the element, calculate the total
TYPE_MODE (type) = BLKmode;
}
}
+ /* When the element size is constant, check that it is at least as
+ large as the element alignment. */
+ if (TYPE_SIZE_UNIT (element)
+ && TREE_CODE (TYPE_SIZE_UNIT (element)) == INTEGER_CST
+ /* If TYPE_SIZE_UNIT overflowed, then it is certainly larger than
+ TYPE_ALIGN_UNIT. */
+ && !TREE_CONSTANT_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");
break;
}
}
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 ();
}
initialize_sizetypes (bool signed_p)
{
tree t = make_node (INTEGER_TYPE);
+ int precision = GET_MODE_BITSIZE (SImode);
TYPE_MODE (t) = SImode;
TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode);
TYPE_USER_ALIGN (t) = 0;
TYPE_IS_SIZETYPE (t) = 1;
TYPE_UNSIGNED (t) = !signed_p;
- TYPE_SIZE (t) = build_int_cst (t, GET_MODE_BITSIZE (SImode));
+ TYPE_SIZE (t) = build_int_cst (t, precision);
TYPE_SIZE_UNIT (t) = build_int_cst (t, GET_MODE_SIZE (SImode));
- TYPE_PRECISION (t) = GET_MODE_BITSIZE (SImode);
- TYPE_MIN_VALUE (t) = build_int_cst (t, 0);
+ TYPE_PRECISION (t) = precision;
- /* 1000 avoids problems with possible overflow and is certainly
- larger than any size value we'd want to be storing. */
- TYPE_MAX_VALUE (t) = build_int_cst (t, 1000);
+ /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE. */
+ set_min_and_max_values_for_integral_type (t, precision, !signed_p);
sizetype = t;
bitsizetype = build_distinct_type_copy (t);
TREE_TYPE (TYPE_CACHED_VALUES (t)) = type;
TYPE_UID (t) = TYPE_UID (sizetype);
TYPE_IS_SIZETYPE (t) = 1;
-
+
/* Replace our original stub sizetype. */
memcpy (sizetype, t, tree_size (sizetype));
TYPE_MAIN_VARIANT (sizetype) = sizetype;
-
+
t = make_node (INTEGER_TYPE);
TYPE_NAME (t) = get_identifier ("bit_size_type");
/* We do want to use bitsizetype's cache, as we will be replacing that
TYPE_PRECISION (t) = precision;
TYPE_UID (t) = TYPE_UID (bitsizetype);
TYPE_IS_SIZETYPE (t) = 1;
+
/* Replace our original stub bitsizetype. */
memcpy (bitsizetype, t, tree_size (bitsizetype));
-
+ TYPE_MAIN_VARIANT (bitsizetype) = bitsizetype;
+
if (TYPE_UNSIGNED (type))
{
fixup_unsigned_type (bitsizetype);
ssizetype = sizetype;
sbitsizetype = bitsizetype;
}
+
+ /* If SIZETYPE is unsigned, we need to fix TYPE_MAX_VALUE so that
+ it is sign extended in a way consistent with force_fit_type. */
+ if (TYPE_UNSIGNED (type))
+ {
+ tree orig_max, new_max;
+
+ orig_max = TYPE_MAX_VALUE (sizetype);
+
+ /* Build a new node with the same values, but a different type. */
+ new_max = build_int_cst_wide (sizetype,
+ TREE_INT_CST_LOW (orig_max),
+ TREE_INT_CST_HIGH (orig_max));
+
+ /* Now sign extend it using force_fit_type to ensure
+ consistency. */
+ new_max = force_fit_type (new_max, 0, 0, 0);
+ TYPE_MAX_VALUE (sizetype) = new_max;
+ }
}
\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
+/* TYPE is an integral type, i.e., an INTEGRAL_TYPE, ENUMERAL_TYPE
+ or BOOLEAN_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,
If LARGEST_MODE is not VOIDmode, it means that we should not use a mode
larger than LARGEST_MODE (usually SImode).
- If no mode meets all these conditions, we return VOIDmode. Otherwise, if
- VOLATILEP is true or SLOW_BYTE_ACCESS is false, we return the smallest
- mode meeting these conditions.
+ If no mode meets all these conditions, we return VOIDmode.
+
+ If VOLATILEP is false and SLOW_BYTE_ACCESS is false, we return the
+ smallest mode meeting these conditions.
+
+ If VOLATILEP is false and SLOW_BYTE_ACCESS is true, we return the
+ largest mode (but a mode no wider than UNITS_PER_WORD) that meets
+ all the conditions.
- Otherwise (VOLATILEP is false and SLOW_BYTE_ACCESS is true), we return
- the largest mode (but a mode no wider than UNITS_PER_WORD) that meets
- all the conditions. */
+ If VOLATILEP is true the narrow_volatile_bitfields target hook is used to
+ decide which of the above modes should be used. */
enum machine_mode
get_best_mode (int bitsize, int bitpos, unsigned int align,
|| (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode)))
return VOIDmode;
- if (SLOW_BYTE_ACCESS && ! volatilep)
+ if ((SLOW_BYTE_ACCESS && ! volatilep)
+ || (volatilep && !targetm.narrow_volatile_bitfield()))
{
enum machine_mode wide_mode = VOIDmode, tmode;
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"