]> granicus.if.org Git - clang/commitdiff
Simplify bitfield codegen.
authorLauro Ramos Venancio <lauro.venancio@gmail.com>
Thu, 7 Feb 2008 19:29:53 +0000 (19:29 +0000)
committerLauro Ramos Venancio <lauro.venancio@gmail.com>
Thu, 7 Feb 2008 19:29:53 +0000 (19:29 +0000)
Fix codegen of struct { short a[3]; int b:15; }.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46859 91177308-0d34-0410-b5e6-96231b3b80d8

CodeGen/CGExpr.cpp
CodeGen/CodeGenTypes.cpp
test/CodeGen/bitfield.c

index cb0f42a645e7125bbe9f43bf253fe99dd322281f..9c7876830cb42e5e4156e8ebda7bbf05219e454e 100644 (file)
@@ -454,7 +454,7 @@ EmitOCUVectorElementExpr(const OCUVectorElementExpr *E) {
 }
 
 LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
-
+  llvm::Value *V;
   bool isUnion = false;
   Expr *BaseExpr = E->getBase();
   llvm::Value *BaseValue = NULL;
@@ -476,14 +476,27 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
   }
 
   FieldDecl *Field = E->getMemberDecl();
-
   unsigned idx = CGM.getTypes().getLLVMFieldNo(Field);
-  llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty), 
-                           llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) };
 
-  llvm::Value *V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp");
+
+  if (Field->isBitField()) {
+    const llvm::Type * FieldTy = ConvertType(Field->getType());
+    const llvm::PointerType * BaseTy =
+      cast<llvm::PointerType>(BaseValue->getType());
+    unsigned AS = BaseTy->getAddressSpace();
+    BaseValue = Builder.CreateBitCast(BaseValue,
+                                      llvm::PointerType::get(FieldTy, AS),
+                                      "tmp");
+    V = Builder.CreateGEP(BaseValue,
+                          llvm::ConstantInt::get(llvm::Type::Int32Ty, idx),
+                          "tmp");
+  } else {
+    llvm::Value *Idxs[2] = { llvm::Constant::getNullValue(llvm::Type::Int32Ty),
+                             llvm::ConstantInt::get(llvm::Type::Int32Ty, idx) };
+    V = Builder.CreateGEP(BaseValue,Idxs, Idxs + 2, "tmp");
+  }
   // Match union field type.
