/* C-compiler utilities for types and variables storage layout
- Copyright (C) 1987, 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
#include "config.h"
#include <stdio.h>
#include "tree.h"
+#include "flags.h"
+#include "except.h"
#include "function.h"
#define CEIL(x,y) (((x) + (y) - 1) / (y))
The value is measured in bits. */
int maximum_field_alignment;
-#define GET_MODE_ALIGNMENT(MODE) \
- MIN (BIGGEST_ALIGNMENT, \
- MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)))
+/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.
+ May be overridden by front-ends. */
+int set_alignment = 0;
static enum machine_mode smallest_mode_for_size PROTO((unsigned int,
enum mode_class));
return chain;
}
-/* Given a size SIZE that isn't constant, return a SAVE_EXPR
+void
+put_pending_sizes (chain)
+ tree chain;
+{
+ if (pending_sizes)
+ abort ();
+
+ pending_sizes = chain;
+}
+
+/* Given a size SIZE that may not be a constant, return a SAVE_EXPR
to serve as the actual size-expression for a type or decl. */
tree
{
/* If the language-processor is to take responsibility for variable-sized
items (e.g., languages which have elaboration procedures like Ada),
- just return SIZE unchanged. */
- if (global_bindings_p () < 0)
+ just return SIZE unchanged. Likewise for self-referential sizes. */
+ if (TREE_CONSTANT (size)
+ || global_bindings_p () < 0 || contains_placeholder_p (size))
return size;
size = save_expr (size);
if (code == FIELD_DECL && DECL_BIT_FIELD (decl))
{
- /* This is a bit-field. We don't know how to handle
- them except for integers and enums, and front end should
- never generate them otherwise. */
-
- if (! (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE))
- abort ();
-
if (spec_size == 0 && DECL_NAME (decl) != 0)
abort ();
DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;
if (maximum_field_alignment != 0)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
+ else if (DECL_PACKED (decl))
+ DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
}
if (DECL_BIT_FIELD (decl)
&& TYPE_SIZE (type) != 0
- && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
{
register enum machine_mode xmode
= mode_for_size (TREE_INT_CST_LOW (DECL_SIZE (decl)), MODE_INT, 1);
}
}
+ /* Turn off DECL_BIT_FIELD if we won't need it set. */
+ if (DECL_BIT_FIELD (decl) && TYPE_MODE (type) == BLKmode
+ && known_align % TYPE_ALIGN (type) == 0
+ && DECL_SIZE (decl) != 0
+ && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
+ || (TREE_INT_CST_LOW (DECL_SIZE (decl)) % BITS_PER_UNIT) == 0)
+ && DECL_ALIGN (decl) >= TYPE_ALIGN (type))
+ DECL_BIT_FIELD (decl) = 0;
+
/* Evaluate nonconstant size only once, either now or as soon as safe. */
if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
DECL_SIZE (decl) = variable_size (DECL_SIZE (decl));
and VAR_SIZE is a tree expression.
If VAR_SIZE is null, the size is just CONST_SIZE.
Naturally we try to avoid using VAR_SIZE. */
- register int const_size = 0;
+ register HOST_WIDE_INT const_size = 0;
register tree var_size = 0;
/* Once we start using VAR_SIZE, this is the maximum alignment
that we know VAR_SIZE has. */
for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
{
+ register int known_align = var_size ? var_align : const_size;
register int desired_align;
/* If FIELD is static, then treat it like a separate variable,
In both cases, all we do is lay out the decl,
and we do it *after* the record is laid out. */
- if (TREE_STATIC (field))
+ if (TREE_CODE (field) == VAR_DECL)
{
pending_statics = tree_cons (NULL_TREE, field, pending_statics);
continue;
continue;
/* Lay out the field so we know what alignment it needs.
- For KNOWN_ALIGN, pass the number of bits from start of record
- or some divisor of it. */
-
- /* For a packed field, use the alignment as specified,
+ For a packed field, use the alignment as specified,
disregarding what the type would want. */
if (DECL_PACKED (field))
desired_align = DECL_ALIGN (field);
- layout_decl (field, var_size ? var_align : const_size);
+ layout_decl (field, known_align);
if (! DECL_PACKED (field))
desired_align = DECL_ALIGN (field);
/* Some targets (i.e. VMS) limit struct field alignment
#ifdef BIGGEST_FIELD_ALIGNMENT
desired_align = MIN (desired_align, BIGGEST_FIELD_ALIGNMENT);
#endif
+#ifdef ADJUST_FIELD_ALIGN
+ desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+#endif
/* Record must have at least as much alignment as any field.
Otherwise, the alignment of the field within the record
int type_align = TYPE_ALIGN (TREE_TYPE (field));
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
+ else if (TYPE_PACKED (rec))
+ type_align = MIN (type_align, BITS_PER_UNIT);
record_align = MAX (record_align, type_align);
}
&& TREE_TYPE (field) != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& !DECL_PACKED (field)
- /* If #pragma pack is in effect, turn off this feature. */
&& maximum_field_alignment == 0
&& !integer_zerop (DECL_SIZE (field)))
{
register tree dsize = DECL_SIZE (field);
int field_size = TREE_INT_CST_LOW (dsize);
- /* A bit field may not span the unit of alignment of its type.
- Advance to next boundary if necessary. */
- /* ??? There is some uncertainty here as to what
- should be done if type_align is less than the width of the type.
- That can happen because the width exceeds BIGGEST_ALIGNMENT
- or because it exceeds maximum_field_alignment. */
- if (const_size / type_align
- != (const_size + field_size - 1) / type_align)
+ /* A bit field may not span more units of alignment of its type
+ than its type itself. Advance to next boundary if necessary. */
+ if (((const_size + field_size) / type_align - const_size / type_align)
+ > TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (field))) / type_align)
const_size = CEIL (const_size, type_align) * type_align;
}
#endif
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
+ else if (TYPE_PACKED (rec))
+ type_align = MIN (type_align, BITS_PER_UNIT);
/* A bit field may not span the unit of alignment of its type.
Advance to next boundary if necessary. */
else if (var_size)
DECL_FIELD_BITPOS (field) = var_size;
else
- DECL_FIELD_BITPOS (field) = size_int (const_size);
+ {
+ DECL_FIELD_BITPOS (field) = size_int (const_size);
+
+ /* If this field ended up more aligned than we thought it
+ would be (we approximate this by seeing if its position
+ changed), lay out the field again; perhaps we can use an
+ integral mode for it now. */
+ if (known_align != const_size)
+ layout_decl (field, const_size);
+ }
/* Now add size of this field to the size of the record. */
if (dsize == 0)
/* Do nothing. */;
else if (TREE_CODE (dsize) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (dsize)
&& TREE_INT_CST_HIGH (dsize) == 0
- && TREE_INT_CST_LOW (dsize) + const_size > const_size)
+ && TREE_INT_CST_LOW (dsize) + const_size >= const_size)
/* Use const_size if there's no overflow. */
const_size += TREE_INT_CST_LOW (dsize);
else
{
case LANG_TYPE:
/* This kind of type is the responsibility
- of the languge-specific code. */
+ of the language-specific code. */
abort ();
case INTEGER_TYPE:
case ENUMERAL_TYPE:
- if (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type)) >= 0)
+ case CHAR_TYPE:
+ if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
+ && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
TREE_UNSIGNED (type) = 1;
TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type),
break;
case OFFSET_TYPE:
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (Pmode));
- TYPE_MODE (type) = Pmode;
+ TYPE_SIZE (type) = size_int (POINTER_SIZE);
+ TYPE_MODE (type) = ptr_mode;
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
- TYPE_MODE (type) = mode_for_size (2 * GET_MODE_BITSIZE (Pmode),
- MODE_INT, 0);
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
+ TYPE_SIZE (type) = size_int (2 * POINTER_SIZE);
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
- TYPE_MODE (type) = Pmode;
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_MODE (type) = ptr_mode;
+ TYPE_SIZE (type) = size_int (POINTER_SIZE);
TREE_UNSIGNED (type) = 1;
- TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type));
+ TYPE_PRECISION (type) = POINTER_SIZE;
break;
case ARRAY_TYPE:
if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
&& TYPE_SIZE (element))
{
- tree length
- = size_binop (PLUS_EXPR, size_one_node,
- size_binop (MINUS_EXPR, TYPE_MAX_VALUE (index),
- TYPE_MIN_VALUE (index)));
+ tree ub = TYPE_MAX_VALUE (index);
+ tree lb = TYPE_MIN_VALUE (index);
+ tree length;
+
+ /* If UB is max (lb - 1, x), remove the MAX_EXPR since the
+ test for negative below covers it. */
+ if (TREE_CODE (ub) == MAX_EXPR
+ && TREE_CODE (TREE_OPERAND (ub, 0)) == MINUS_EXPR
+ && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 0), 1))
+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 0), 0),
+ lb, 0))
+ ub = TREE_OPERAND (ub, 1);
+ else if (TREE_CODE (ub) == MAX_EXPR
+ && TREE_CODE (TREE_OPERAND (ub, 1)) == MINUS_EXPR
+ && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 1), 1))
+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 1),
+ 0),
+ lb, 0))
+ ub = TREE_OPERAND (ub, 0);
+
+ length = size_binop (PLUS_EXPR, size_one_node,
+ size_binop (MINUS_EXPR, ub, lb));
+
+ /* If neither bound is a constant and sizetype is signed, make
+ sure the size is never negative. We should really do this
+ if *either* bound is non-constant, but this is the best
+ compromise between C and Ada. */
+ if (! TREE_UNSIGNED (sizetype)
+ && TREE_CODE (TYPE_MIN_VALUE (index)) != INTEGER_CST
+ && TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST)
+ length = size_binop (MAX_EXPR, length, size_zero_node);
TYPE_SIZE (type) = size_binop (MULT_EXPR, length,
TYPE_SIZE (element));
}
break;
- /* Pascal types */
- case BOOLEAN_TYPE: /* store one byte/boolean for now. */
+ /* Pascal and Chill types */
+ case BOOLEAN_TYPE: /* store one byte/boolean for now. */
TYPE_MODE (type) = QImode;
TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
TYPE_PRECISION (type) = 1;
TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+ if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
+ && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
+ TREE_UNSIGNED (type) = 1;
break;
- case CHAR_TYPE:
- TYPE_MODE (type) = QImode;
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
- TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type));
- TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
+ case SET_TYPE:
+ if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
+ || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
+ abort();
+ else
+ {
+#ifndef SET_WORD_SIZE
+#define SET_WORD_SIZE BITS_PER_WORD
+#endif
+ int alignment = set_alignment ? set_alignment : SET_WORD_SIZE;
+ int size_in_bits =
+ TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1;
+ int rounded_size
+ = ((size_in_bits + alignment - 1) / alignment) * alignment;
+ if (rounded_size > alignment)
+ TYPE_MODE (type) = BLKmode;
+ else
+ TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
+ TYPE_SIZE (type) = size_int (rounded_size);
+ TYPE_ALIGN (type) = alignment;
+ TYPE_PRECISION (type) = size_in_bits;
+ }
break;
case FILE_TYPE: