[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