diff options
author | Douglas B Rupp <rupp@gnat.com> | 2002-09-18 18:51:14 +0000 |
---|---|---|
committer | Douglas Rupp <rupp@gcc.gnu.org> | 2002-09-18 18:51:14 +0000 |
commit | e4850f36e545325e3309870d13dfe4582e7cb9d4 (patch) | |
tree | db1286b6218421cfbaf55c157f77ee8912f2bf17 | |
parent | 62f1a74c0f77dbe42561774579317fe56fda7401 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 29 | ||||
-rw-r--r-- | gcc/stor-layout.c | 202 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
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 @@ -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; |