[cfe-commits] r44664 - in /cfe/trunk: CodeGen/CodeGenTypes.cpp CodeGen/CodeGenTypes.h test/CodeGen/struct-x86-darwin.c

Devang Patel dpatel at apple.com
Thu Dec 6 11:16:06 PST 2007


Author: dpatel
Date: Thu Dec  6 13:16:05 2007
New Revision: 44664

URL: http://llvm.org/viewvc/llvm-project?rev=44664&view=rev
Log:
More struct bitfields layout work. Now handle,

struct STestB1 {char a; char b:2; } stb1;
struct STestB2 {char a; char b:5; char c:4} stb2;


Modified:
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/CodeGen/CodeGenTypes.h
    cfe/trunk/test/CodeGen/struct-x86-darwin.c

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=44664&r1=44663&r2=44664&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Thu Dec  6 13:16:05 2007
@@ -359,12 +359,13 @@
 
 /// addFieldInfo - Assign field number to field FD.
 void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No,
-                                unsigned Begin, unsigned End) {
+                                unsigned Begin, unsigned End,
+                                unsigned AccessNo) {
   if (Begin == 0 && End == 0)
     FieldInfo[FD] = No;
   else
     // FD is a bit field
-    BitFields.insert(std::make_pair(FD, BitFieldInfo(No, Begin, End)));
+    BitFields.insert(std::make_pair(FD, BitFieldInfo(No, Begin, End, AccessNo)));
 }
 
 /// getCGRecordLayout - Return record layout info for the given llvm::Type.
@@ -409,24 +410,52 @@
       assert (isBitField  && "Invalid BitField size expression");
       uint64_t BitFieldSize =  FieldSize.getZExtValue();
       if (ExtraBits == 0) {
-        const llvm::Type *PrevTy = LLVMFields.back();
+        // CurrentField is a bit-field and structure is in one of the
+        // following form.
+        // struct { char CurrentField:2; char B:4; }
+        // struct { char A; char CurrentField:2; };
+        // struct { char A; short CurrentField:2; };
         const llvm::Type *Ty = CGT.ConvertType(FD->getType());
-        assert (CGT.getTargetData().getTypeSizeInBits(PrevTy) >=
-                CGT.getTargetData().getTypeSizeInBits(Ty) 
-                && "FIXME Unable to handle bit field. Reuse last field");
-                
         // Calculate extra bits available in this bitfield.
         ExtraBits = CGT.getTargetData().getTypeSizeInBits(Ty) - BitFieldSize;
-        addLLVMField(Ty, BitFieldSize, FD, 0, ExtraBits);
+
+        if (LLVMFields.empty()) 
+          // Ths is - struct { char CurrentField:2; char B:4; }
+          addLLVMField(Ty, BitFieldSize, FD, 0, ExtraBits);
+        else {
+          const llvm::Type *PrevTy = LLVMFields.back();
+          if (CGT.getTargetData().getTypeSizeInBits(PrevTy) >=
+              CGT.getTargetData().getTypeSizeInBits(Ty)) 
+            // This is - struct { char A; char CurrentField:2; };
+            addLLVMField(Ty, BitFieldSize, FD, 0, ExtraBits);
+          else {
+            // This is - struct { char A; short CurrentField:2; };
+            // Use one of the previous filed to access current field.
+            assert(0 
+                   && "Incomplete support for struct { char a; short b:2;}; ");
+          }
+        }
       } else  if (ExtraBits >= BitFieldSize) {
         // Reuse existing llvm field
         ExtraBits = ExtraBits  - BitFieldSize;
         CGT.addFieldInfo(FD, FieldNo, Cursor - CurrentFieldStart,
-                         ExtraBits);
+                         ExtraBits, FieldNo);
         Cursor = Cursor + BitFieldSize;
         ++FieldNo;
