/* C-compiler utilities for types and variables storage layout
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#include "config.h"
#include "expr.h"
#include "toplev.h"
#include "ggc.h"
+#include "target.h"
+#include "langhooks.h"
/* Set to one when set_sizetype has been called. */
static int sizetype_set;
\f
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
-static tree pending_sizes;
+static GTY(()) tree pending_sizes;
/* Nonzero means cannot safely call expand_expr now,
so put variable sizes onto `pending_sizes' instead. */
put_pending_size (expr)
tree expr;
{
+ /* Strip any simple arithmetic from EXPR to see if it has an underlying
+ SAVE_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);
}
{
/* If the language-processor is to take responsibility for variable-sized
items (e.g., languages which have elaboration procedures like Ada),
- just return SIZE unchanged. Likewise for self-referential sizes. */
+ just return SIZE unchanged. Likewise for self-referential sizes and
+ constant sizes. */
if (TREE_CONSTANT (size)
- || global_bindings_p () < 0 || contains_placeholder_p (size))
+ || (*lang_hooks.decls.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 ((*lang_hooks.decls.global_bindings_p) ())
{
if (TREE_CONSTANT (size))
error ("type size can't be explicitly evaluated");
}
if (immediate_size_expand)
- /* NULL_RTX is not defined; neither is the rtx type.
+ /* NULL_RTX is not defined; neither is the rtx type.
Also, we would like to pass const0_rtx here, but don't have it. */
expand_expr (size, expand_expr (integer_zero_node, NULL_RTX, VOIDmode, 0),
VOIDmode, 0);
enum mode_class class;
int limit;
{
- register enum machine_mode mode;
+ enum machine_mode mode;
if (limit && size > MAX_FIXED_MODE_SIZE)
return BLKmode;
unsigned int size;
enum mode_class class;
{
- register enum machine_mode mode;
+ enum machine_mode mode;
/* Get the first mode which has at least this size, in the
specified class. */
case MODE_RANDOM:
if (mode == BLKmode)
- break;
+ break;
/* ... fall through ... */
tree decl;
unsigned int known_align;
{
- register tree type = TREE_TYPE (decl);
- register enum tree_code code = TREE_CODE (decl);
+ tree type = TREE_TYPE (decl);
+ enum tree_code code = TREE_CODE (decl);
if (code == CONST_DECL)
return;
&& (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;
}
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))
+
+ /* If the field is of variable size, we can't misalign it since we
+ have no way to make a temporary to align the result. But this
+ isn't an issue if the decl is not addressable. Likewise if it
+ is of unknown size. */
+ 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;
}
}
- /* See if we can use an ordinary integer mode for a bit-field.
+ /* See if we can use an ordinary integer mode for a bit-field.
Conditions are: a fixed size that is correct for another mode
and occupying a complete byte or bytes on proper boundary. */
if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
{
- register enum machine_mode xmode
+ enum machine_mode xmode
= mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
/* Begin laying out type T, which may be a RECORD_TYPE, UNION_TYPE, or
QUAL_UNION_TYPE. Return a pointer to a struct record_layout_info which
is to be passed to all other layout functions for this record. It is the
- responsibility of the caller to call `free' for the storage returned.
+ responsibility of the caller to call `free' for the storage returned.
Note that garbage collection is not permitted until we finish laying
out the record. */
start_record_layout (t)
tree t;
{
- record_layout_info rli
+ record_layout_info rli
= (record_layout_info) xmalloc (sizeof (struct record_layout_info_s));
rli->t = t;
rli->offset = size_zero_node;
rli->bitpos = bitsize_zero_node;
+ rli->prev_field = 0;
rli->pending_statics = 0;
rli->packed_maybe_necessary = 0;
= 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));
}
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);
MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
+#ifdef ADJUST_FIELD_ALIGN
+ desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+#endif
+
+ TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
+
/* Union must be at least as aligned as any field requires. */
rli->record_align = MAX (rli->record_align, desired_align);
rli->unpadded_align = MAX (rli->unpadded_align, desired_align);
entire union to have `int' alignment. */
if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
{
- rli->record_align = MAX (rli->record_align,
+ rli->record_align = MAX (rli->record_align,
TYPE_ALIGN (TREE_TYPE (field)));
rli->unpadded_align = MAX (rli->unpadded_align,
TYPE_ALIGN (TREE_TYPE (field)));
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,
+ rli->offset = fold (build (COND_EXPR, sizetype,
DECL_QUALIFIER (field),
DECL_SIZE_UNIT (field), rli->offset));
}
unsigned int user_align;
/* The type of this field. */
tree type = TREE_TYPE (field);
-
+
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
return;
/* Record must have at least as much alignment as any field.
Otherwise, the alignment of the field within the record is
meaningless. */
+ 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)))
{
variable-sized fields, we need not worry about compatibility. */
#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)
#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)
}
#endif
+ /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. */
+ 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)))
+ /* If the previous field was a zero-sized bit-field, either
+ it was ignored, in which case we must ensure the proper
+ alignment of this field here, or it already forced the
+ alignment of this field, in which case forcing the
+ alignment again is harmless. So, do it in both cases. */
+ || (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)
+ /* If the previous bit-field is zero-sized, we've already
+ accounted for its alignment needs (or ignored it, if
+ appropriate) while placing it. */
+ && ! 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);
+ }
+
/* Offset so far becomes the position of this field after normalizing. */
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 this field ended up more aligned than we thought it would be (we
approximate this by seeing if its position changed), lay out the field
again; perhaps we can use an integral mode for it now. */
if (known_align != actual_align)
layout_decl (field, actual_align);
+ rli->prev_field = field;
+
/* Now add size of this field to the size of the record. If the size is
not constant, treat the field as being a multiple of bytes and just
adjust the offset, resetting the bit position. Otherwise, apportion the
#else
TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
#endif
- TYPE_USER_ALIGN (rli->t) = 0;
/* Compute the size so far. Be sure to allow for extra bits in the
size in bytes. We have guaranteed above that it will be no more
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))
|| (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);
-
+
/* Must be BLKmode if any field crosses a word boundary,
since extract_bit_field can't handle that in registers. */
if (bitpos / BITS_PER_WORD
#ifdef MEMBER_TYPE_FORCES_BLK
/* With some targets, eg. c4x, it is sub-optimal
to access an aligned BLKmode structure as a scalar. */
- if (mode == VOIDmode && MEMBER_TYPE_FORCES_BLK (field))
+
+ /* On ia64-*-hpux we need to ensure that we don't change the
+ mode of a structure containing a single field or else we
+ will pass it incorrectly. Since a structure with a single
+ field causes mode to get set above we can't allow the
+ check for mode == VOIDmode in this case. Perhaps
+ MEMBER_TYPE_FORCES_BLK should be extended to include mode
+ as an argument and the check could be put in there for c4x. */
+
+ if ((mode == VOIDmode || FUNCTION_ARG_REG_LITTLE_ENDIAN)
+ && MEMBER_TYPE_FORCES_BLK (field))
return;
#endif /* MEMBER_TYPE_FORCES_BLK */
}
case ARRAY_TYPE:
{
- register tree index = TYPE_DOMAIN (type);
- register tree element = TREE_TYPE (type);
+ tree index = TYPE_DOMAIN (type);
+ tree element = TREE_TYPE (type);
build_pointer_type (element);
#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)
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
|| TYPE_NO_FORCE_BLK (TREE_TYPE (type))))
{
- TYPE_MODE (type)
- = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
+ /* One-element arrays get the component type's mode. */
+ 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
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();
+ abort ();
else
{
#ifndef SET_WORD_SIZE
/* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For
records and unions, finish_record_layout already called this
function. */
- if (TREE_CODE (type) != RECORD_TYPE
+ if (TREE_CODE (type) != RECORD_TYPE
&& TREE_CODE (type) != UNION_TYPE
&& TREE_CODE (type) != QUAL_UNION_TYPE)
finalize_type_size (type);
make_signed_type (precision)
int precision;
{
- register tree type = make_node (INTEGER_TYPE);
+ tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
make_unsigned_type (precision)
int precision;
{
- register tree type = make_node (INTEGER_TYPE);
+ tree type = make_node (INTEGER_TYPE);
TYPE_PRECISION (type) = precision;
TYPE_REFERENCE_TO (sizetype_tab[i]) = 0;
}
- ggc_add_tree_root ((tree *) &sizetype_tab,
- sizeof sizetype_tab / sizeof (tree));
-
/* Go down each of the types we already made and set the proper type
for the sizes in them. */
for (t = early_type_list; t != 0; t = TREE_CHAIN (t))
fixup_signed_type (type)
tree type;
{
- register int precision = TYPE_PRECISION (type);
+ int precision = TYPE_PRECISION (type);
+
+ /* We can not represent properly constants greater then
+ 2 * HOST_BITS_PER_WIDE_INT, still we need the types
+ as they are used by i386 vector extensions and friends. */
+ 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
fixup_unsigned_type (type)
tree type;
{
- register int precision = TYPE_PRECISION (type);
+ int precision = TYPE_PRECISION (type);
+
+ /* We can not represent properly constants greater then
+ 2 * HOST_BITS_PER_WIDE_INT, still we need the types
+ as they are used by i386 vector extensions and friends. */
+ 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)
return mode;
}
-/* Return the alignment of MODE. This will be bounded by 1 and
- BIGGEST_ALIGNMENT. */
-
-unsigned int
-get_mode_alignment (mode)
- enum machine_mode mode;
-{
- unsigned int alignment = GET_MODE_UNIT_SIZE (mode);
-
- /* Extract the LSB of the size. */
- alignment = alignment & -alignment;
- alignment *= BITS_PER_UNIT;
-
- alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
- return alignment;
-}
-
-/* This function is run once to initialize stor-layout.c. */
-
-void
-init_stor_layout_once ()
-{
- ggc_add_tree_root (&pending_sizes, 1);
-}
+#include "gt-stor-layout.h"