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

Devang Patel dpatel at apple.com
Mon Dec 10 16:49:18 PST 2007


Author: dpatel
Date: Mon Dec 10 18:49:18 2007
New Revision: 44830

URL: http://llvm.org/viewvc/llvm-project?rev=44830&view=rev
Log:
Add support to share llvm fields for bit-fields.
For example, struct { char a; short b:2; };

Modified:
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    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=44830&r1=44829&r2=44830&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Mon Dec 10 18:49:18 2007
@@ -65,6 +65,15 @@
       return STy;
     }
 
+    /// fixCursorPosition - When bit-field is followed by a normal field
+    /// then cursor position may require some adjustments. For example,
+    /// struct { char a; short b:2;  char c; }; 
+    /// At the beginning of 'c' during layout, cursor position is 10.
+    /// However, only one llvm struct field is allocated and it is i8.
+    /// This happens because 'b' shares llvm field with 'a'.
+    /// Similar adjustment may be required if bit-field is last field.
+    void fixCursorPosition(const ASTRecordLayout &RL);
+
   private:
     CodeGenTypes &CGT;
     llvm::Type *STy;
@@ -80,6 +89,7 @@
      uint64_t CurrentFieldStart;
     llvm::SmallVector<const FieldDecl *, 8> FieldDecls;
     std::vector<const llvm::Type*> LLVMFields;
+    llvm::SmallVector<uint64_t, 8> Offsets;
   };
 }
 
@@ -431,8 +441,23 @@
           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;}; ");
+            bool FoundPrevField = false;
+            unsigned TotalOffsets = Offsets.size();
+            uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
+            for (unsigned i = TotalOffsets; i != 0; --i) {
+              uint64_t O = Offsets[i - 1];
+              if (O % TySize == 0) {
+                // This is appropriate llvm field to share access.
+                FoundPrevField = true;
+                CurrentFieldStart = O % TySize;
+                unsigned FieldBegin = Cursor - (O % TySize);
+                unsigned FieldEnd = TySize - (FieldBegin + BitFieldSize);
+                Cursor += BitFieldSize;
+                CGT.addFieldInfo(FD, FieldNo, FieldBegin, FieldEnd, i);
+              }
+            }
+            assert(FoundPrevField && 
+                   "Unable to find a place for bitfield in struct layout");
           }
         }
       } else  if (ExtraBits >= BitFieldSize) {
@@ -458,10 +483,20 @@
       }
     } else {
       ExtraBits = 0;
+      // FD is not a bitfield. If prev field was a bit field then it may have
+      // positioned cursor such that it needs adjustment now.
+      if (Cursor % 8 != 0)
+        fixCursorPosition(RL);
+
       const llvm::Type *Ty = CGT.ConvertType(FD->getType());
       addLLVMField(Ty, CGT.getTargetData().getABITypeSizeInBits(Ty), FD, 0, 0);
     }
   }
+
+  // At the end of structure, cursor should point to end of the strucutre.
+  // This may not happen automatically if last field is a bit-field.
+  fixCursorPosition(RL);
+
   STy = llvm::StructType::get(LLVMFields);
 }
 
@@ -490,6 +525,7 @@
     // combining consequetive padding fields.
     addPaddingFields(Cursor % AlignmentInBits);
 
+  Offsets.push_back(Cursor);
   CurrentFieldStart = Cursor;
   Cursor += Size;
   LLVMFields.push_back(Ty);
@@ -533,3 +569,25 @@
   STy = llvm::StructType::get(Fields);
 }
 
+/// fixCursorPosition - When bit-field is followed by a normal field
+/// then cursor position may require some adjustments. For example,
+/// struct { char a; short b:2;  char c; }; 
+/// At the beginning of 'c' during layout, cursor position is 10.
+/// However, only one llvm struct field is allocated so far  is i8.
+/// This happens because 'b' shares llvm field with 'a'.
+/// Similar adjustment may be required if last record field is a bit-field.
+void RecordOrganizer::fixCursorPosition(const ASTRecordLayout &RL) {
+  uint64_t llvmSize = 0;
+  for(std::vector<const llvm::Type*>::iterator LI = LLVMFields.begin(), 
+        LE = LLVMFields.end(); LI != LE; ++LI) {
+    const llvm::Type *Ty = *LI;
+    llvmSize += CGT.getTargetData().getABITypeSizeInBits(Ty);
+  }
+  Cursor = llvmSize;
+  unsigned llvmSizeBytes = llvmSize/8;
+  unsigned StructAlign = RL.getAlignment() / 8;
+  if (llvmSizeBytes % StructAlign) {
+    unsigned StructPadding = StructAlign - (llvmSizeBytes % StructAlign);
+    addPaddingFields(StructPadding*8);
+  }
+}

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=44830&r1=44829&r2=44830&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/struct-x86-darwin.c (original)
+++ cfe/trunk/test/CodeGen/struct-x86-darwin.c Mon Dec 10 18:49:18 2007
@@ -3,7 +3,9 @@
 // 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
+// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1 &&
+// RUN: grep "STestB3 = type { i8, i8 }" %t1 &&
+// RUN: grep "STestB4 = type { i8, 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
@@ -14,7 +16,9 @@
 
 // Bitfields 
 struct STestB1 {char a; char b:2; } stb1;
-struct STestB2 {char a; char b:5; char c:4} stb2;
+struct STestB2 {char a; char b:5; char c:4; } stb2;
+struct STestB3 {char a; char b:2; } stb3;
+struct STestB4 {char a; short b:2; char c; } stb4;
 
 //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