summaryrefslogtreecommitdiff
path: root/gcc/stor-layout.c
diff options
context:
space:
mode:
authorrupp <rupp@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-18 18:51:14 +0000
committerrupp <rupp@138bc75d-0d04-0410-961f-82ee72b054a4>2002-09-18 18:51:14 +0000
commit8642f3d3ca9bd142a875260ed9998508eb992a75 (patch)
treedb1286b6218421cfbaf55c157f77ee8912f2bf17 /gcc/stor-layout.c
parent3193f3b162324f2600d5bec2c81224e9943ef19f (diff)
downloadgcc-8642f3d3ca9bd142a875260ed9998508eb992a75.tar.gz
* stor-layout.c (place_field): Handle alignment of whole
structures when MSVC compatible bitfields are involved. Change method of computing location of MS bitfields to be compatible with #pragma pack(n). * tree.h (record_layout_info): Add new field remaining_in_alignment. * doc/tm.texi: (TARGET_MS_BITFIELD_LAYOUT_P): Update. (pragma pack): Add paragraph on MSVC bitfield packing. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@57281 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stor-layout.c')
-rw-r--r--gcc/stor-layout.c202
1 files changed, 158 insertions, 44 deletions
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 28d8f6218d1..dae4c2df38e 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -801,15 +801,27 @@ place_field (rli, field)
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)))
+ && ! integer_zerop (TYPE_SIZE (type)))
{
- if (rli->prev_field
- && DECL_BIT_FIELD_TYPE (rli->prev_field)
- && ! integer_zerop (DECL_SIZE (rli->prev_field)))
+ /* 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, non-zero-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))))
{
- rli->record_align = MAX (rli->record_align, desired_align);
+ 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;
@@ -991,48 +1003,148 @@ place_field (rli, field)
}
#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->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. */
@@ -1061,7 +1173,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