r201282 - ms_struct layout replaces platform-specific behavior like

John McCall rjmccall at apple.com
Wed Feb 12 16:50:08 PST 2014


Author: rjmccall
Date: Wed Feb 12 18:50:08 2014
New Revision: 201282

URL: http://llvm.org/viewvc/llvm-project?rev=201282&view=rev
Log:
ms_struct layout replaces platform-specific behavior like
useBitFieldTypeAlignment() and appears to ignore the special
bit-packing semantics of __attribute__((packed)).

Further flesh out an already-extensive comment.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/test/CodeGen/ms_struct-bitfield.c

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=201282&r1=201281&r2=201282&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed Feb 12 18:50:08 2014
@@ -1458,21 +1458,50 @@ void RecordLayoutBuilder::LayoutBitField
   // 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
     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
   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.

Modified: cfe/trunk/test/CodeGen/ms_struct-bitfield.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms_struct-bitfield.c?rev=201282&r1=201281&r2=201282&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/ms_struct-bitfield.c (original)
+++ cfe/trunk/test/CodeGen/ms_struct-bitfield.c Wed Feb 12 18:50:08 2014
@@ -1,7 +1,11 @@
 // RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-apple-darwin9 %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - -triple thumbv7-apple-ios -target-abi apcs-gnu %s | FileCheck %s -check-prefix=CHECK-ARM
 
 // rdar://8823265
 
+// Note that we're declaring global variables with these types,
+// triggering both Sema and IRGen struct layout.
+
 #define ATTR __attribute__((__ms_struct__))
 
 struct
@@ -12,6 +16,7 @@ struct
 } ATTR t1;
 int s1 = sizeof(t1);
 // CHECK: @s1 = global i32 2
+// CHECK-ARM: @s1 = global i32 2
 
 struct
 {
@@ -23,6 +28,7 @@ struct
 } ATTR t2;
 int s2 = sizeof(t2);
 // CHECK: @s2 = global i32 2
+// CHECK-ARM: @s2 = global i32 2
 
 struct
 {
@@ -36,6 +42,7 @@ struct
 } ATTR t3;
 int s3 = sizeof(t3);
 // CHECK: @s3 = global i32 2
+// CHECK-ARM: @s3 = global i32 2
 
 struct
 {
@@ -44,6 +51,7 @@ struct
 } ATTR t4;
 int s4 = sizeof(t4);
 // CHECK: @s4 = global i32 1
+// CHECK-ARM: @s4 = global i32 1
 
 struct
 {
@@ -54,6 +62,7 @@ struct
 } ATTR t5;
 int s5 = sizeof(t5);
 // CHECK: @s5 = global i32 1
+// CHECK-ARM: @s5 = global i32 1
 
 struct
 {
@@ -64,6 +73,7 @@ struct
 } ATTR t6;
 int s6 = sizeof(t6);
 // CHECK: @s6 = global i32 1
+// CHECK-ARM: @s6 = global i32 1
 
 struct
 {
@@ -84,6 +94,7 @@ struct
 } ATTR t7;
 int s7 = sizeof(t7);
 // CHECK: @s7 = global i32 9
+// CHECK-ARM: @s7 = global i32 9
 
 struct
 {
@@ -93,6 +104,7 @@ struct
 } ATTR t8;
 int s8 = sizeof(t8);
 // CHECK: @s8 = global i32 0
+// CHECK-ARM: @s8 = global i32 0
 
 struct
 {
@@ -125,6 +137,7 @@ struct
 } ATTR t9;
 int s9 = sizeof(t9);
 // CHECK: @s9 = global i32 28
+// CHECK-ARM: @s9 = global i32 28
 
 struct
 {
@@ -134,3 +147,33 @@ struct
 } ATTR t10;
 int s10 = sizeof(t10);
 // CHECK: @s10 = global i32 16
+// CHECK-ARM: @s10 = global i32 8
+
+// rdar://16041826 - ensure that ms_structs work correctly on a
+// !useBitFieldTypeAlignment() target
+struct {
+  unsigned int a : 31;
+  unsigned int b : 2;
+  unsigned int c;
+} ATTR t11;
+int s11 = sizeof(t11);
+// CHECK: @s11 = global i32 12
+// CHECK-ARM: @s11 = global i32 12
+
+struct {
+  unsigned char a : 3;
+  unsigned char b : 4;
+  unsigned short c : 6;
+} ATTR t12;
+int s12 = sizeof(t12);
+// CHECK: @s12 = global i32 4
+// CHECK-ARM: @s12 = global i32 4
+
+struct {
+  unsigned char a : 3;
+  unsigned char b : 4;
+  __attribute__((packed)) unsigned short c : 6;
+} ATTR t13;
+int s13 = sizeof(t13);
+// CHECK: @s13 = global i32 4
+// CHECK-ARM: @s13 = global i32 4





More information about the cfe-commits mailing list