-      } else 
-        assert (!FD->isBitField() && "Bit fields are not yet supported");
+      } else {
+        //ExtraBits are not enough to hold entire FD.
+        const llvm::Type *Ty = CGT.ConvertType(FD->getType());
+        const llvm::Type *PrevTy = LLVMFields.back();
+        uint64_t TySize = CGT.getTargetData().getTypeSizeInBits(Ty);
+        if (CGT.getTargetData().getTypeSizeInBits(PrevTy) >= TySize) {
+          // Previous field does not allow sharing of ExtraBits. Use new field.
+          // struct { char a; char b:5; char c:4; } where c is current FD.
+          Cursor += ExtraBits;
+          ExtraBits = 0;
+          addLLVMField(Ty, TySize, FD, 0, BitFieldSize);
+        } else
+          assert (!FD->isBitField() && "Bit fields are not yet supported");
+      }
     } else {
       ExtraBits = 0;
       const llvm::Type *Ty = CGT.ConvertType(FD->getType());
@@ -465,7 +494,7 @@
   Cursor += Size;
   LLVMFields.push_back(Ty);
   if (FD)
-    CGT.addFieldInfo(FD, FieldNo, Begin, End);
+    CGT.addFieldInfo(FD, FieldNo, Begin, End, FieldNo);
   ++FieldNo;
 }
 
@@ -477,7 +506,7 @@
   unsigned PrimaryEltNo = 0;
   std::pair<uint64_t, unsigned> PrimaryElt =
     CGT.getContext().getTypeInfo(FieldDecls[0]->getType(), SourceLocation());
-  CGT.addFieldInfo(FieldDecls[0], 0, 0, 0);
+  CGT.addFieldInfo(FieldDecls[0], 0, 0, 0, 0);
 
   unsigned Size = FieldDecls.size();
   for(unsigned i = 1; i != Size; ++i) {
@@ -495,7 +524,7 @@
     }
 
     // In union, each field gets first slot.
-    CGT.addFieldInfo(FD, 0, 0, 0);
+    CGT.addFieldInfo(FD, 0, 0, 0, 0);
   }
 
   std::vector<const llvm::Type*> Fields;

Modified: cfe/trunk/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.h?rev=44664&r1=44663&r2=44664&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.h Thu Dec  6 13:16:05 2007
@@ -78,12 +78,19 @@
 
   class BitFieldInfo {
   public:
-    explicit BitFieldInfo(unsigned N, unsigned B, unsigned E)
-      : No(N), Begin(B), End(E) {}
+    explicit BitFieldInfo(unsigned N, unsigned B, unsigned E, unsigned A)
+      : No(N), Begin(B), End(E), AccessFieldNo(A) {}
   private:
+    // No - Field number in llvm struct.
     unsigned No;
     unsigned Begin;
     unsigned End;
+    // AccessFieldNo - llvm struct field number that is used to
+    // access this field. It may be not same as No. For example,
+    // struct S { char a; short b:2; }
+    // Here field 'b' is second field however it is accessed as
+    // 9th and 10th bitfield of first field whose type is short.
+    unsigned AccessFieldNo;
   };
   llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields;
 
@@ -125,7 +132,7 @@
 
   /// addFieldInfo - Assign field number to field FD.
   void addFieldInfo(const FieldDecl *FD, unsigned No, unsigned Begin, 
-                    unsigned End);
+                    unsigned End, unsigned AccessNo);
 };
 
 }  // end namespace CodeGen

Modified: cfe/trunk/test/CodeGen/struct-x86-darwin.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/struct-x86-darwin.c?rev=44664&r1=44663&r2=44664&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/struct-x86-darwin.c (original)
+++ cfe/trunk/test/CodeGen/struct-x86-darwin.c Thu Dec  6 13:16:05 2007
@@ -1,7 +1,9 @@
 // RUN: clang %s -emit-llvm > %t1
-// RUN  grep "STest1 = type { i32, \[4 x i16\], double }" %t1
-// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1
-// RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1
+// Run  grep "STest1 = type { i32, \[4 x i16\], double }" %t1 &&
+// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1 &&
+// RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1 &&
+// RUN: grep "STestB1 = type { i8, i8 }" %t1 &&
+// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1
 // Test struct layout for x86-darwin target
 // FIXME : Enable this test for x86-darwin only. At the moment clang hard codes
 // x86-darwin as the target
@@ -10,5 +12,9 @@
 struct STest2 {short a,b; int c,d; } st2;
 struct STest3 {char a; short b; int c; } st3;
 
-// Bitfields struct STestB1 {int a:1; char b; int c:13 } stb1;
+// Bitfields 
+struct STestB1 {char a; char b:2; } stb1;
+struct STestB2 {char a; char b:5; char c:4} stb2;
+
+//struct STestB {int a:1; char b; int c:13 } stb;
 // Packed struct STestP1 {char a; short b; int c; } __attribute__((__packed__)) stp1;





More information about the cfe-commits mailing list