/* 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, 2005, 2006
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
/* Similar, except passed a tree node. */
enum machine_mode
-mode_for_size_tree (tree size, enum mode_class class, int limit)
+mode_for_size_tree (const_tree size, enum mode_class class, int limit)
{
unsigned HOST_WIDE_INT uhwi;
unsigned int ui;
case MODE_DECIMAL_FLOAT:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
+ case MODE_FRACT:
+ case MODE_ACCUM:
+ case MODE_UFRACT:
+ case MODE_UACCUM:
+ case MODE_VECTOR_FRACT:
+ case MODE_VECTOR_ACCUM:
+ case MODE_VECTOR_UFRACT:
+ case MODE_VECTOR_UACCUM:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
break;
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.
-
- Note that do_type_align may set DECL_USER_ALIGN, so we need to
- check old_user_align instead. */
+ /* If the field is packed and not explicitly aligned, give it the
+ minimum alignment. Note that do_type_align may set
+ DECL_USER_ALIGN, so we need to check old_user_align instead. */
if (packed_p
- && !old_user_align
- && (DECL_NONADDRESSABLE_P (decl)
- || DECL_SIZE_UNIT (decl) == 0
- || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
+ && !old_user_align)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
if (! packed_p && ! DECL_USER_ALIGN (decl))
{
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);
#ifdef STRUCTURE_SIZE_BOUNDARY
/* Packed structures don't need to have minimum size. */
if (! TYPE_PACKED (t))
- rli->record_align = MAX (rli->record_align, (unsigned) STRUCTURE_SIZE_BOUNDARY);
+ {
+ unsigned tmp;
+
+ /* #pragma pack overrides STRUCTURE_SIZE_BOUNDARY. */
+ tmp = (unsigned) STRUCTURE_SIZE_BOUNDARY;
+ if (maximum_field_alignment != 0)
+ tmp = MIN (tmp, maximum_field_alignment);
+ rli->record_align = MAX (rli->record_align, tmp);
+ }
#endif
rli->offset = size_zero_node;
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 (!is_bitfield
+ if ((!is_bitfield && !DECL_PACKED (field))
|| (!integer_zerop (DECL_SIZE (field))
? !DECL_PACKED (field)
: (rli->prev_field
if (targetm.ms_bitfield_layout_p (rli->t))
{
tree prev_saved = rli->prev_field;
+ tree prev_type = prev_saved ? DECL_BIT_FIELD_TYPE (prev_saved) : NULL;
/* This is a bitfield if it exists. */
if (rli->prev_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))))
+ && 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,
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), 1);
+ 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
{
Note: since the beginning of the field was aligned then
of course the end will be too. No round needed. */
- if (!integer_zerop (DECL_SIZE (rli->prev_field))
- && rli->remaining_in_alignment)
+ if (!integer_zerop (DECL_SIZE (rli->prev_field)))
{
rli->bitpos
= size_binop (PLUS_EXPR, rli->bitpos,
/* 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)), 1)
- - tree_low_cst (DECL_SIZE (field), 1);
+ {
+ 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. */
type_align = TYPE_ALIGN (TREE_TYPE (field));
if (DECL_SIZE (field) == 0)
/* Do nothing. */;
else if (TREE_CODE (DECL_SIZE (field)) != INTEGER_CST
- || TREE_CONSTANT_OVERFLOW (DECL_SIZE (field)))
+ || TREE_OVERFLOW (DECL_SIZE (field)))
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
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)
TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
+ case FIXED_POINT_TYPE:
+ /* TYPE_MODE (type) has been set already. */
+ TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
+ break;
+
case COMPLEX_TYPE:
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
TYPE_MODE (type)
case VECTOR_TYPE:
{
int nunits = TYPE_VECTOR_SUBPARTS (type);
- tree nunits_tree = build_int_cst (NULL_TREE, nunits);
tree innertype = TREE_TYPE (type);
gcc_assert (!(nunits & (nunits - 1)));
/* First, look for a supported vector type. */
if (SCALAR_FLOAT_MODE_P (innermode))
mode = MIN_MODE_VECTOR_FLOAT;
+ else if (SCALAR_FRACT_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_FRACT;
+ else if (SCALAR_UFRACT_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_UFRACT;
+ else if (SCALAR_ACCUM_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_ACCUM;
+ else if (SCALAR_UACCUM_MODE_P (innermode))
+ mode = MIN_MODE_VECTOR_UACCUM;
else
mode = MIN_MODE_VECTOR_INT;
TYPE_MODE (type) = mode;
}
+ TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR,
TYPE_SIZE_UNIT (innertype),
- nunits_tree, 0);
+ size_int (nunits), 0);
TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype),
- nunits_tree, 0);
+ bitsize_int (nunits), 0);
/* Always naturally align vectors. This prevents ABI changes
depending on whether or not native vector modes are supported. */
#else
TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
#endif
+ if (!TYPE_SIZE (element))
+ /* We don't know the size of the underlying element type, so
+ our alignment calculations will be wrong, forcing us to
+ fall back on structural equality. */
+ SET_TYPE_STRUCTURAL_EQUALITY (type);
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
if (TYPE_MODE (type) != BLKmode
&& STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT
- && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type))
- && TYPE_MODE (type) != BLKmode)
+ && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (TYPE_MODE (type)))
{
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
&& 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))
+ && !TREE_OVERFLOW (TYPE_SIZE_UNIT (element))
&& !integer_zerop (TYPE_SIZE_UNIT (element))
&& compare_tree_int (TYPE_SIZE_UNIT (element),
TYPE_ALIGN_UNIT (element)) < 0)
return type;
}
\f
+/* Create and return a type for fract of PRECISION bits, UNSIGNEDP,
+ and SATP. */
+
+tree
+make_fract_type (int precision, int unsignedp, int satp)
+{
+ tree type = make_node (FIXED_POINT_TYPE);
+
+ TYPE_PRECISION (type) = precision;
+
+ if (satp)
+ TYPE_SATURATING (type) = 1;
+
+ /* Lay out the type: set its alignment, size, etc. */
+ if (unsignedp)
+ {
+ TYPE_UNSIGNED (type) = 1;
+ TYPE_MODE (type) = mode_for_size (precision, MODE_UFRACT, 0);
+ }
+ else
+ TYPE_MODE (type) = mode_for_size (precision, MODE_FRACT, 0);
+ layout_type (type);
+
+ return type;
+}
+
+/* Create and return a type for accum of PRECISION bits, UNSIGNEDP,
+ and SATP. */
+
+tree
+make_accum_type (int precision, int unsignedp, int satp)
+{
+ tree type = make_node (FIXED_POINT_TYPE);
+
+ TYPE_PRECISION (type) = precision;
+
+ if (satp)
+ TYPE_SATURATING (type) = 1;
+
+ /* Lay out the type: set its alignment, size, etc. */
+ if (unsignedp)
+ {
+ TYPE_UNSIGNED (type) = 1;
+ TYPE_MODE (type) = mode_for_size (precision, MODE_UACCUM, 0);
+ }
+ else
+ TYPE_MODE (type) = mode_for_size (precision, MODE_ACCUM, 0);
+ layout_type (type);
+
+ return type;
+}
+
/* Initialize sizetype and bitsizetype to a reasonable and temporary
value to enable integer types to be created. */
calculating signed sizes / offsets in bits. However, when
cross-compiling from a 32 bit to a 64 bit host, we are limited to 64 bit
precision. */
- int precision = MIN (oprecision + BITS_PER_UNIT_LOG + 1,
+ int precision = MIN (MIN (oprecision + BITS_PER_UNIT_LOG + 1,
+ MAX_FIXED_MODE_SIZE),
2 * HOST_BITS_PER_WIDE_INT);
tree t;
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);
+ /* Build a new node with the same values, but a different type.
+ Sign extend it to ensure consistency. */
+ new_max = build_int_cst_wide_type (sizetype,
+ TREE_INT_CST_LOW (orig_max),
+ TREE_INT_CST_HIGH (orig_max));
TYPE_MAX_VALUE (sizetype) = new_max;
}
}
return VOIDmode;
if ((SLOW_BYTE_ACCESS && ! volatilep)
- || (volatilep && !targetm.narrow_volatile_bitfield()))
+ || (volatilep && !targetm.narrow_volatile_bitfield ()))
{
enum machine_mode wide_mode = VOIDmode, tmode;