aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas B Rupp <rupp@gnat.com>2002-09-18 18:51:14 +0000
committerDouglas Rupp <rupp@gcc.gnu.org>2002-09-18 18:51:14 +0000
commite4850f36e545325e3309870d13dfe4582e7cb9d4 (patch)
treedb1286b6218421cfbaf55c157f77ee8912f2bf17
parent62f1a74c0f77dbe42561774579317fe56fda7401 (diff)
downloadgcc-e4850f36e545325e3309870d13dfe4582e7cb9d4.zip
gcc-e4850f36e545325e3309870d13dfe4582e7cb9d4.tar.gz
gcc-e4850f36e545325e3309870d13dfe4582e7cb9d4.tar.bz2
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/doc/tm.texi29
-rw-r--r--gcc/stor-layout.c202
-rw-r--r--gcc/tree.h2
4 files changed, 203 insertions, 44 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ee2543a..365c689 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index ebc242f..2fd4a7b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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.
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 28d8f62..dae4c2d 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
diff --git a/gcc/tree.h b/gcc/tree.h
index f95f363..310d643 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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;