summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp63
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.
OpenPOWER on IntegriCloud