diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 63 |
1 files changed, 46 insertions, 17 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 5624ce7836f..cffdcaf743b 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1458,21 +1458,50 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // for ms_struct records it's also a multiple of the // LastBitfieldTypeSize (if set). - // The basic bitfield layout rule for ms_struct is to allocate an - // entire unit of the bitfield's declared type (e.g. 'unsigned - // long'), then parcel it up among successive bitfields whose - // declared types have the same size, making a new unit as soon as - // the last can no longer store the whole value. - - // The standard bitfield layout rule for non-ms_struct is to place - // bitfields at the next available bit offset where the entire - // bitfield would fit in an aligned storage unit of the declared - // type (even if there are also non-bitfields within that same - // unit). However, some targets (those that !useBitFieldTypeAlignment()) - // don't require this storage unit to be aligned, and therefore - // always put the bit-field at the next available bit offset. - // Such targets generally do interpret zero-width bitfields as - // forcing the use of a new storage unit. + // The struct-layout algorithm is dictated by the platform ABI, + // which in principle could use almost any rules it likes. In + // practice, UNIXy targets tend to inherit the algorithm described + // in the System V generic ABI. The basic bitfield layout rule in + // System V is to place bitfields at the next available bit offset + // where the entire bitfield would fit in an aligned storage unit of + // the declared type; it's okay if an earlier or later non-bitfield + // is allocated in the same storage unit. However, some targets + // (those that !useBitFieldTypeAlignment(), e.g. ARM APCS) don't + // require this storage unit to be aligned, and therefore always put + // the bitfield at the next available bit offset. + + // ms_struct basically requests a complete replacement of the + // platform ABI's struct-layout algorithm, with the high-level goal + // of duplicating MSVC's layout. For non-bitfields, this follows + // the the standard algorithm. The basic bitfield layout rule is to + // allocate an entire unit of the bitfield's declared type + // (e.g. 'unsigned long'), then parcel it up among successive + // bitfields whose declared types have the same size, making a new + // unit as soon as the last can no longer store the whole value. + // Since it completely replaces the platform ABI's algorithm, + // settings like !useBitFieldTypeAlignment() do not apply. + + // A zero-width bitfield forces the use of a new storage unit for + // later bitfields. In general, this occurs by rounding up the + // current size of the struct as if the algorithm were about to + // place a non-bitfield of the field's formal type. Usually this + // does not change the alignment of the struct itself, but it does + // on some targets (those that useZeroLengthBitfieldAlignment(), + // e.g. ARM). In ms_struct layout, zero-width bitfields are + // ignored unless they follow a non-zero-width bitfield. + + // A field alignment restriction (e.g. from #pragma pack) or + // specification (e.g. from __attribute__((aligned))) changes the + // formal alignment of the field. For System V, this alters the + // required alignment of the notional storage unit that must contain + // the bitfield. For ms_struct, this only affects the placement of + // new storage units. In both cases, the effect of #pragma pack is + // ignored on zero-width bitfields. + + // On System V, a packed field (e.g. from #pragma pack or + // __attribute__((packed))) always uses the next available bit + // offset. + // First, some simple bookkeeping to perform for ms_struct structs. if (IsMsStruct) { @@ -1504,7 +1533,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { IsUnion ? 0 : (getDataSizeInBits() - UnfilledBitsInLastUnit); // Handle targets that don't honor bitfield type alignment. - if (!Context.getTargetInfo().useBitFieldTypeAlignment()) { + if (!IsMsStruct && !Context.getTargetInfo().useBitFieldTypeAlignment()) { // Some such targets do honor it on zero-width bitfields. if (FieldSize == 0 && Context.getTargetInfo().useZeroLengthBitfieldAlignment()) { @@ -1524,7 +1553,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { unsigned UnpackedFieldAlign = FieldAlign; // Ignore the field alignment if the field is packed. - if (FieldPacked) + if (!IsMsStruct && FieldPacked) FieldAlign = 1; // But, if there's an 'aligned' attribute on the field, honor that. |

