[cfe-commits] r101467 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp lib/AST/RecordLayoutBuilder.h test/SemaCXX/bitfield-layout.cpp

Anders Carlsson andersca at mac.com
Fri Apr 16 08:57:11 PDT 2010


Author: andersca
Date: Fri Apr 16 10:57:11 2010
New Revision: 101467

URL: http://llvm.org/viewvc/llvm-project?rev=101467&view=rev
Log:
More work on wide bit-fields, WIP.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.h
    cfe/trunk/test/SemaCXX/bitfield-layout.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=101467&r1=101466&r2=101467&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Apr 16 10:57:11 2010
@@ -609,6 +609,66 @@
     LayoutField(*Field);
 }
 
+void ASTRecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, 
+                                                uint64_t TypeSize) {
+  assert(Context.getLangOptions().CPlusPlus &&
+         "Can only have wide bit-fields in C++!");
+  
+  // Itanium C++ ABI 2.4:
+  //   If sizeof(T)*8 < n, let T' be the largest integral POD type with 
+  //   sizeof(T')*8 <= n.
+  
+  QualType IntegralPODTypes[] = {
+    Context.UnsignedCharTy, Context.UnsignedShortTy, Context.UnsignedIntTy, 
+    Context.UnsignedLongTy, Context.UnsignedLongLongTy
+  };
+
+  printf("field sizes %llu type size %llu\n",
+         FieldSize, TypeSize);
+  
+  QualType Type;
+  for (unsigned I = 0, E = llvm::array_lengthof(IntegralPODTypes);
+       I != E; ++I) {
+    uint64_t Size = Context.getTypeSize(IntegralPODTypes[I]);
+    printf("going to try %s %llu\n", IntegralPODTypes[I].getAsString().c_str(),
+           Size);
+
+    if (Size > FieldSize)
+      break;
+
+    Type = IntegralPODTypes[I];
+  }
+  assert(!Type.isNull() && "Did not find a type!");
+  printf("type should be %s\n", Type.getAsString().c_str());
+  
+  unsigned TypeAlign = Context.getTypeAlign(Type);
+
+  // We're not going to use any of the unfilled bits in the last byte.
+  UnfilledBitsInLastByte = 0;
+
+  // The bitfield is allocated starting at the next offset aligned appropriately
+  // for T', with length n bits. 
+  uint64_t FieldOffset = llvm::RoundUpToAlignment(DataSize, TypeAlign);
+
+  if (IsUnion) {
+    DataSize = std::max(DataSize, FieldSize);
+  } else {
+    uint64_t NewSizeInBits = FieldOffset + FieldSize;
+    
+    DataSize = llvm::RoundUpToAlignment(NewSizeInBits, 8);
+    UnfilledBitsInLastByte = DataSize - NewSizeInBits;
+  }
+
+  // Place this field at the current location.
+  FieldOffsets.push_back(FieldOffset);
+
+  // Update the size.
+  Size = std::max(Size, DataSize);
+  
+  // Remember max struct/class alignment.
+  UpdateAlignment(TypeAlign);
+}
+
 void ASTRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
   uint64_t FieldOffset = IsUnion ? 0 : (DataSize - UnfilledBitsInLastByte);
@@ -618,6 +678,11 @@
   uint64_t TypeSize = FieldInfo.first;
   unsigned FieldAlign = FieldInfo.second;
 
+  if (FieldSize > TypeSize) {
+    LayoutWideBitField(FieldSize, TypeSize);
+    return;
+  }
+
   if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
     FieldAlign = 1;
   if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.h?rev=101467&r1=101466&r2=101467&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.h (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.h Fri Apr 16 10:57:11 2010
@@ -91,6 +91,7 @@
 
   void LayoutFields(const RecordDecl *D);
   void LayoutField(const FieldDecl *D);
+  void LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize);
   void LayoutBitField(const FieldDecl *D);
 
   /// DeterminePrimaryBase - Determine the primary base of the given class.

Modified: cfe/trunk/test/SemaCXX/bitfield-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/bitfield-layout.cpp?rev=101467&r1=101466&r2=101467&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/bitfield-layout.cpp (original)
+++ cfe/trunk/test/SemaCXX/bitfield-layout.cpp Fri Apr 16 10:57:11 2010
@@ -3,10 +3,28 @@
 #define CHECK_SIZE(name, size) extern int name##1[sizeof(name) == size ? 1 : -1];
 #define CHECK_ALIGN(name, size) extern int name##2[__alignof(name) == size ? 1 : -1];
 
-// Simple test.
+// Simple tests.
 struct Test1 {
   char c : 9; // expected-warning {{size of bit-field 'c' (9 bits) exceeds the size of its type; value will be truncated to 8 bits}}
 };
 CHECK_SIZE(Test1, 2);
 CHECK_ALIGN(Test1, 1);
 
+struct Test2 {
+  char c : 16; // expected-warning {{size of bit-field 'c' (16 bits) exceeds the size of its type; value will be truncated to 8 bits}}
+};
+CHECK_SIZE(Test2, 2);
+CHECK_ALIGN(Test2, 2);
+
+struct Test3 {
+  char c : 32; // expected-warning {{size of bit-field 'c' (32 bits) exceeds the size of its type; value will be truncated to 8 bits}}
+};
+CHECK_SIZE(Test3, 4);
+CHECK_ALIGN(Test3, 4);
+
+struct Test4 {
+  char c : 64; // expected-warning {{size of bit-field 'c' (64 bits) exceeds the size of its type; value will be truncated to 8 bits}}
+};
+CHECK_SIZE(Test4, 8);
+CHECK_ALIGN(Test4, 8);
+





More information about the cfe-commits mailing list