#include "config.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))
struct sizetype_tab sizetype_tab;
tree size_zero_node;
tree size_one_node;
int maximum_field_alignment;
int set_alignment = 0;
static tree layout_record PROTO((tree));
static void layout_union PROTO((tree));
static tree pending_sizes;
int immediate_size_expand;
tree
get_pending_sizes ()
{
tree chain = pending_sizes;
tree t;
for (t = chain; t; t = TREE_CHAIN (t))
SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = current_function_decl;
pending_sizes = 0;
return chain;
}
void
put_pending_sizes (chain)
tree chain;
{
if (pending_sizes)
abort ();
pending_sizes = chain;
}
tree
variable_size (size)
tree size;
{
if (TREE_CONSTANT (size)
|| global_bindings_p () < 0 || contains_placeholder_p (size))
return size;
size = save_expr (size);
if (global_bindings_p ())
{
if (TREE_CONSTANT (size))
error ("type size can't be explicitly evaluated");
else
error ("variable-size type declared outside of any function");
return size_int (1);
}
if (immediate_size_expand)
expand_expr (size, expand_expr (integer_zero_node, NULL_PTR, VOIDmode, 0),
VOIDmode, 0);
else
pending_sizes = tree_cons (NULL_TREE, size, pending_sizes);
return size;
}
#ifndef MAX_FIXED_MODE_SIZE
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
#endif
enum machine_mode
mode_for_size (size, class, limit)
unsigned int size;
enum mode_class class;
int limit;
{
register enum machine_mode mode;
if (limit && size > (unsigned int)(MAX_FIXED_MODE_SIZE))
return BLKmode;
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned int)GET_MODE_BITSIZE (mode) == size)
return mode;
return BLKmode;
}
enum machine_mode
smallest_mode_for_size (size, class)
unsigned int size;
enum mode_class class;
{
register enum machine_mode mode;
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if ((unsigned int)GET_MODE_BITSIZE (mode) >= size)
return mode;
abort ();
}
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_VECTOR:
mode = BLKmode;
break;
case MODE_RANDOM:
if (mode == BLKmode)
break;
case MODE_CC:
default:
abort();
}
return mode;
}
tree
round_up (value, divisor)
tree value;
int divisor;
{
return size_binop (MULT_EXPR,
size_binop (CEIL_DIV_EXPR, value, size_int (divisor)),
size_int (divisor));
}
void
layout_decl (decl, known_align)
tree decl;
unsigned known_align;
{
register tree type = TREE_TYPE (decl);
register enum tree_code code = TREE_CODE (decl);
int spec_size = DECL_FIELD_SIZE (decl);
if (code == CONST_DECL)
return;
if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
&& code != FIELD_DECL && code != TYPE_DECL)
abort ();
if (type == error_mark_node)
{
type = void_type_node;
spec_size = 0;
}
DECL_MODE (decl) = TYPE_MODE (type);
TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
if (DECL_SIZE (decl) == 0)
DECL_SIZE (decl) = TYPE_SIZE (type);
if (code == FIELD_DECL && DECL_BIT_FIELD (decl))
{
if (spec_size == 0 && DECL_NAME (decl) != 0)
abort ();
DECL_SIZE (decl) = size_int (spec_size);
}
else if (DECL_ALIGN (decl) == 0
|| (! DECL_PACKED (decl) && TYPE_ALIGN (type) > DECL_ALIGN (decl)))
DECL_ALIGN (decl) = TYPE_ALIGN (type);
if (code == FIELD_DECL)
{
DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;
if (maximum_field_alignment != 0)
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl),
(unsigned)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
&& 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);
if (xmode != BLKmode
&& known_align % GET_MODE_ALIGNMENT (xmode) == 0)
{
DECL_ALIGN (decl) = MAX ((unsigned) GET_MODE_ALIGNMENT (xmode),
DECL_ALIGN (decl));
DECL_MODE (decl) = xmode;
DECL_SIZE (decl) = size_int (GET_MODE_BITSIZE (xmode));
DECL_BIT_FIELD (decl) = 0;
}
}
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;
if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
DECL_SIZE (decl) = variable_size (DECL_SIZE (decl));
}
static tree
layout_record (rec)
tree rec;
{
register tree field;
unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
tree pending_statics = NULL_TREE;
register HOST_WIDE_INT const_size = 0;
register tree var_size = 0;
register int var_align = BITS_PER_UNIT;
#ifdef STRUCTURE_SIZE_BOUNDARY
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 = 0;
if (TREE_CODE (field) == VAR_DECL)
{
pending_statics = tree_cons (NULL_TREE, field, pending_statics);
continue;
}
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (DECL_PACKED (field))
desired_align = DECL_ALIGN (field);
layout_decl (field, known_align);
if (! DECL_PACKED (field))
desired_align = DECL_ALIGN (field);
#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
#ifndef PCC_BITFIELD_TYPE_MATTERS
record_align = MAX (record_align, desired_align);
#else
if (PCC_BITFIELD_TYPE_MATTERS && TREE_TYPE (field) != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& ! integer_zerop (TYPE_SIZE (TREE_TYPE (field))))
{
if (! integer_zerop (DECL_SIZE (field)))
record_align = MAX ((int)record_align, desired_align);
else if (! DECL_PACKED (field))
desired_align = TYPE_ALIGN (TREE_TYPE (field));
if (DECL_NAME (field) != 0)
{
int type_align = TYPE_ALIGN (TREE_TYPE (field));
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);
record_align = MAX ((int)record_align, type_align);
}
}
else
record_align = MAX ((int)record_align, desired_align);
#endif
if (const_size % desired_align != 0
|| (var_align % desired_align != 0
&& var_size != 0))
{
if (var_size == 0
|| var_align % desired_align == 0)
const_size
= CEIL (const_size, desired_align) * desired_align;
else
{
if (const_size > 0)
var_size = size_binop (PLUS_EXPR, var_size,
bitsize_int (const_size, 0L));
const_size = 0;
var_size = round_up (var_size, desired_align);
var_align = MIN (var_align, desired_align);
}
}
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS
&& TREE_CODE (field) == FIELD_DECL
&& TREE_TYPE (field) != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& !DECL_PACKED (field)
&& maximum_field_alignment == 0
&& !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);
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
#ifdef BITFIELD_NBYTES_LIMITED
if (BITFIELD_NBYTES_LIMITED
&& TREE_CODE (field) == FIELD_DECL
&& TREE_TYPE (field) != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& !DECL_PACKED (field)
&& !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);
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);
if (const_size / type_align
!= (const_size + field_size - 1) / type_align)
const_size = CEIL (const_size, type_align) * type_align;
}
#endif
if (var_size && const_size)
DECL_FIELD_BITPOS (field)
= size_binop (PLUS_EXPR, var_size, bitsize_int (const_size, 0L));
else if (var_size)
DECL_FIELD_BITPOS (field) = var_size;
else
{
DECL_FIELD_BITPOS (field) = size_int (const_size);
if (known_align != const_size)
layout_decl (field, const_size);
}
{
register tree dsize = DECL_SIZE (field);
if (dsize == 0)
;
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)
const_size += TREE_INT_CST_LOW (dsize);
else
{
if (var_size == 0)
var_size = dsize;
else
var_size = size_binop (PLUS_EXPR, var_size, dsize);
}
}
}
if (var_size == 0)
{
TYPE_SIZE (rec) = size_int (const_size);
}
else
{
if (const_size)
var_size
= size_binop (PLUS_EXPR, var_size, bitsize_int (const_size, 0L));
TYPE_SIZE (rec) = var_size;
}
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), record_align);
#else
TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), record_align);
#endif
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_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));
#endif
return pending_statics;
}
static void
layout_union (rec)
tree rec;
{
register tree field;
unsigned union_align = BITS_PER_UNIT;
register int const_size = 0;
register tree var_size = 0;
#ifdef STRUCTURE_SIZE_BOUNDARY
if (! TYPE_PACKED (rec))
union_align = STRUCTURE_SIZE_BOUNDARY;
#endif
if (TREE_CODE (rec) == QUAL_UNION_TYPE)
TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL)
continue;
layout_decl (field, 0);
DECL_FIELD_BITPOS (field) = bitsize_int (0L, 0L);
union_align = MAX (union_align, DECL_ALIGN (field));
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
union_align = MAX (union_align, TYPE_ALIGN (TREE_TYPE (field)));
#endif
if (TREE_CODE (rec) == UNION_TYPE)
{
if (TREE_CODE (DECL_SIZE (field)) == INTEGER_CST)
const_size
= MAX (const_size, TREE_INT_CST_LOW (DECL_SIZE (field)));
else if (var_size == 0)
var_size = DECL_SIZE (field);
else
var_size = size_binop (MAX_EXPR, var_size, DECL_SIZE (field));
}
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 : bitsize_int (0L, 0L)));
}
if (TREE_CODE (rec) == QUAL_UNION_TYPE)
TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
if (NULL == var_size)
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 (bitsize_int (const_size, 0L),
BITS_PER_UNIT));
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), union_align);
#else
TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), union_align);
#endif
#ifdef ROUND_TYPE_SIZE
TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));
#else
TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));
#endif
}
void
layout_type (type)
tree type;
{
int old;
tree pending_statics;
if (type == 0)
abort ();
if (TYPE_SIZE (type))
return;
old = suspend_momentary ();
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
saveable_allocation ();
switch (TREE_CODE (type))
{
case LANG_TYPE:
abort ();
case BOOLEAN_TYPE:
if (TYPE_PRECISION (type) == 0)
TYPE_PRECISION (type) = 1;
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) = 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:
TREE_UNSIGNED (type) = TREE_UNSIGNED (TREE_TYPE (type));
TYPE_MODE (type)
= mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)),
(TREE_CODE (TREE_TYPE (type)) == INTEGER_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 VECTOR_TYPE:
TREE_UNSIGNED (type) = TREE_UNSIGNED (TREE_TYPE (type));
TYPE_MODE (type) = SVmode;
TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (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) = 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;
case ARRAY_TYPE:
{
register tree index = TYPE_DOMAIN (type);
register tree element = TREE_TYPE (type);
build_pointer_type (element);
if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
&& TYPE_SIZE (element))
{
tree ub = TYPE_MAX_VALUE (index);
tree lb = TYPE_MIN_VALUE (index);
tree length;
tree element_size;
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,
fold (build (MINUS_EXPR, TREE_TYPE (lb),
ub, lb)));
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);
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 (TYPE_SIZE_UNIT (element) != 0
&& element_size != integer_one_node)
{
TYPE_SIZE_UNIT (type)
= size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length);
}
}
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (type)
= ROUND_TYPE_ALIGN (type, TYPE_ALIGN (element), BITS_PER_UNIT);
#else
TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
#endif
#ifdef ROUND_TYPE_SIZE
if (TYPE_SIZE (type) != 0)
{
tree tmp;
tmp = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
if (simple_cst_equal (TYPE_SIZE (type), tmp) != 1)
TYPE_SIZE_UNIT (type) = NULL;
TYPE_SIZE (type) = tmp;
}
#endif
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
|| TYPE_NO_FORCE_BLK (TREE_TYPE (type))))
{
TYPE_MODE (type)
= mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
MODE_INT, 1);
if (STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT
&& (int)TYPE_ALIGN (type) < TREE_INT_CST_LOW (TYPE_SIZE (type))
&& TYPE_MODE (type) != BLKmode)
{
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
}
break;
}
case RECORD_TYPE:
pending_statics = layout_record (type);
TYPE_MODE (type) = BLKmode;
if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
tree field;
enum machine_mode mode = VOIDmode;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
int bitpos;
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
&& ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
goto record_lose;
if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST)
goto record_lose;
bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
if (bitpos / BITS_PER_WORD
!= ((TREE_INT_CST_LOW (DECL_SIZE (field)) + bitpos - 1)
/ BITS_PER_WORD)
&& TREE_INT_CST_LOW (DECL_SIZE (field)) % BITS_PER_WORD != 0)
goto record_lose;
if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
mode = DECL_MODE (field);
}
if (mode != VOIDmode)
TYPE_MODE (type) = mode;
else
#if defined (NEXT_SEMANTICS) && defined (TARGET_TOC)
if (mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
MODE_INT, 1) != DImode
|| !flag_pic)
#endif
TYPE_MODE (type)
= mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
MODE_INT, 1);
if (STRICT_ALIGNMENT
&& ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
|| ((int)TYPE_ALIGN (type)
>= TREE_INT_CST_LOW (TYPE_SIZE (type)))))
{
if (TYPE_MODE (type) != BLKmode)
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
record_lose: ;
}
while (pending_statics)
{
layout_decl (TREE_VALUE (pending_statics), 0);
pending_statics = TREE_CHAIN (pending_statics);
}
break;
case UNION_TYPE:
case QUAL_UNION_TYPE:
layout_union (type);
TYPE_MODE (type) = BLKmode;
if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& (! STRICT_ALIGNMENT
|| TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
|| (int)TYPE_ALIGN (type) >= TREE_INT_CST_LOW (TYPE_SIZE (type))))
{
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
&& ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
goto union_lose;
}
#if defined (NEXT_SEMANTICS) && defined (TARGET_TOC)
if (mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
MODE_INT, 1) != DImode
|| !flag_pic)
#endif
TYPE_MODE (type)
= mode_for_size (TREE_INT_CST_LOW (TYPE_SIZE (type)),
MODE_INT, 1);
union_lose: ;
}
break;
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) = 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;
}
break;
case FILE_TYPE:
TYPE_ALIGN (type) = BIGGEST_ALIGNMENT;
TYPE_MODE (type) = BLKmode;
break;
default:
abort ();
}
if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode
&& (STRICT_ALIGNMENT
|| (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE
&& TREE_CODE (type) != QUAL_UNION_TYPE
&& TREE_CODE (type) != ARRAY_TYPE)))
TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (type)
= ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
#endif
#ifdef ROUND_TYPE_SIZE
if (TYPE_SIZE (type) != 0)
TYPE_SIZE (type)
= ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
#endif
if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
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));
}
if (TYPE_SIZE_UNIT (type) != 0
&& TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
if (TYPE_NEXT_VARIANT (type)
|| type != TYPE_MAIN_VARIANT (type))
{
tree 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);
for (variant = TYPE_MAIN_VARIANT (type);
variant;
variant = TYPE_NEXT_VARIANT (variant))
{
TYPE_SIZE (variant) = size;
TYPE_SIZE_UNIT (variant) = size_unit;
TYPE_ALIGN (variant) = align;
TYPE_MODE (variant) = mode;
}
}
pop_obstacks ();
resume_momentary (old);
}
tree
make_signed_type (precision)
int precision;
{
register tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
TYPE_MIN_VALUE (type)
= build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
(((HOST_WIDE_INT) (-1)
<< (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
? precision - HOST_BITS_PER_WIDE_INT - 1
: 0))));
TYPE_MAX_VALUE (type)
= build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
(precision - HOST_BITS_PER_WIDE_INT - 1 > 0
? (((HOST_WIDE_INT) 1
<< (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
: 0));
TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
if (sizetype == 0)
set_sizetype (type);
layout_type (type);
return type;
}
tree
make_unsigned_type (precision)
int precision;
{
register tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
if (sizetype == 0)
{
TREE_UNSIGNED (type) = 1;
set_sizetype (type);
}
fixup_unsigned_type (type);
return type;
}
void
set_sizetype (type)
tree type;
{
int oprecision = TYPE_PRECISION (type), precision;
sizetype = type;
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;
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);
}
}
void
fixup_signed_type (type)
tree type;
{
register int precision = TYPE_PRECISION (type);
TYPE_MIN_VALUE (type)
= build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
(((HOST_WIDE_INT) (-1)
<< (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
? precision - HOST_BITS_PER_WIDE_INT - 1
: 0))));
TYPE_MAX_VALUE (type)
= build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
(precision - HOST_BITS_PER_WIDE_INT - 1 > 0
? (((HOST_WIDE_INT) 1
<< (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
: 0));
TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
layout_type (type);
}
void
fixup_unsigned_type (type)
tree type;
{
register int precision = TYPE_PRECISION (type);
TYPE_MIN_VALUE (type) = build_int_2 (0, 0);
TYPE_MAX_VALUE (type)
= build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
precision - HOST_BITS_PER_WIDE_INT > 0
? ((unsigned HOST_WIDE_INT) ~0
>> (HOST_BITS_PER_WIDE_INT
- (precision - HOST_BITS_PER_WIDE_INT)))
: 0);
TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
layout_type (type);
}
enum machine_mode
get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
int bitsize, bitpos;
int align;
enum machine_mode largest_mode;
int volatilep;
{
enum machine_mode mode;
int unit = 0;
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
{
unit = GET_MODE_BITSIZE (mode);
if ((bitpos % unit) + bitsize <= unit)
break;
}
if (mode == MAX_MACHINE_MODE
|| MIN (unit, BIGGEST_ALIGNMENT) > align
|| (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode)))
return VOIDmode;
if (SLOW_BYTE_ACCESS && ! volatilep)
{
enum machine_mode wide_mode = VOIDmode, tmode;
for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT); tmode != VOIDmode;
tmode = GET_MODE_WIDER_MODE (tmode))
{
unit = GET_MODE_BITSIZE (tmode);
if (bitpos / unit == (bitpos + bitsize - 1) / unit
&& unit <= BITS_PER_WORD
&& unit <= MIN (align, BIGGEST_ALIGNMENT)
&& (largest_mode == VOIDmode
|| unit <= GET_MODE_BITSIZE (largest_mode)))
wide_mode = tmode;
}
if (wide_mode != VOIDmode)
return wide_mode;
}
return mode;
}
void
save_storage_status (p)
struct function *p ATTRIBUTE_UNUSED;
{
#if 0
p->pending_sizes = pending_sizes;
p->immediate_size_expand = immediate_size_expand;
#endif
}
void
restore_storage_status (p)
struct function *p ATTRIBUTE_UNUSED;
{
#if 0
pending_sizes = p->pending_sizes;
immediate_size_expand = p->immediate_size_expand;
#endif
}