-  if (isUnion || Field->isBitField()) {
+  if (isUnion) {
     const llvm::Type * FieldTy = ConvertType(Field->getType());
     const llvm::PointerType * BaseTy = 
       cast<llvm::PointerType>(BaseValue->getType());
index 93b441bc62b07f8bcd41555376e5d1a55b3a29e3..bed01eeb61bc11a509f8e7fc6cc37582019f7686 100644 (file)
@@ -73,7 +73,6 @@ namespace {
     uint64_t llvmSize;
     llvm::SmallVector<const FieldDecl *, 8> FieldDecls;
     std::vector<const llvm::Type*> LLVMFields;
-    llvm::SmallVector<uint64_t, 8> Offsets;
     llvm::SmallSet<unsigned, 8> PaddingFields;
   };
 }
@@ -449,7 +448,6 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
   llvmFieldNo = 0;
   Cursor = 0;
   LLVMFields.clear();
-  Offsets.clear();
 
   for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(),
          E = FieldDecls.end(); I != E; ++I) {
@@ -499,7 +497,6 @@ void RecordOrganizer::addLLVMField(const llvm::Type *Ty, bool isPaddingField) {
   }
 
   unsigned TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
-  Offsets.push_back(llvmSize);
   llvmSize += TySize;
   if (isPaddingField)
     PaddingFields.insert(llvmFieldNo);
@@ -555,51 +552,26 @@ void RecordOrganizer::placeBitField(const FieldDecl *FD) {
   assert (isBitField  && "Invalid BitField size expression");
   uint64_t BitFieldSize =  FieldSize.getZExtValue();
 
-  bool FoundPrevField = false;
-  unsigned TotalOffsets = Offsets.size();
   const llvm::Type *Ty = CGT.ConvertType(FD->getType());
   uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
-  
-  if (!TotalOffsets) {
-    // Special case: the first field. 
-    CGT.addFieldInfo(FD, llvmFieldNo);
-    CGT.addBitFieldInfo(FD, 0, BitFieldSize);
-    addPaddingFields(BitFieldSize);
-    Cursor = BitFieldSize;
-    return;
-  }
 
-  // Search for the last aligned field.
-  for (unsigned i = TotalOffsets; i != 0; --i) {
-    uint64_t O = Offsets[i - 1];
-    if (O % TySize == 0) {
-      FoundPrevField = true;
-      if (TySize > (Cursor - O) && TySize - (Cursor - O) >= BitFieldSize) {
-       // The bitfield fits in the last aligned field.
-       // This is : struct { char a; int CurrentField:10;};
-       // where 'CurrentField' shares first field with 'a'.
-       addPaddingFields(Cursor + BitFieldSize);
-       CGT.addFieldInfo(FD, i - 1);
-       CGT.addBitFieldInfo(FD, Cursor - O, BitFieldSize);
-       Cursor += BitFieldSize;
-      } else {
-       // Place the bitfield in a new LLVM field.
-       // This is : struct { char a; short CurrentField:10;};
-       // where 'CurrentField' needs a new llvm field.
-        unsigned Padding = 0;
-        if (Cursor % TySize) {
-          Padding = TySize - (Cursor % TySize);
-          addPaddingFields(Cursor + Padding);
-        }
-       CGT.addFieldInfo(FD, llvmFieldNo);
-       CGT.addBitFieldInfo(FD, 0, BitFieldSize);
-        Cursor += Padding + BitFieldSize;
-       addPaddingFields(Cursor);
-      }
-      break;
-    }
-  }
+  unsigned Idx = Cursor / TySize;
+  unsigned BitsLeft = TySize - (Cursor % TySize);
 
-  assert(FoundPrevField && 
-        "Unable to find a place for bitfield in struct layout");
+  if (BitsLeft >= BitFieldSize) {
+    // The bitfield fits in the last aligned field.
+    // This is : struct { char a; int CurrentField:10;};
+    // where 'CurrentField' shares first field with 'a'.
+    CGT.addFieldInfo(FD, Idx);
+    CGT.addBitFieldInfo(FD, TySize - BitsLeft, BitFieldSize);
+    Cursor += BitFieldSize;
+  } else {
+    // Place the bitfield in a new LLVM field.
+    // This is : struct { char a; short CurrentField:10;};
+    // where 'CurrentField' needs a new llvm field.
+    CGT.addFieldInfo(FD, Idx + 1);
+    CGT.addBitFieldInfo(FD, 0, BitFieldSize);
+    Cursor = (Idx + 1) * TySize + BitFieldSize;
+  }
+  addPaddingFields(Cursor);
 }
index 70414a9c1e3840d31e28bb07169e925e67b29e31..740c41c5369e4ce0ebc2869b7775eb36b8d620c1 100644 (file)
@@ -5,10 +5,12 @@
 // RUN: grep "lshr i16 %tmp5, 9" %t1
 // RUN: grep "and i32 %tmp, -8192" %t1
 // RUN: grep "and i16 %tmp5, -32513" %t1
+// RUN: grep "getelementptr (i32\* bitcast (.struct.STestB2\* @stb2 to i32\*), i32 1)" %t1
 // Test bitfield access
 
 
 struct STestB1 { int a:13; char b; unsigned short c:7;} stb1;
+struct STestB2 { short a[3]; int b:15} stb2;
 
 int f() {
   return stb1.a + stb1.b + stb1.c;
@@ -19,3 +21,12 @@ void g() {
   stb1.b = 10;
   stb1.c = 15;
 }
+
+int h() {
+  return stb2.a[1] + stb2.b;
+}
+
+void i(){
+  stb2.a[2] = -40;
+  stb2.b = 10;
+}