/* C-compiler utilities for types and variables storage layout
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
#include "config.h"
-#include <stdio.h>
+#include "system.h"
#include "tree.h"
+#include "rtl.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
+#include "expr.h"
+#include "toplev.h"
#define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Data type for the expressions representing sizes of data types.
- It is the first integer type laid out.
- In C, this is int. */
+ It is the first integer type laid out. */
-tree sizetype;
+struct sizetype_tab sizetype_tab;
/* An integer constant with value 0 whose type is sizetype. */
May be overridden by front-ends. */
int set_alignment = 0;
-#define GET_MODE_ALIGNMENT(MODE) \
- MIN (BIGGEST_ALIGNMENT, \
- MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)))
-
static enum machine_mode smallest_mode_for_size PROTO((unsigned int,
enum mode_class));
static tree layout_record PROTO((tree));
return chain;
}
+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. */
{
register enum machine_mode mode;
- if (limit && size > MAX_FIXED_MODE_SIZE)
+ if (limit && size > (unsigned int)(MAX_FIXED_MODE_SIZE))
return BLKmode;
/* 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 ((unsigned int)GET_MODE_BITSIZE (mode) == size)
return mode;
return BLKmode;
specified class. */
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
- if (GET_MODE_BITSIZE (mode) >= size)
+ if ((unsigned int)GET_MODE_BITSIZE (mode) >= size)
return mode;
abort ();
}
+/* Find an integer mode of the exact same size, or BLKmode on failure. */
+
+enum machine_mode
+int_mode_for_mode (mode)
+ enum machine_mode mode;
+{
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+ break;
+
+ case MODE_RANDOM:
+ if (mode == BLKmode)
+ break;
+ /* FALLTHRU */
+
+ case MODE_CC:
+ default:
+ abort();
+ }
+
+ return mode;
+}
+
/* Return the value of VALUE, rounded up to a multiple of DIVISOR. */
tree
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 (flag_pack_struct)
+ 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));
tree rec;
{
register tree field;
-#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned record_align = MAX (STRUCTURE_SIZE_BOUNDARY, TYPE_ALIGN (rec));
-#else
unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
-#endif
/* These must be laid out *after* the record is. */
tree pending_statics = NULL_TREE;
/* Record size so far is CONST_SIZE + VAR_SIZE bits,
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. */
register int var_align = BITS_PER_UNIT;
+#ifdef STRUCTURE_SIZE_BOUNDARY
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (rec))
+ record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
+#endif
for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
{
register int known_align = var_size ? var_align : const_size;
- register int desired_align;
+ register int desired_align = 0;
/* If FIELD is static, then treat it like a separate variable,
not really like a structure field.
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;
#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 (flag_pack_struct)
+ else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
record_align = MAX (record_align, type_align);
{
if (const_size > 0)
var_size = size_binop (PLUS_EXPR, var_size,
- size_int (const_size));
+ bitsize_int (const_size, 0L));
const_size = 0;
var_size = round_up (var_size, desired_align);
var_align = MIN (var_align, desired_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
- && !flag_pack_struct
&& !integer_zerop (DECL_SIZE (field)))
{
int type_align = TYPE_ALIGN (TREE_TYPE (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 - 1) / 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 (flag_pack_struct)
+ /* ??? This test is opposite the test in the containing if
+ statement, so this code is unreachable currently. */
+ else if (DECL_PACKED (field))
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. */
+ /* ??? This code should match the code above for the
+ PCC_BITFIELD_TYPE_MATTERS case. */
if (const_size / type_align
!= (const_size + field_size - 1) / type_align)
const_size = CEIL (const_size, type_align) * type_align;
if (var_size && const_size)
DECL_FIELD_BITPOS (field)
- = size_binop (PLUS_EXPR, var_size, size_int (const_size));
+ = size_binop (PLUS_EXPR, var_size, bitsize_int (const_size, 0L));
else if (var_size)
DECL_FIELD_BITPOS (field) = var_size;
else
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
{
if (const_size)
var_size
- = size_binop (PLUS_EXPR, var_size, size_int (const_size));
+ = size_binop (PLUS_EXPR, var_size, bitsize_int (const_size, 0L));
TYPE_SIZE (rec) = var_size;
}
TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), record_align);
#endif
+ /* Record the un-rounded size in the binfo node. But first we check
+ the size of TYPE_BINFO to make sure that BINFO_SIZE is available. */
+ if (TYPE_BINFO (rec) && TREE_VEC_LENGTH (TYPE_BINFO (rec)) > 6)
+ TYPE_BINFO_SIZE (rec) = TYPE_SIZE (rec);
+
#ifdef ROUND_TYPE_SIZE
TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));
#else
tree rec;
{
register tree field;
-#ifdef STRUCTURE_SIZE_BOUNDARY
- unsigned union_align = STRUCTURE_SIZE_BOUNDARY;
-#else
unsigned union_align = BITS_PER_UNIT;
-#endif
/* The size of the union, based on the fields scanned so far,
is max (CONST_SIZE, VAR_SIZE).
register int const_size = 0;
register tree var_size = 0;
+#ifdef STRUCTURE_SIZE_BOUNDARY
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (rec))
+ union_align = STRUCTURE_SIZE_BOUNDARY;
+#endif
+
/* If this is a QUAL_UNION_TYPE, we want to process the fields in
the reverse order in building the COND_EXPR that denotes its
size. We reverse them again later. */
continue;
layout_decl (field, 0);
- DECL_FIELD_BITPOS (field) = size_int (0);
+ DECL_FIELD_BITPOS (field) = bitsize_int (0L, 0L);
/* Union must be at least as aligned as any field requires. */
else if (TREE_CODE (rec) == QUAL_UNION_TYPE)
var_size = fold (build (COND_EXPR, sizetype, DECL_QUALIFIER (field),
DECL_SIZE (field),
- var_size ? var_size : integer_zero_node));
+ var_size ? var_size : bitsize_int (0L, 0L)));
}
if (TREE_CODE (rec) == QUAL_UNION_TYPE)
/* Determine the ultimate size of the union (in bytes). */
if (NULL == var_size)
- TYPE_SIZE (rec) = size_int (CEIL (const_size, BITS_PER_UNIT)
- * BITS_PER_UNIT);
+ TYPE_SIZE (rec) = bitsize_int (CEIL (const_size, BITS_PER_UNIT)
+ * BITS_PER_UNIT, 0L);
else if (const_size == 0)
TYPE_SIZE (rec) = var_size;
else
TYPE_SIZE (rec) = size_binop (MAX_EXPR, var_size,
- round_up (size_int (const_size),
+ round_up (bitsize_int (const_size, 0L),
BITS_PER_UNIT));
/* Determine the desired alignment. */
of the language-specific code. */
abort ();
+ case BOOLEAN_TYPE: /* Used for Java, Pascal, and Chill. */
+ if (TYPE_PRECISION (type) == 0)
+ TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
+ /* ... fall through ... */
+
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)
TREE_UNSIGNED (type) = 1;
TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type),
MODE_INT);
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+ TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
case REAL_TYPE:
TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0);
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+ TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
case COMPLEX_TYPE:
(TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT),
0);
- TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
+ TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+ TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
case VOID_TYPE:
TYPE_SIZE (type) = size_zero_node;
+ TYPE_SIZE_UNIT (type) = size_zero_node;
TYPE_ALIGN (type) = 1;
TYPE_MODE (type) = VOIDmode;
break;
case OFFSET_TYPE:
- TYPE_SIZE (type) = size_int (POINTER_SIZE);
+ TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
+ TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
TYPE_MODE (type) = ptr_mode;
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
- TYPE_SIZE (type) = size_int (2 * POINTER_SIZE);
+ TYPE_SIZE (type) = bitsize_int (2 * POINTER_SIZE, 0);
+ TYPE_SIZE_UNIT (type) = size_int ((2 * POINTER_SIZE) / BITS_PER_UNIT);
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
TYPE_MODE (type) = ptr_mode;
- TYPE_SIZE (type) = size_int (POINTER_SIZE);
+ TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
+ TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
TREE_UNSIGNED (type) = 1;
TYPE_PRECISION (type) = POINTER_SIZE;
break;
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;
+ tree element_size;
+
+ /* 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);
+
+ /* 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,
+ fold (build (MINUS_EXPR, TREE_TYPE (lb),
+ ub, lb)));
/* If neither bound is a constant and sizetype is signed, make
sure the size is never negative. We should really do this
&& 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));
+ /* Special handling for arrays of bits (for Chill). */
+ element_size = TYPE_SIZE (element);
+ if (TYPE_PACKED (type) && INTEGRAL_TYPE_P (element))
+ {
+ HOST_WIDE_INT maxvalue, minvalue;
+ maxvalue = TREE_INT_CST_LOW (TYPE_MAX_VALUE (element));
+ minvalue = TREE_INT_CST_LOW (TYPE_MIN_VALUE (element));
+ if (maxvalue - minvalue == 1
+ && (maxvalue == 1 || maxvalue == 0))
+ element_size = integer_one_node;
+ }
+
+ TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size, length);
+
+ /* If we know the size of the element, calculate the total
+ size directly, rather than do some division thing below.
+ This optimization helps Fortran assumed-size arrays
+ (where the size of the array is determined at runtime)
+ substantially.
+ Note that we can't do this in the case where the size of
+ the elements is one bit since TYPE_SIZE_UNIT cannot be
+ set correctly in that case. */
+ if (TYPE_SIZE_UNIT (element) != 0
+ && element_size != integer_one_node)
+ {
+ TYPE_SIZE_UNIT (type)
+ = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length);
+ }
}
/* Now round the alignment and size,
#ifdef ROUND_TYPE_SIZE
if (TYPE_SIZE (type) != 0)
- TYPE_SIZE (type)
- = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
+ {
+ tree tmp;
+ tmp = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
+ /* If the rounding changed the size of the type, remove any
+ pre-calculated TYPE_SIZE_UNIT. */
+ if (simple_cst_equal (TYPE_SIZE (type), tmp) != 1)
+ TYPE_SIZE_UNIT (type) = NULL;
+ TYPE_SIZE (type) = tmp;
+ }
#endif
TYPE_MODE (type) = BLKmode;
if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
tree field;
+ enum machine_mode mode = VOIDmode;
+
/* A record which has any BLKmode members must itself be BLKmode;
it can't go in a register.
Unless the member is BLKmode only because it isn't aligned. */
!= ((TREE_INT_CST_LOW (DECL_SIZE (field)) + bitpos - 1)
/ BITS_PER_WORD)
/* But there is no problem if the field is entire words. */
- && TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD == 0)
+ && TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD != 0)
goto record_lose;
+
+ /* If this field is the whole struct, remember its mode so
+ that, say, we can put a double in a class into a DF
+ register instead of forcing it to live in the stack. */
+ if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
+ mode = DECL_MODE (field);
}
- TYPE_MODE (type)
- = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
- MODE_INT, 1);
+ if (mode != VOIDmode)
+ /* We only have one real field; use its mode. */
+ TYPE_MODE (type) = mode;
+ else
+ TYPE_MODE (type)
+ = mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
+ MODE_INT, 1);
/* If structure's known alignment is less than
what the scalar mode would need, and it matters,
}
break;
- /* 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));
- break;
-
- case SET_TYPE:
+ case SET_TYPE: /* Used by Chill and Pascal. */
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
|| TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
abort();
#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 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_SIZE (type) = bitsize_int (rounded_size, 0L);
+ TYPE_SIZE_UNIT (type) = size_int (rounded_size / BITS_PER_UNIT);
TYPE_ALIGN (type) = alignment;
TYPE_PRECISION (type) = size_in_bits;
}
if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
+ /* If we failed to find a simple way to calculate the unit size
+ of the type above, find it by division. */
+ if (TYPE_SIZE_UNIT (type) == 0 && TYPE_SIZE (type) != 0)
+ {
+ TYPE_SIZE_UNIT (type) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+ size_int (BITS_PER_UNIT));
+ }
+
+ /* Once again evaluate only once, either now or as soon as safe. */
+ if (TYPE_SIZE_UNIT (type) != 0
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
+ TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
+
/* Also layout any other variants of the type. */
if (TYPE_NEXT_VARIANT (type)
|| type != TYPE_MAIN_VARIANT (type))
tree variant;
/* Record layout info of this variant. */
tree size = TYPE_SIZE (type);
+ tree size_unit = TYPE_SIZE_UNIT (type);
int align = TYPE_ALIGN (type);
enum machine_mode mode = TYPE_MODE (type);
variant = TYPE_NEXT_VARIANT (variant))
{
TYPE_SIZE (variant) = size;
+ TYPE_SIZE_UNIT (variant) = size_unit;
TYPE_ALIGN (variant) = align;
TYPE_MODE (variant) = mode;
}
is the type for size values. */
if (sizetype == 0)
- {
- sizetype = type;
- }
+ set_sizetype (type);
/* Lay out the type: set its alignment, size, etc. */
if (sizetype == 0)
{
- sizetype = type;
+ TREE_UNSIGNED (type) = 1;
+ set_sizetype (type);
}
fixup_unsigned_type (type);
return type;
}
+/* Set sizetype to TYPE, and initialize *sizetype accordingly.
+ Also update the type of any standard type's sizes made so far. */
+
+void
+set_sizetype (type)
+ tree type;
+{
+ int oprecision = TYPE_PRECISION (type), precision;
+
+ sizetype = type;
+
+ /* The *bitsizetype types use a precision that avoids overflows when
+ calculating signed sizes / offsets in bits.
+
+ We are allocating bitsizetype once and change it in place when
+ we decide later that we want to change it. This way, we avoid the
+ hassle of changing all the TYPE_SIZE (TREE_TYPE (sometype))
+ individually in each front end. */
+ if (! bitsizetype)
+ bitsizetype = make_node (INTEGER_TYPE);
+ if (TYPE_NAME (sizetype) && ! TYPE_NAME (bitsizetype))
+ TYPE_NAME (bitsizetype) = TYPE_NAME (sizetype);
+
+ precision = oprecision + BITS_PER_UNIT_LOG + 1;
+ /* However, when cross-compiling from a 32 bit to a 64 bit host,
+ we are limited to 64 bit precision. */
+ if (precision > 2 * HOST_BITS_PER_WIDE_INT)
+ precision = 2 * HOST_BITS_PER_WIDE_INT;
+ TYPE_PRECISION (bitsizetype) = precision;
+ if (TREE_UNSIGNED (type))
+ fixup_unsigned_type (bitsizetype);
+ else
+ fixup_signed_type (bitsizetype);
+ layout_type (bitsizetype);
+
+ if (TREE_UNSIGNED (type))
+ {
+ usizetype = sizetype;
+ ubitsizetype = bitsizetype;
+ ssizetype = make_signed_type (oprecision);
+ sbitsizetype = make_signed_type (precision);
+ }
+ else
+ {
+ ssizetype = sizetype;
+ sbitsizetype = bitsizetype;
+ usizetype = make_unsigned_type (oprecision);
+ ubitsizetype = make_unsigned_type (precision);
+ }
+}
+
/* Set the extreme values of TYPE based on its precision in bits,
then lay it out. Used when make_signed_type won't do
because the tree code is not INTEGER_TYPE.
int volatilep;
{
enum machine_mode mode;
- int unit;
+ int unit = 0;
/* Find the narrowest integer mode that contains the bit field. */
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
unit = GET_MODE_BITSIZE (mode);
- if (bitpos / unit == (bitpos + bitsize - 1) / unit)
+ if ((bitpos % unit) + bitsize <= unit)
break;
}
void
save_storage_status (p)
- struct function *p;
+ struct function *p ATTRIBUTE_UNUSED;
{
#if 0 /* Need not save, since always 0 and non0 (resp.) within a function. */
p->pending_sizes = pending_sizes;
void
restore_storage_status (p)
- struct function *p;
+ struct function *p ATTRIBUTE_UNUSED;
{
#if 0
pending_sizes = p->pending_sizes;