summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/stor-layout.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
committerkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
commitb2a8872fbe1ec1c49094559ac7b78e6ea4ab7180 (patch)
treef6b0610f4a17fd26aa234354f050080f789861a4 /contrib/gcc/stor-layout.c
parent52e69d78eee5612ac195e0701a5cebe40d1ab0e1 (diff)
downloadFreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.zip
FreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.tar.gz
Gcc 3.3.1-pre as of 2003-07-11.
Diffstat (limited to 'contrib/gcc/stor-layout.c')
-rw-r--r--contrib/gcc/stor-layout.c540
1 files changed, 332 insertions, 208 deletions
diff --git a/contrib/gcc/stor-layout.c b/contrib/gcc/stor-layout.c
index c330fb6..4fb2908 100644
--- a/contrib/gcc/stor-layout.c
+++ b/contrib/gcc/stor-layout.c
@@ -1,6 +1,6 @@
/* C-compiler utilities for types and variables storage layout
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#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;
@@ -47,7 +48,7 @@ tree sizetype_tab[(int) TYPE_KIND_LAST];
The value is measured in bits. */
unsigned int maximum_field_alignment;
-/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.
+/* If nonzero, the alignment of a bitstring or (power-)set value, in bits.
May be overridden by front-ends. */
unsigned int set_alignment = 0;
@@ -59,11 +60,14 @@ 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));
+static unsigned int update_alignment_for_field
+ PARAMS ((record_layout_info, tree,
+ unsigned int));
extern void debug_rli PARAMS ((record_layout_info));
/* 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. */
@@ -95,7 +99,7 @@ get_pending_sizes ()
return chain;
}
-/* Return non-zero if EXPR is present on the pending sizes list. */
+/* Return nonzero if EXPR is present on the pending sizes list. */
int
is_pending_size (expr)
@@ -151,7 +155,8 @@ variable_size (size)
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);
@@ -167,7 +172,7 @@ variable_size (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");
@@ -178,7 +183,7 @@ variable_size (size)
}
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);
@@ -281,7 +286,7 @@ int_mode_for_mode (mode)
case MODE_RANDOM:
if (mode == BLKmode)
- break;
+ break;
/* ... fall through ... */
@@ -293,6 +298,29 @@ int_mode_for_mode (mode)
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;
+
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+ alignment = GET_MODE_UNIT_SIZE (mode);
+ else
+ alignment = GET_MODE_SIZE (mode);
+
+ /* Extract the LSB of the size. */
+ alignment = alignment & -alignment;
+ alignment *= BITS_PER_UNIT;
+
+ alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
+ return alignment;
+}
+
/* Return the value of VALUE, rounded up to a multiple of DIVISOR.
This can only be applied to objects of a sizetype. */
@@ -338,6 +366,7 @@ layout_decl (decl, known_align)
{
tree type = TREE_TYPE (decl);
enum tree_code code = TREE_CODE (decl);
+ rtx rtl = NULL_RTX;
if (code == CONST_DECL)
return;
@@ -345,6 +374,8 @@ layout_decl (decl, known_align)
&& code != TYPE_DECL && code != FIELD_DECL)
abort ();
+ rtl = DECL_RTL_IF_SET (decl);
+
if (type == error_mark_node)
type = void_type_node;
@@ -379,7 +410,7 @@ layout_decl (decl, known_align)
&& (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;
}
@@ -405,7 +436,7 @@ layout_decl (decl, known_align)
}
}
- /* 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)
@@ -459,6 +490,15 @@ layout_decl (decl, known_align)
larger_than_size);
}
}
+
+ /* If the RTL was already set, update its mode and mem attributes. */
+ if (rtl)
+ {
+ PUT_MODE (rtl, DECL_MODE (decl));
+ SET_DECL_RTL (decl, 0);
+ set_mem_attributes (rtl, decl, 1);
+ SET_DECL_RTL (decl, rtl);
+ }
}
/* Hook for a front-end function that can modify the record layout as needed
@@ -476,7 +516,7 @@ set_lang_adjust_rli (f)
/* 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. */
@@ -484,7 +524,7 @@ record_layout_info
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;
@@ -585,7 +625,7 @@ normalize_offset (poffset, pbitpos, off_align)
= 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));
}
@@ -642,66 +682,154 @@ rli_size_so_far (rli)
return bit_from_pos (rli->offset, rli->bitpos);
}
-/* Called from place_field to handle unions. */
+/* FIELD is about to be added to RLI->T. The alignment (in bits) of
+ the next available location is given by KNOWN_ALIGN. Update the
+ variable alignment fields in RLI, and return the alignment to give
+ the FIELD. */
-static void
-place_union_field (rli, field)
+static unsigned int
+update_alignment_for_field (rli, field, known_align)
record_layout_info rli;
tree field;
+ unsigned int known_align;
{
+ /* The alignment required for FIELD. */
unsigned int desired_align;
+ /* The type of this field. */
+ tree type = TREE_TYPE (field);
+ /* True if the field was explicitly aligned by the user. */
+ bool user_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);
-
+ /* Lay out the field so we know what alignment it needs. For a
+ packed field, use the alignment as specified, disregarding what
+ the type would want. */
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
- /* Some targets (i.e. i386) limit union field alignment
+ /* Some targets (i.e. i386, VMS) limit struct field alignment
to a lower boundary than alignment of variables unless
it was overridden by attribute aligned. */
- if (! DECL_USER_ALIGN (field))
- desired_align =
- MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
+#ifdef BIGGEST_FIELD_ALIGNMENT
+ if (!user_align)
+ desired_align
+ = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
#endif
#ifdef ADJUST_FIELD_ALIGN
- if (! DECL_USER_ALIGN (field))
+ if (!user_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);
-
+ /* 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)))
+ {
+ /* Here, the alignment of the underlying type of a bitfield can
+ affect the alignment of a record; even a zero-sized field
+ can do this. The alignment should be to the alignment of
+ the type, except that for zero-size bitfields this only
+ applies if there was an immediately prior, nonzero-size
+ bitfield. (That's the way it is, experimentally.) */
+ if (! integer_zerop (DECL_SIZE (field))
+ ? ! DECL_PACKED (field)
+ : (rli->prev_field
+ && DECL_BIT_FIELD_TYPE (rli->prev_field)
+ && ! integer_zerop (DECL_SIZE (rli->prev_field))))
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
+ type_align = MAX (type_align, desired_align);
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
+ rli->record_align = MAX (rli->record_align, type_align);
+ rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+ rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+ }
+ else
+ desired_align = 1;
+ }
+ else
#ifdef PCC_BITFIELD_TYPE_MATTERS
- /* On the m88000, a bit field of declare type `int' forces the
- entire union to have `int' alignment. */
- if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
+ 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)))
{
- unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
+ /* For these machines, a zero-length field does not
+ affect the alignment of the structure as a whole.
+ It does, however, affect the alignment of the next field
+ within the structure. */
+ if (! integer_zerop (DECL_SIZE (field)))
+ rli->record_align = MAX (rli->record_align, desired_align);
+ else if (! DECL_PACKED (field) && !user_align)
+ desired_align = TYPE_ALIGN (type);
+
+ /* A named bit field of declared type `int'
+ forces the entire structure to have `int' alignment. */
+ if (DECL_NAME (field) != 0)
+ {
+ unsigned int type_align = TYPE_ALIGN (type);
#ifdef ADJUST_FIELD_ALIGN
- if (! TYPE_USER_ALIGN (TREE_TYPE (field)))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
+ if (! TYPE_USER_ALIGN (type))
+ type_align = ADJUST_FIELD_ALIGN (field, type_align);
#endif
- rli->record_align = MAX (rli->record_align, type_align);
- rli->unpadded_align = MAX (rli->unpadded_align, type_align);
- TYPE_USER_ALIGN (rli->t) |= TYPE_USER_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);
+
+ 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));
+ user_align |= TYPE_USER_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));
+ }
+
+ TYPE_USER_ALIGN (rli->t) |= user_align;
+
+ DECL_ALIGN (field) = desired_align;
+
+ return desired_align;
+}
+
+/* Called from place_field to handle unions. */
+
+static void
+place_union_field (rli, field)
+ record_layout_info rli;
+ tree field;
+{
+ update_alignment_for_field (rli, field, /*known_align=*/0);
+
+ DECL_FIELD_OFFSET (field) = size_zero_node;
+ DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
+ SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
/* We assume the union's size will be a multiple of a byte so we don't
bother with BITPOS. */
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));
}
@@ -722,10 +850,9 @@ place_field (rli, field)
record as it presently stands. */
unsigned int known_align;
unsigned int actual_align;
- 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;
@@ -766,98 +893,8 @@ place_field (rli, field)
& - tree_low_cst (rli->offset, 1)));
else
known_align = rli->offset_align;
-
- /* Lay out the field so we know what alignment it needs. For a
- packed field, use the alignment as specified, disregarding what
- the type would want. */
- 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);
- }
-
- /* Some targets (i.e. i386, VMS) limit struct field alignment
- to a lower boundary than alignment of variables unless
- it was overridden by attribute aligned. */
-#ifdef BIGGEST_FIELD_ALIGNMENT
- if (! user_align)
- desired_align
- = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
-#endif
-
-#ifdef ADJUST_FIELD_ALIGN
- if (! user_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 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)))
- {
- /* For these machines, a zero-length field does not
- affect the alignment of the structure as a whole.
- It does, however, affect the alignment of the next field
- within the structure. */
- 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);
-
- /* A named bit field of declared type `int'
- forces the entire structure to have `int' alignment. */
- if (DECL_NAME (field) != 0)
- {
- unsigned int type_align = TYPE_ALIGN (type);
-
-#ifdef ADJUST_FIELD_ALIGN
- if (! TYPE_USER_ALIGN (type))
- type_align = ADJUST_FIELD_ALIGN (field, type_align);
-#endif
-
- 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);
-
- 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));
- user_align |= TYPE_USER_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));
- }
+
+ desired_align = update_alignment_for_field (rli, field, known_align);
if (warn_packed && DECL_PACKED (field))
{
@@ -942,7 +979,7 @@ place_field (rli, field)
> tree_low_cst (TYPE_SIZE (type), 1) / type_align)
rli->bitpos = round_up (rli->bitpos, type_align);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
@@ -985,52 +1022,153 @@ place_field (rli, field)
/ type_align))
rli->bitpos = round_up (rli->bitpos, type_align);
- user_align |= TYPE_USER_ALIGN (type);
+ TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
}
#endif
- /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details. */
+ /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details.
+ A subtlety:
+ When a bit field is inserted into a packed record, the whole
+ size of the underlying type is used by one or more same-size
+ adjacent bitfields. (That is, if its long:3, 32 bits is
+ used in the record, and any additional adjacent long bitfields are
+ packed into the same chunk of 32 bits. However, if the size
+ changes, a new field of that size is allocated.) In an unpacked
+ record, this is the same as using alignment, but not eqivalent
+ when packing.
+
+ Note: for compatability, we use the type size, not the type alignment
+ to determine alignment, since that matches the documentation */
+
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)))))
+ && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field))
+ || (rli->prev_field && ! DECL_PACKED (rli->prev_field))))
{
- unsigned int type_align = TYPE_ALIGN (type);
+ /* At this point, either the prior or current are bitfields,
+ (possibly both), and we're dealing with MS packing. */
+ tree prev_saved = rli->prev_field;
- 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)));
+ /* Is the prior field a bitfield? If so, handle "runs" of same
+ type size fields. */
+ if (rli->prev_field /* necessarily a bitfield if it exists. */)
+ {
+ /* If both are bitfields, nonzero, and the same size, this is
+ the middle of a run. Zero declared size fields are special
+ and handled as "end of run". (Note: it's nonzero declared
+ size, but equal type sizes!) (Since we know that both
+ the current and previous fields are bitfields by the
+ time we check it, DECL_SIZE must be present for both.) */
+ if (DECL_BIT_FIELD_TYPE (field)
+ && !integer_zerop (DECL_SIZE (field))
+ && !integer_zerop (DECL_SIZE (rli->prev_field))
+ && simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (rli->prev_field))) )
+ {
+ /* We're in the middle of a run of equal type size fields; make
+ sure we realign if we run out of bits. (Not decl size,
+ type size!) */
+ int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
+ tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+
+ if (rli->remaining_in_alignment < bitsize)
+ {
+ /* out of bits; bump up to next 'word'. */
+ rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
+ rli->bitpos = size_binop (PLUS_EXPR,
+ type_size,
+ DECL_FIELD_BIT_OFFSET(rli->prev_field));
+ rli->prev_field = field;
+ rli->remaining_in_alignment = TREE_INT_CST_LOW (type_size);
+ }
+ rli->remaining_in_alignment -= bitsize;
+ }
+ else
+ {
+ /* End of a run: if leaving a run of bitfields of the same type
+ size, we have to "use up" the rest of the bits of the type
+ size.
+
+ Compute the new position as the sum of the size for the prior
+ type and where we first started working on that type.
+ Note: since the beginning of the field was aligned then
+ of course the end will be too. No round needed. */
+
+ if (!integer_zerop (DECL_SIZE (rli->prev_field)))
+ {
+ tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+ rli->bitpos = size_binop (PLUS_EXPR,
+ type_size,
+ DECL_FIELD_BIT_OFFSET(rli->prev_field));
+ }
+ else
+ {
+ /* We "use up" size zero fields; the code below should behave
+ as if the prior field was not a bitfield. */
+ prev_saved = NULL;
+ }
+
+ /* Cause a new bitfield to be captured, either this time (if
+ currently a bitfield) or next time we see one. */
+ if (!DECL_BIT_FIELD_TYPE(field)
+ || integer_zerop (DECL_SIZE (field)))
+ {
+ rli->prev_field = NULL;
+ }
+ }
+ normalize_rli (rli);
+ }
+
+ /* If we're starting a new run of same size type bitfields
+ (or a run of non-bitfields), set up the "first of the run"
+ fields.
+
+ That is, if the current field is not a bitfield, or if there
+ was a prior bitfield the type sizes differ, or if there wasn't
+ a prior bitfield the size of the current field is nonzero.
+
+ Note: we must be sure to test ONLY the type size if there was
+ a prior bitfield and ONLY for the current field being zero if
+ there wasn't. */
+
+ if (!DECL_BIT_FIELD_TYPE (field)
+ || ( prev_saved != NULL
+ ? !simple_cst_equal (TYPE_SIZE (type),
+ TYPE_SIZE (TREE_TYPE (prev_saved)))
+ : !integer_zerop (DECL_SIZE (field)) ))
+ {
+ unsigned int type_align = 8; /* Never below 8 for compatability */
+
+ /* (When not a bitfield), we could be seeing a flex array (with
+ no DECL_SIZE). Since we won't be using remaining_in_alignment
+ until we see a bitfield (and come by here again) we just skip
+ calculating it. */
+
+ if (DECL_SIZE (field) != NULL)
+ rli->remaining_in_alignment
+ = TREE_INT_CST_LOW (TYPE_SIZE(TREE_TYPE(field)))
+ - TREE_INT_CST_LOW (DECL_SIZE (field));
+
+ /* Now align (conventionally) for the new type. */
+ if (!DECL_PACKED(field))
+ type_align = MAX(TYPE_ALIGN (type), type_align);
+
+ if (prev_saved
+ && DECL_BIT_FIELD_TYPE (prev_saved)
+ /* 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 (prev_saved)))
+ type_align = MAX (type_align,
+ TYPE_ALIGN (TREE_TYPE (prev_saved)));
- if (maximum_field_alignment != 0)
- type_align = MIN (type_align, maximum_field_alignment);
+ if (maximum_field_alignment != 0)
+ type_align = MIN (type_align, maximum_field_alignment);
- rli->bitpos = round_up (rli->bitpos, type_align);
+ rli->bitpos = round_up (rli->bitpos, type_align);
+ /* If we really aligned, don't allow subsequent bitfields
+ to undo that. */
+ rli->prev_field = NULL;
+ }
}
/* Offset so far becomes the position of this field after normalizing. */
@@ -1039,8 +1177,6 @@ place_field (rli, field)
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. */
@@ -1059,7 +1195,9 @@ place_field (rli, field)
if (known_align != actual_align)
layout_decl (field, actual_align);
- rli->prev_field = field;
+ /* Only the MS bitfields use this. */
+ if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
+ 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
@@ -1146,7 +1284,7 @@ finalize_record_size (rli)
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))
@@ -1233,7 +1371,7 @@ compute_record_mode (type)
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
@@ -1253,16 +1391,7 @@ compute_record_mode (type)
/* With some targets, eg. c4x, it is sub-optimal
to access an aligned BLKmode structure as a scalar. */
- /* 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))
+ if (MEMBER_TYPE_FORCES_BLK (field, mode))
return;
#endif /* MEMBER_TYPE_FORCES_BLK */
}
@@ -1377,11 +1506,14 @@ finalize_type_size (type)
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
- for RLI. */
+ for RLI, unless FREE_P is false. Passing a value other than false
+ for FREE_P is bad practice; this option only exists to support the
+ G++ 3.2 ABI. */
void
-finish_record_layout (rli)
+finish_record_layout (rli, free_p)
record_layout_info rli;
+ int free_p;
{
/* Compute the final size. */
finalize_record_size (rli);
@@ -1401,7 +1533,8 @@ finish_record_layout (rli)
}
/* Clean up. */
- free (rli);
+ if (free_p)
+ free (rli);
}
/* Calculate the mode, size, and alignment for TYPE.
@@ -1602,7 +1735,7 @@ layout_type (type)
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
#ifdef MEMBER_TYPE_FORCES_BLK
- && ! MEMBER_TYPE_FORCES_BLK (type)
+ && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)
#endif
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
@@ -1656,7 +1789,7 @@ layout_type (type)
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
- finish_record_layout (rli);
+ finish_record_layout (rli, /*free_p=*/true);
}
break;
@@ -1705,7 +1838,7 @@ layout_type (type)
/* 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);
@@ -1848,9 +1981,6 @@ set_sizetype (type)
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))
@@ -2006,10 +2136,4 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
return mode;
}
-/* 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"
OpenPOWER on IntegriCloud