stor-layout.c (place_field): Handle alignment of whole structures when MSVC compatible bitfields are involved.
* 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. Co-Authored-By: Donn Terry <donnte@microsoft.com> From-SVN: r57281
This commit is contained in:
parent
62f1a74c0f
commit
e4850f36e5
|
@ -1,3 +1,17 @@
|
|||
2002-09-18 Douglas Rupp <rupp@gnat.com>
|
||||
Donn Terry <donnte@microsoft.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2002-09-18 Richard Earnshaw (reanrsha@arm.com)
|
||||
|
||||
PR optimization/7967
|
||||
|
|
|
@ -1429,6 +1429,20 @@ the whole enclosing structure, even if it is unnamed; except that
|
|||
(iii) a zero-sized bit-field will be disregarded unless it follows
|
||||
another bit-field of non-zero size. If this hook returns @code{true},
|
||||
other macros that control bit-field layout are ignored.
|
||||
|
||||
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
|
||||
bit-fields (that is, if its long:3, 32 bits is used in the record,
|
||||
and any additional adjacent long bit-fields 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 equivalent when packing.
|
||||
|
||||
If both MS bit-fields and @samp{__attribute__((packed))} are used,
|
||||
the latter will take precedence. If @samp{__attribute__((packed))} is
|
||||
used on a single field when MS bit-fields are in use, it will take
|
||||
precedence for that field, but the alignment of the rest of the structure
|
||||
may affect its placement.
|
||||
@end deftypefn
|
||||
|
||||
@node Type Layout
|
||||
|
@ -8802,6 +8816,21 @@ within a structure, in much the same way as the @samp{__aligned__} and
|
|||
@samp{__packed__} @code{__attribute__}s do. A pack value of zero resets
|
||||
the behavior to the default.
|
||||
|
||||
A subtlety for Microsoft Visual C/C++ style bit-field packing
|
||||
(e.g. -mms-bitfields) for targets that support it:
|
||||
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
|
||||
bit-fields (that is, if its long:3, 32 bits is used in the record,
|
||||
and any additional adjacent long bit-fields are packed into the same
|
||||
chunk of 32 bits. However, if the size changes, a new field of that
|
||||
size is allocated).
|
||||
|
||||
If both MS bit-fields and @samp{__attribute__((packed))} are used,
|
||||
the latter will take precedence. If @samp{__attribute__((packed))} is
|
||||
used on a single field when MS bit-fields are in use, it will take
|
||||
precedence for that field, but the alignment of the rest of the structure
|
||||
may affect its placement.
|
||||
|
||||
The weak pragma only works if @code{SUPPORTS_WEAK} and
|
||||
@code{ASM_WEAKEN_LABEL} are defined. If enabled it allows the creation
|
||||
of specifically named weak labels, optionally with a value.
|
||||
|
|
|
@ -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 (maximum_field_alignment != 0)
|
||||
type_align = MIN (type_align, maximum_field_alignment);
|
||||
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.
|
||||
|
||||
rli->bitpos = round_up (rli->bitpos, type_align);
|
||||
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);
|
||||
|
||||
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
|
||||
|
|
|
@ -2403,6 +2403,8 @@ typedef struct record_layout_info_s
|
|||
/* The static variables (i.e., class variables, as opposed to
|
||||
instance variables) encountered in T. */
|
||||
tree pending_statics;
|
||||
/* Bits remaining in the current alignment group */
|
||||
int remaining_in_alignment;
|
||||
int packed_maybe_necessary;
|
||||
} *record_layout_info;
|
||||
|
||||
|
|
Loading…
Reference in New Issue