#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
#include "toplev.h"
#include "ggc.h"
#include "target.h"
static int sizetype_set;
static tree early_type_list;
tree sizetype_tab[(int) TYPE_KIND_LAST];
unsigned int maximum_field_alignment;
unsigned int set_alignment = 0;
static int reference_types_internal = 0;
static void finalize_record_size PARAMS ((record_layout_info));
static void finalize_type_size PARAMS ((tree));
static void place_union_field PARAMS ((record_layout_info, tree));
extern void debug_rli PARAMS ((record_layout_info));
static tree pending_sizes;
int immediate_size_expand;
extern int compiling_objc;
int darwin_align_is_first_member_of_class = 0;
void
internal_reference_types ()
{
reference_types_internal = 1;
}
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;
}
int
is_pending_size (expr)
tree expr;
{
tree t;
for (t = pending_sizes; t; t = TREE_CHAIN (t))
if (TREE_VALUE (t) == expr)
return 1;
return 0;
}
void
put_pending_size (expr)
tree expr;
{
while (TREE_CODE_CLASS (TREE_CODE (expr)) == '1'
|| (TREE_CODE_CLASS (TREE_CODE (expr)) == '2'
&& TREE_CONSTANT (TREE_OPERAND (expr, 1))))
expr = TREE_OPERAND (expr, 0);
if (TREE_CODE (expr) == SAVE_EXPR)
pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);
}
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 (TREE_CODE (size) == SAVE_EXPR)
SAVE_EXPR_PERSISTENT_P (size) = 1;
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_one_node;
}
if (immediate_size_expand)
expand_expr (size, expand_expr (integer_zero_node, NULL_RTX, VOIDmode, 0),
VOIDmode, 0);
else if (cfun != 0 && cfun->x_dont_save_pending_sizes_p)
;
else
put_pending_size (size);
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;
{
enum machine_mode mode;
if (limit && size > MAX_FIXED_MODE_SIZE)
return BLKmode;
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if (GET_MODE_BITSIZE (mode) == size)
return mode;
return BLKmode;
}
enum machine_mode
mode_for_size_tree (size, class, limit)
tree size;
enum mode_class class;
int limit;
{
if (TREE_CODE (size) != INTEGER_CST
|| compare_tree_int (size, 1000) > 0)
return BLKmode;
else
return mode_for_size (TREE_INT_CST_LOW (size), class, limit);
}
enum machine_mode
smallest_mode_for_size (size, class)
unsigned int size;
enum mode_class class;
{
enum machine_mode mode;
for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
if (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:
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
break;
case MODE_RANDOM:
if (mode == BLKmode)
break;
case MODE_CC:
default:
abort ();
}
return mode;
}
tree
round_up (value, divisor)
tree value;
int divisor;
{
tree arg = size_int_type (divisor, TREE_TYPE (value));
return size_binop (MULT_EXPR, size_binop (CEIL_DIV_EXPR, value, arg), arg);
}
tree
round_down (value, divisor)
tree value;
int divisor;
{
tree arg = size_int_type (divisor, TREE_TYPE (value));
return size_binop (MULT_EXPR, size_binop (FLOOR_DIV_EXPR, value, arg), arg);
}
void
layout_decl (decl, known_align)
tree decl;
unsigned int known_align;
{
tree type = TREE_TYPE (decl);
enum tree_code code = TREE_CODE (decl);
if (code == CONST_DECL)
return;
else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
&& code != TYPE_DECL && code != FIELD_DECL)
abort ();
if (type == error_mark_node)
type = void_type_node;
TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
if (DECL_MODE (decl) == VOIDmode)
DECL_MODE (decl) = TYPE_MODE (type);
if (DECL_SIZE (decl) == 0)
{
DECL_SIZE (decl) = TYPE_SIZE (type);
DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
}
else
DECL_SIZE_UNIT (decl)
= convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
bitsize_unit_node));
if (! (code == FIELD_DECL && DECL_BIT_FIELD (decl))
&& (DECL_ALIGN (decl) == 0
|| (! (code == FIELD_DECL && DECL_PACKED (decl))
&& TYPE_ALIGN (type) > DECL_ALIGN (decl))))
{
DECL_ALIGN (decl) = TYPE_ALIGN (type);
DECL_USER_ALIGN (decl) = 0;
}
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), maximum_field_alignment);
else if (DECL_PACKED (decl)
&& (DECL_NONADDRESSABLE_P (decl)
|| DECL_SIZE_UNIT (decl) == 0
|| TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
{
DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
DECL_USER_ALIGN (decl) = 0;
}
#ifdef PEG_ALIGN_FOR_MAC68K
else if (TARGET_ALIGN_MAC68K)
DECL_ALIGN (decl) = PEG_ALIGN_FOR_MAC68K (DECL_ALIGN (decl));
#endif
}
if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
&& TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
{
enum machine_mode xmode
= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
{
DECL_ALIGN (decl) = MAX (GET_MODE_ALIGNMENT (xmode),
DECL_ALIGN (decl));
DECL_MODE (decl) = xmode;
if (!compiling_objc)
DECL_BIT_FIELD (decl) = 0;
}
}
if (code == FIELD_DECL && DECL_BIT_FIELD (decl) && !compiling_objc
&& TYPE_MODE (type) == BLKmode && DECL_MODE (decl) == BLKmode
&& known_align >= TYPE_ALIGN (type)
&& DECL_ALIGN (decl) >= TYPE_ALIGN (type)
&& DECL_SIZE_UNIT (decl) != 0)
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));
if (DECL_SIZE_UNIT (decl) != 0
&& TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST)
DECL_SIZE_UNIT (decl) = variable_size (DECL_SIZE_UNIT (decl));
if (warn_larger_than
&& (code == VAR_DECL || code == PARM_DECL)
&& ! DECL_EXTERNAL (decl))
{
tree size = DECL_SIZE_UNIT (decl);
if (size != 0 && TREE_CODE (size) == INTEGER_CST
&& compare_tree_int (size, larger_than_size) > 0)
{
unsigned int size_as_int = TREE_INT_CST_LOW (size);
if (compare_tree_int (size, size_as_int) == 0)
warning_with_decl (decl, "size of `%s' is %d bytes", size_as_int);
else
warning_with_decl (decl, "size of `%s' is larger than %d bytes",
larger_than_size);
}
}
}
void (*lang_adjust_rli) PARAMS ((record_layout_info)) = 0;
void
set_lang_adjust_rli (f)
void (*f) PARAMS ((record_layout_info));
{
lang_adjust_rli = f;
}
record_layout_info
start_record_layout (t)
tree t;
{
record_layout_info rli
= (record_layout_info) xmalloc (sizeof (struct record_layout_info_s));
rli->t = t;
rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
rli->unpacked_align = rli->unpadded_align = rli->record_align;
rli->offset_align = MAX (rli->record_align, BIGGEST_ALIGNMENT);
#ifdef STRUCTURE_SIZE_BOUNDARY
if (! TYPE_PACKED (t))
rli->record_align = MAX (rli->record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
rli->offset = size_zero_node;
rli->bitpos = bitsize_zero_node;
rli->prev_field = 0;
rli->pending_statics = 0;
rli->packed_maybe_necessary = 0;
return rli;
}
tree
bit_from_pos (offset, bitpos)
tree offset, bitpos;
{
return size_binop (PLUS_EXPR, bitpos,
size_binop (MULT_EXPR, convert (bitsizetype, offset),
bitsize_unit_node));
}
tree
byte_from_pos (offset, bitpos)
tree offset, bitpos;
{
return size_binop (PLUS_EXPR, offset,
convert (sizetype,
size_binop (TRUNC_DIV_EXPR, bitpos,
bitsize_unit_node)));
}
void
pos_from_byte (poffset, pbitpos, off_align, pos)
tree *poffset, *pbitpos;
unsigned int off_align;
tree pos;
{
*poffset
= size_binop (MULT_EXPR,
convert (sizetype,
size_binop (FLOOR_DIV_EXPR, pos,
bitsize_int (off_align
/ BITS_PER_UNIT))),
size_int (off_align / BITS_PER_UNIT));
*pbitpos = size_binop (MULT_EXPR,
size_binop (FLOOR_MOD_EXPR, pos,
bitsize_int (off_align / BITS_PER_UNIT)),
bitsize_unit_node);
}
void
pos_from_bit (poffset, pbitpos, off_align, pos)
tree *poffset, *pbitpos;
unsigned int off_align;
tree pos;
{
*poffset = size_binop (MULT_EXPR,
convert (sizetype,
size_binop (FLOOR_DIV_EXPR, pos,
bitsize_int (off_align))),
size_int (off_align / BITS_PER_UNIT));
*pbitpos = size_binop (FLOOR_MOD_EXPR, pos, bitsize_int (off_align));
}
void
normalize_offset (poffset, pbitpos, off_align)
tree *poffset, *pbitpos;
unsigned int off_align;
{
if (compare_tree_int (*pbitpos, off_align) >= 0)
{
tree extra_aligns = size_binop (FLOOR_DIV_EXPR, *pbitpos,
bitsize_int (off_align));
*poffset
= size_binop (PLUS_EXPR, *poffset,
size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
size_int (off_align / BITS_PER_UNIT)));
*pbitpos
= size_binop (FLOOR_MOD_EXPR, *pbitpos, bitsize_int (off_align));
}
}
void
debug_rli (rli)
record_layout_info rli;
{
print_node_brief (stderr, "type", rli->t, 0);
print_node_brief (stderr, "\noffset", rli->offset, 0);
print_node_brief (stderr, " bitpos", rli->bitpos, 0);
fprintf (stderr, "\naligns: rec = %u, unpack = %u, unpad = %u, off = %u\n",
rli->record_align, rli->unpacked_align, rli->unpadded_align,
rli->offset_align);
if (rli->packed_maybe_necessary)
fprintf (stderr, "packed may be necessary\n");
if (rli->pending_statics)
{
fprintf (stderr, "pending statics:\n");
debug_tree (rli->pending_statics);
}
}
void
normalize_rli (rli)
record_layout_info rli;
{
normalize_offset (&rli->offset, &rli->bitpos, rli->offset_align);
}
tree
rli_size_unit_so_far (rli)
record_layout_info rli;
{
return byte_from_pos (rli->offset, rli->bitpos);
}
tree
rli_size_so_far (rli)
record_layout_info rli;
{
return bit_from_pos (rli->offset, rli->bitpos);
}
static void
place_union_field (rli, field)
record_layout_info rli;
tree field;
{
unsigned int desired_align;
layout_decl (field, 0);
DECL_FIELD_OFFSET (field) = size_zero_node;
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
desired_align = DECL_ALIGN (field);
#ifdef BIGGEST_FIELD_ALIGNMENT
if (! DECL_USER_ALIGN (field))
desired_align =
MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#if 0
#ifdef ADJUST_FIELD_ALIGN
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
#endif
#endif
TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
rli->record_align = MAX (rli->record_align, desired_align);
rli->unpadded_align = MAX (rli->unpadded_align, desired_align);
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
{
rli->record_align = MAX (rli->record_align,
TYPE_ALIGN (TREE_TYPE (field)));
rli->unpadded_align = MAX (rli->unpadded_align,
TYPE_ALIGN (TREE_TYPE (field)));
}
#endif
if (TREE_CODE (rli->t) == UNION_TYPE)
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
rli->offset = fold (build (COND_EXPR, sizetype,
DECL_QUALIFIER (field),
DECL_SIZE_UNIT (field), rli->offset));
}
void
place_field (rli, field)
record_layout_info rli;
tree field;
{
unsigned int desired_align;
unsigned int known_align;
unsigned int actual_align;
unsigned int user_align;
tree type = TREE_TYPE (field);
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
return;
if (TREE_CODE (field) == VAR_DECL)
{
rli->pending_statics = tree_cons (NULL_TREE, field,
rli->pending_statics);
return;
}
else if (TREE_CODE (field) != FIELD_DECL)
return;
else if (TREE_CODE (rli->t) != RECORD_TYPE)
{
place_union_field (rli, field);
return;
}
if (! integer_zerop (rli->bitpos))
known_align = (tree_low_cst (rli->bitpos, 1)
& - tree_low_cst (rli->bitpos, 1));
else if (integer_zerop (rli->offset))
known_align = BIGGEST_ALIGNMENT;
else if (host_integerp (rli->offset, 1))
known_align = (BITS_PER_UNIT
* (tree_low_cst (rli->offset, 1)
& - tree_low_cst (rli->offset, 1)));
else
known_align = rli->offset_align;
desired_align = DECL_ALIGN (field);
user_align = DECL_USER_ALIGN (field);
layout_decl (field, known_align);
if (! DECL_PACKED (field))
{
desired_align = DECL_ALIGN (field);
user_align = DECL_USER_ALIGN (field);
}
#ifdef BIGGEST_FIELD_ALIGNMENT
if (! user_align)
desired_align
= MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
desired_align = ADJUST_FIELD_ALIGN (field, desired_align,
(darwin_align_is_first_member_of_class
== 1)
|| (integer_zerop (rli->offset)
&& integer_zerop (rli->bitpos)));
#endif
if ((* targetm.ms_bitfield_layout_p) (rli->t)
&& type != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& ! integer_zerop (TYPE_SIZE (type))
&& integer_zerop (DECL_SIZE (field)))
{
if (rli->prev_field
&& DECL_BIT_FIELD_TYPE (rli->prev_field)
&& ! integer_zerop (DECL_SIZE (rli->prev_field)))
{
rli->record_align = MAX (rli->record_align, desired_align);
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
}
else
desired_align = 1;
}
else
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
&& ! (* targetm.ms_bitfield_layout_p) (rli->t)
&& DECL_BIT_FIELD_TYPE (field)
&& ! integer_zerop (TYPE_SIZE (type)))
{
if (! integer_zerop (DECL_SIZE (field)))
rli->record_align = MAX (rli->record_align, desired_align);
else if (! DECL_PACKED (field))
desired_align = TYPE_ALIGN (type);
if (DECL_NAME (field) != 0)
{
unsigned int type_align = TYPE_ALIGN (type);
if (maximum_field_alignment != 0)
type_align = MIN (type_align, (unsigned) maximum_field_alignment);
else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
#ifdef PEG_ALIGN_FOR_MAC68K
else if (TARGET_ALIGN_MAC68K)
type_align = PEG_ALIGN_FOR_MAC68K (type_align);
#endif
rli->record_align = MAX (rli->record_align, type_align);
rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
if (warn_packed)
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
}
}
else
#endif
{
rli->record_align = MAX (rli->record_align, desired_align);
rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
}
if (warn_packed && DECL_PACKED (field))
{
if (known_align > TYPE_ALIGN (type))
{
if (TYPE_ALIGN (type) > desired_align)
{
if (STRICT_ALIGNMENT)
warning_with_decl (field, "packed attribute causes inefficient alignment for `%s'");
else
warning_with_decl (field, "packed attribute is unnecessary for `%s'");
}
}
else
rli->packed_maybe_necessary = 1;
}
if (known_align < desired_align)
{
if (warn_padded)
warning_with_decl (field, "padding struct to align `%s'");
if (desired_align < rli->offset_align)
rli->bitpos = round_up (rli->bitpos, desired_align);
else
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
convert (sizetype,
size_binop (CEIL_DIV_EXPR, rli->bitpos,
bitsize_unit_node)));
rli->bitpos = bitsize_zero_node;
rli->offset = round_up (rli->offset, desired_align / BITS_PER_UNIT);
}
if (! TREE_CONSTANT (rli->offset))
rli->offset_align = desired_align;
}
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS
&& ! (* targetm.ms_bitfield_layout_p) (rli->t)
&& TREE_CODE (field) == FIELD_DECL
&& type != error_mark_node
&& DECL_BIT_FIELD (field)
&& ! DECL_PACKED (field)
&& maximum_field_alignment == 0
#ifdef PEG_ALIGN_FOR_MAC68K
&& ! TARGET_ALIGN_MAC68K
#endif
&& ! integer_zerop (DECL_SIZE (field))
&& host_integerp (DECL_SIZE (field), 1)
&& host_integerp (rli->offset, 1)
&& host_integerp (TYPE_SIZE (type), 1))
{
unsigned int type_align = TYPE_ALIGN (type);
tree dsize = DECL_SIZE (field);
HOST_WIDE_INT field_size = tree_low_cst (dsize, 1);
HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
if ((((offset * BITS_PER_UNIT + bit_offset + field_size +
type_align - 1)
/ type_align)
- (offset * BITS_PER_UNIT + bit_offset) / type_align)
> tree_low_cst (TYPE_SIZE (type), 1) / type_align)
rli->bitpos = round_up (rli->bitpos, type_align);
}
#endif
#ifdef BITFIELD_NBYTES_LIMITED
if (BITFIELD_NBYTES_LIMITED
&& ! (* targetm.ms_bitfield_layout_p) (rli->t)
&& TREE_CODE (field) == FIELD_DECL
&& type != error_mark_node
&& DECL_BIT_FIELD_TYPE (field)
&& ! DECL_PACKED (field)
&& ! integer_zerop (DECL_SIZE (field))
&& host_integerp (DECL_SIZE (field), 1)
&& host_integerp (rli->offset, 1)
&& host_integerp (TYPE_SIZE (type), 1))
{
unsigned int type_align = TYPE_ALIGN (type);
tree dsize = DECL_SIZE (field);
HOST_WIDE_INT field_size = tree_low_cst (dsize, 1);
HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
if (maximum_field_alignment != 0)
type_align = MIN (type_align, (unsigned) maximum_field_alignment);
else if (DECL_PACKED (field))
type_align = MIN (type_align, BITS_PER_UNIT);
#ifdef PEG_ALIGN_FOR_MAC68K
else if (TARGET_ALIGN_MAC68K)
type_align = PEG_ALIGN_FOR_MAC68K (type_align);
#endif
if ((offset * BITS_PER_UNIT + bit_offset) / type_align
!= ((offset * BITS_PER_UNIT + bit_offset + field_size - 1)
/ type_align))
rli->bitpos = round_up (rli->bitpos, type_align);
}
#endif
if ((* targetm.ms_bitfield_layout_p) (rli->t)
&& TREE_CODE (field) == FIELD_DECL
&& type != error_mark_node
&& ! DECL_PACKED (field)
&& rli->prev_field
&& DECL_SIZE (field)
&& host_integerp (DECL_SIZE (field), 1)
&& DECL_SIZE (rli->prev_field)
&& host_integerp (DECL_SIZE (rli->prev_field), 1)
&& host_integerp (rli->offset, 1)
&& host_integerp (TYPE_SIZE (type), 1)
&& host_integerp (TYPE_SIZE (TREE_TYPE (rli->prev_field)), 1)
&& ((DECL_BIT_FIELD_TYPE (rli->prev_field)
&& ! integer_zerop (DECL_SIZE (rli->prev_field)))
|| (DECL_BIT_FIELD_TYPE (field)
&& ! integer_zerop (DECL_SIZE (field))))
&& (! simple_cst_equal (TYPE_SIZE (type),
TYPE_SIZE (TREE_TYPE (rli->prev_field)))
|| (DECL_BIT_FIELD_TYPE (rli->prev_field)
&& integer_zerop (DECL_SIZE (rli->prev_field)))))
{
unsigned int type_align = TYPE_ALIGN (type);
if (rli->prev_field
&& DECL_BIT_FIELD_TYPE (rli->prev_field)
&& ! integer_zerop (DECL_SIZE (rli->prev_field)))
type_align = MAX (type_align,
TYPE_ALIGN (TREE_TYPE (rli->prev_field)));
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
rli->bitpos = round_up (rli->bitpos, type_align);
}
normalize_rli (rli);
DECL_FIELD_OFFSET (field) = rli->offset;
DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
TYPE_USER_ALIGN (rli->t) |= user_align;
if (! integer_zerop (DECL_FIELD_BIT_OFFSET (field)))
actual_align = (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1));
else if (integer_zerop (DECL_FIELD_OFFSET (field)))
actual_align = BIGGEST_ALIGNMENT;
else if (host_integerp (DECL_FIELD_OFFSET (field), 1))
actual_align = (BITS_PER_UNIT
* (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
& - tree_low_cst (DECL_FIELD_OFFSET (field), 1)));
else
actual_align = DECL_OFFSET_ALIGN (field);
if (known_align != actual_align)
layout_decl (field, actual_align);
rli->prev_field = field;
if (DECL_SIZE (field) == 0)
;
else if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST
|| TREE_CONSTANT_OVERFLOW (DECL_SIZE_UNIT (field)))
{
rli->offset
= size_binop (PLUS_EXPR, rli->offset,
convert (sizetype,
size_binop (CEIL_DIV_EXPR, rli->bitpos,
bitsize_unit_node)));
rli->offset
= size_binop (PLUS_EXPR, rli->offset, DECL_SIZE_UNIT (field));
rli->bitpos = bitsize_zero_node;
rli->offset_align = MIN (rli->offset_align, DECL_ALIGN (field));
}
else
{
rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos, DECL_SIZE (field));
normalize_rli (rli);
}
}
static void
finalize_record_size (rli)
record_layout_info rli;
{
tree unpadded_size, unpadded_size_unit;
rli->offset_align = BITS_PER_UNIT;
normalize_rli (rli);
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t),
rli->record_align);
#else
TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
#endif
unpadded_size = rli_size_so_far (rli);
unpadded_size_unit = rli_size_unit_so_far (rli);
if (! integer_zerop (rli->bitpos))
unpadded_size_unit
= size_binop (PLUS_EXPR, unpadded_size_unit, size_one_node);
if (TYPE_BINFO (rli->t) && TREE_VEC_LENGTH (TYPE_BINFO (rli->t)) > 6)
{
TYPE_BINFO_SIZE (rli->t) = unpadded_size;
TYPE_BINFO_SIZE_UNIT (rli->t) = unpadded_size_unit;
}
#ifdef ROUND_TYPE_SIZE
TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, unpadded_size,
TYPE_ALIGN (rli->t));
TYPE_SIZE_UNIT (rli->t)
= ROUND_TYPE_SIZE_UNIT (rli->t, unpadded_size_unit,
TYPE_ALIGN (rli->t) / BITS_PER_UNIT);
#else
TYPE_SIZE (rli->t) = round_up (unpadded_size, TYPE_ALIGN (rli->t));
TYPE_SIZE_UNIT (rli->t) = round_up (unpadded_size_unit,
TYPE_ALIGN (rli->t) / BITS_PER_UNIT);
#endif
if (warn_padded && TREE_CONSTANT (unpadded_size)
&& simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
warning ("padding struct size to alignment boundary");
if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
&& TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary
&& TREE_CONSTANT (unpadded_size))
{
tree unpacked_size;
#ifdef ROUND_TYPE_ALIGN
rli->unpacked_align
= ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t), rli->unpacked_align);
#else
rli->unpacked_align = MAX (TYPE_ALIGN (rli->t), rli->unpacked_align);
#endif
#ifdef ROUND_TYPE_SIZE
unpacked_size = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t),
rli->unpacked_align);
#else
unpacked_size = round_up (TYPE_SIZE (rli->t), rli->unpacked_align);
#endif
if (simple_cst_equal (unpacked_size, TYPE_SIZE (rli->t)))
{
TYPE_PACKED (rli->t) = 0;
if (TYPE_NAME (rli->t))
{
const char *name;
if (TREE_CODE (TYPE_NAME (rli->t)) == IDENTIFIER_NODE)
name = IDENTIFIER_POINTER (TYPE_NAME (rli->t));
else
name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (rli->t)));
if (STRICT_ALIGNMENT)
warning ("packed attribute causes inefficient alignment for `%s'", name);
else
warning ("packed attribute is unnecessary for `%s'", name);
}
else
{
if (STRICT_ALIGNMENT)
warning ("packed attribute causes inefficient alignment");
else
warning ("packed attribute is unnecessary");
}
}
}
}
void
compute_record_mode (type)
tree type;
{
tree field;
enum machine_mode mode = VOIDmode;
TYPE_MODE (type) = BLKmode;
if (! host_integerp (TYPE_SIZE (type), 1))
return;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
unsigned HOST_WIDE_INT bitpos;
if (TREE_CODE (field) != FIELD_DECL)
continue;
if (TREE_CODE (TREE_TYPE (field)) == ERROR_MARK
|| (TYPE_MODE (TREE_TYPE (field)) == BLKmode
&& ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
|| ! host_integerp (bit_position (field), 1)
|| DECL_SIZE (field) == 0
|| ! host_integerp (DECL_SIZE (field), 1))
return;
bitpos = int_bit_position (field);
if (bitpos / BITS_PER_WORD
!= ((tree_low_cst (DECL_SIZE (field), 1) + bitpos - 1)
/ BITS_PER_WORD)
&& tree_low_cst (DECL_SIZE (field), 1) % BITS_PER_WORD != 0)
return;
if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
mode = DECL_MODE (field);
#ifdef MEMBER_TYPE_FORCES_BLK
if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN)
&& MEMBER_TYPE_FORCES_BLK (field))
return;
#endif
}
if (TREE_CODE (type) == RECORD_TYPE && mode != VOIDmode)
TYPE_MODE (type) = mode;
else if (mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1) == DImode
&& flag_pic)
;
else
TYPE_MODE (type) = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
if (TYPE_MODE (type) != BLKmode
&& STRICT_ALIGNMENT
&& ! (TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
|| TYPE_ALIGN (type) >= GET_MODE_ALIGNMENT (TYPE_MODE (type))))
{
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
}
static void
finalize_type_size (type)
tree type;
{
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));
TYPE_USER_ALIGN (type) = 0;
}
#ifdef ROUND_TYPE_ALIGN
TYPE_ALIGN (type)
= ROUND_TYPE_ALIGN (type, TYPE_ALIGN (type), BITS_PER_UNIT);
#endif
if (TYPE_SIZE_UNIT (type) == 0 && TYPE_SIZE (type) != 0)
TYPE_SIZE_UNIT (type)
= convert (sizetype,
size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
bitsize_unit_node));
if (TYPE_SIZE (type) != 0)
{
#ifdef ROUND_TYPE_SIZE
TYPE_SIZE (type)
= ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
TYPE_SIZE_UNIT (type)
= ROUND_TYPE_SIZE_UNIT (type, TYPE_SIZE_UNIT (type),
TYPE_ALIGN (type) / BITS_PER_UNIT);
#else
TYPE_SIZE (type) = round_up (TYPE_SIZE (type), TYPE_ALIGN (type));
TYPE_SIZE_UNIT (type)
= round_up (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type) / BITS_PER_UNIT);
#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
&& 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);
unsigned int align = TYPE_ALIGN (type);
unsigned int user_align = TYPE_USER_ALIGN (type);
enum machine_mode mode = TYPE_MODE (type);
for (variant = TYPE_MAIN_VARIANT (type);
variant != 0;
variant = TYPE_NEXT_VARIANT (variant))
{
TYPE_SIZE (variant) = size;
TYPE_SIZE_UNIT (variant) = size_unit;
TYPE_ALIGN (variant) = align;
TYPE_USER_ALIGN (variant) = user_align;
TYPE_MODE (variant) = mode;
}
}
}
void
finish_record_layout (rli)
record_layout_info rli;
{
finalize_record_size (rli);
compute_record_mode (rli->t);
finalize_type_size (rli->t);
while (rli->pending_statics)
{
layout_decl (TREE_VALUE (rli->pending_statics), 0);
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
free (rli);
}
void
layout_type (type)
tree type;
{
if (type == 0)
abort ();
if (TYPE_SIZE (type))
return;
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)));
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)));
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)));
TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
break;
case VECTOR_TYPE:
{
tree subtype;
subtype = TREE_TYPE (type);
TREE_UNSIGNED (type) = TREE_UNSIGNED (subtype);
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 VOID_TYPE:
TYPE_ALIGN (type) = 1;
TYPE_USER_ALIGN (type) = 0;
TYPE_MODE (type) = VOIDmode;
break;
case OFFSET_TYPE:
TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
TYPE_MODE (type) = mode_for_size (POINTER_SIZE, MODE_INT, 0);
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);
TYPE_SIZE_UNIT (type) = size_int ((2 * POINTER_SIZE) / BITS_PER_UNIT);
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
{
int nbits = ((TREE_CODE (type) == REFERENCE_TYPE
&& reference_types_internal)
? GET_MODE_BITSIZE (Pmode) : POINTER_SIZE);
TYPE_MODE (type) = nbits == POINTER_SIZE ? ptr_mode : Pmode;
TYPE_SIZE (type) = bitsize_int (nbits);
TYPE_SIZE_UNIT (type) = size_int (nbits / BITS_PER_UNIT);
TREE_UNSIGNED (type) = 1;
TYPE_PRECISION (type) = nbits;
}
break;
case ARRAY_TYPE:
{
tree index = TYPE_DOMAIN (type);
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;
length = size_binop (PLUS_EXPR, size_one_node,
convert (sizetype,
fold (build (MINUS_EXPR,
TREE_TYPE (lb),
ub, lb))));
element_size = TYPE_SIZE (element);
if (TYPE_PACKED (type) && INTEGRAL_TYPE_P (element)
&& (integer_zerop (TYPE_MAX_VALUE (element))
|| integer_onep (TYPE_MAX_VALUE (element)))
&& host_integerp (TYPE_MIN_VALUE (element), 1))
{
HOST_WIDE_INT maxvalue
= tree_low_cst (TYPE_MAX_VALUE (element), 1);
HOST_WIDE_INT minvalue
= tree_low_cst (TYPE_MIN_VALUE (element), 1);
if (maxvalue - minvalue == 1
&& (maxvalue == 1 || maxvalue == 0))
element_size = integer_one_node;
}
TYPE_SIZE (type) = size_binop (MULT_EXPR, element_size,
convert (bitsizetype, length));
if (TYPE_SIZE_UNIT (element) != 0 && ! integer_onep (element_size))
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
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
#ifdef ROUND_TYPE_SIZE
if (TYPE_SIZE (type) != 0)
{
tree 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
#ifdef MEMBER_TYPE_FORCES_BLK
&& ! MEMBER_TYPE_FORCES_BLK (type)
#endif
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
|| TYPE_NO_FORCE_BLK (TREE_TYPE (type))))
{
if (simple_cst_equal (TYPE_SIZE (type),
TYPE_SIZE (TREE_TYPE (type))))
TYPE_MODE (type) = TYPE_MODE (TREE_TYPE (type));
else
TYPE_MODE (type)
= mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
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_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
}
break;
}
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
{
tree field;
record_layout_info rli;
rli = start_record_layout (type);
if (TREE_CODE (type) == QUAL_UNION_TYPE)
TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
place_field (rli, field);
if (TREE_CODE (type) == QUAL_UNION_TYPE)
TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
if (lang_adjust_rli)
(*lang_adjust_rli) (rli);
finish_record_layout (rli);
}
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
unsigned 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 > (int) alignment)
TYPE_MODE (type) = BLKmode;
else
TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
TYPE_SIZE (type) = bitsize_int (rounded_size);
TYPE_SIZE_UNIT (type) = size_int (rounded_size / BITS_PER_UNIT);
TYPE_ALIGN (type) = alignment;
TYPE_USER_ALIGN (type) = 0;
TYPE_PRECISION (type) = size_in_bits;
}
break;
case FILE_TYPE:
TYPE_ALIGN (type) = BIGGEST_ALIGNMENT;
TYPE_USER_ALIGN (type) = 0;
TYPE_MODE (type) = BLKmode;
break;
default:
abort ();
}
if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& TREE_CODE (type) != QUAL_UNION_TYPE)
finalize_type_size (type);
if (! sizetype_set)
early_type_list = tree_cons (NULL_TREE, type, early_type_list);
if (AGGREGATE_TYPE_P (type) && TYPE_ALIAS_SET_KNOWN_P (type))
TYPE_ALIAS_SET (type) = 0;
}
tree
make_signed_type (precision)
int precision;
{
tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
fixup_signed_type (type);
return type;
}
tree
make_unsigned_type (precision)
int precision;
{
tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
fixup_unsigned_type (type);
return type;
}
void
initialize_sizetypes ()
{
tree t = make_node (INTEGER_TYPE);
integer_type_node = t;
TYPE_MODE (t) = SImode;
TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode);
TYPE_USER_ALIGN (t) = 0;
TYPE_SIZE (t) = build_int_2 (GET_MODE_BITSIZE (SImode), 0);
TYPE_SIZE_UNIT (t) = build_int_2 (GET_MODE_SIZE (SImode), 0);
TREE_UNSIGNED (t) = 1;
TYPE_PRECISION (t) = GET_MODE_BITSIZE (SImode);
TYPE_MIN_VALUE (t) = build_int_2 (0, 0);
TYPE_IS_SIZETYPE (t) = 1;
TYPE_MAX_VALUE (t) = build_int_2 (1000, 0);
sizetype = t;
bitsizetype = copy_node (t);
integer_type_node = 0;
}
void
set_sizetype (type)
tree type;
{
int oprecision = TYPE_PRECISION (type);
int precision = MIN (oprecision + BITS_PER_UNIT_LOG + 1,
2 * HOST_BITS_PER_WIDE_INT);
unsigned int i;
tree t;
if (sizetype_set)
abort ();
sizetype = copy_node (type);
TYPE_DOMAIN (sizetype) = type;
TYPE_IS_SIZETYPE (sizetype) = 1;
bitsizetype = make_node (INTEGER_TYPE);
TYPE_NAME (bitsizetype) = TYPE_NAME (type);
TYPE_PRECISION (bitsizetype) = precision;
TYPE_IS_SIZETYPE (bitsizetype) = 1;
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 = copy_node (make_signed_type (oprecision));
sbitsizetype = copy_node (make_signed_type (precision));
}
else
{
ssizetype = sizetype;
sbitsizetype = bitsizetype;
usizetype = copy_node (make_unsigned_type (oprecision));
ubitsizetype = copy_node (make_unsigned_type (precision));
}
TYPE_NAME (bitsizetype) = get_identifier ("bit_size_type");
for (i = 0; i < ARRAY_SIZE (sizetype_tab); i++)
{
TYPE_IS_SIZETYPE (sizetype_tab[i]) = 1;
TYPE_MAIN_VARIANT (sizetype_tab[i]) = sizetype_tab[i];
TYPE_NEXT_VARIANT (sizetype_tab[i]) = 0;
TYPE_POINTER_TO (sizetype_tab[i]) = 0;
TYPE_REFERENCE_TO (sizetype_tab[i]) = 0;
}
ggc_add_tree_root ((tree *) &sizetype_tab,
sizeof sizetype_tab / sizeof (tree));
for (t = early_type_list; t != 0; t = TREE_CHAIN (t))
{
if (TREE_CODE (TREE_VALUE (t)) != INTEGER_TYPE)
abort ();
TREE_TYPE (TYPE_SIZE (TREE_VALUE (t))) = bitsizetype;
TREE_TYPE (TYPE_SIZE_UNIT (TREE_VALUE (t))) = sizetype;
}
early_type_list = 0;
sizetype_set = 1;
}
void
fixup_signed_type (type)
tree type;
{
int precision = TYPE_PRECISION (type);
if (precision > HOST_BITS_PER_WIDE_INT * 2)
precision = HOST_BITS_PER_WIDE_INT * 2;
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;
{
int precision = TYPE_PRECISION (type);
if (precision > HOST_BITS_PER_WIDE_INT * 2)
precision = HOST_BITS_PER_WIDE_INT * 2;
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;
unsigned int align;
enum machine_mode largest_mode;
int volatilep;
{
enum machine_mode mode;
unsigned 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 == VOIDmode
|| 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
init_stor_layout_once ()
{
ggc_add_tree_root (&pending_sizes, 1);
}