#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_tab[2], sbitsizetype, ubitsizetype;
+struct sizetype_tab sizetype_tab;
/* An integer constant with value 0 whose type is sizetype. */
{
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
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.
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
TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type),
MODE_INT);
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) = 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:
? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT),
0);
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) = 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) = 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;
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. */
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,
- size_binop (MINUS_EXPR, ub, lb));
+ 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, TYPE_SIZE (element),
- length);
+ /* 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;
else
TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
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;
}
return type;
}
-/* Set sizetype to TYPE, and initialize *bitsizetype accordingly.
+/* 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 precision = TYPE_PRECISION (type);
+ int oprecision = TYPE_PRECISION (type), precision;
sizetype = type;
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 += BITS_PER_UNIT_LOG + 1;
+ 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;
- (TREE_UNSIGNED (type) ? fixup_unsigned_type : fixup_signed_type)
- (bitsizetype);
+ if (TREE_UNSIGNED (type))
+ fixup_unsigned_type (bitsizetype);
+ else
+ fixup_signed_type (bitsizetype);
layout_type (bitsizetype);
- sbitsizetype = make_signed_type (precision);
- ubitsizetype = make_unsigned_type (precision);
+ 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,
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;
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;