[cfe-commits] r46230 - in /cfe/trunk: CodeGen/CodeGenTypes.cpp CodeGen/CodeGenTypes.h test/CodeGen/struct-x86-darwin.c
Lauro Ramos Venancio
lauro.venancio at gmail.com
Mon Jan 21 14:54:57 PST 2008
Author: laurov
Date: Mon Jan 21 16:54:57 2008
New Revision: 46230
URL: http://llvm.org/viewvc/llvm-project?rev=46230&view=rev
Log:
Simplify the bitfield codegen.
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=46230&r1=46229&r2=46230&view=diff
==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Mon Jan 21 16:54:57 2008
@@ -33,17 +33,15 @@
class RecordOrganizer {
public:
explicit RecordOrganizer(CodeGenTypes &Types) :
- CGT(Types), STy(NULL), FieldNo(0), Cursor(0), ExtraBits(0),
- CurrentFieldStart(0), llvmSize(0) {}
+ CGT(Types), STy(NULL), llvmFieldNo(0), Cursor(0),
+ llvmSize(0) {}
/// addField - Add new field.
void addField(const FieldDecl *FD);
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
- /// Update cursor and increment field count.
- void addLLVMField(const llvm::Type *Ty, uint64_t Size,
- const FieldDecl *FD = NULL, unsigned Begin = 0,
- unsigned End = 0);
+ /// Increment field count.
+ void addLLVMField(const llvm::Type *Ty);
/// addPaddingFields - Current cursor is not suitable place to add next
/// field. Add required padding fields.
@@ -65,35 +63,14 @@
return STy;
}
- /// fixCursorPosition - When bit-field is followed by a normal field
- /// cursor position may require some adjustments.
- ///
- /// For example, struct { char a; short b:2; char c; };
- ///
- /// At the beginning of field 'c' layout, cursor position is 10.
- /// However, only llvm struct field allocated so far is of type i8.
- /// This happens because 'b' shares llvm field with 'a'. Add padding
- /// field of i8 type and reposition cursor to point at 16. This
- /// should be done only if next field (i.e. 'c' here) is not a bit-field
- /// or last record field is a bit-field.
- void fixCursorPosition(const ASTRecordLayout &RL);
-
/// placeBitField - Find a place for FD, which is a bit-field.
void placeBitField(const FieldDecl *FD);
private:
CodeGenTypes &CGT;
llvm::Type *STy;
- unsigned FieldNo;
- uint64_t Cursor;
- /* If last field is a bitfield then it may not have occupied all allocated
- bits. Use remaining bits for next field if it also a bitfield. */
- uint64_t ExtraBits;
- /* CurrentFieldStart - Indicates starting offset for current llvm field.
- When current llvm field is shared by multiple bitfields, this is
- used find starting bit offset for the bitfield from the beginning of
- llvm field. */
- uint64_t CurrentFieldStart;
+ unsigned llvmFieldNo;
+ uint64_t Cursor;
uint64_t llvmSize;
llvm::SmallVector<const FieldDecl *, 8> FieldDecls;
std::vector<const llvm::Type*> LLVMFields;
@@ -418,7 +395,6 @@
/// getLLVMFieldNo - Return llvm::StructType element number
/// that corresponds to the field FD.
unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) {
- // FIXME : Check bit fields also
llvm::DenseMap<const FieldDecl *, unsigned>::iterator
I = FieldInfo.find(FD);
assert (I != FieldInfo.end() && "Unable to find field info");
@@ -426,13 +402,22 @@
}
/// addFieldInfo - Assign field number to field FD.
-void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No,
- unsigned Begin, unsigned End) {
- if (Begin == 0 && End == 0)
- FieldInfo[FD] = No;
- else
- // FD is a bit field
- BitFields.insert(std::make_pair(FD, BitFieldInfo(No, Begin, End)));
+void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) {
+ FieldInfo[FD] = No;
+}
+
+/// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field FD.
+CodeGenTypes::BitFieldInfo CodeGenTypes::getBitFieldInfo(const FieldDecl *FD) {
+ llvm::DenseMap<const FieldDecl *, BitFieldInfo>::iterator
+ I = BitFields.find(FD);
+ assert (I != BitFields.end() && "Unable to find bitfield info");
+ return I->second;
+}
+
+/// addBitFieldInfo - Assign a start bit and a size to field FD.
+void CodeGenTypes::addBitFieldInfo(const FieldDecl *FD, unsigned Begin,
+ unsigned Size) {
+ BitFields.insert(std::make_pair(FD, BitFieldInfo(Begin, Size)));
}
/// getCGRecordLayout - Return record layout info for the given llvm::Type.
@@ -462,9 +447,12 @@
/// - Ignore packed structs
void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
// FIXME : Use SmallVector
+ llvmSize = 0;
+ llvmFieldNo = 0;
Cursor = 0;
- FieldNo = 0;
LLVMFields.clear();
+ Offsets.clear();
+
for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(),
E = FieldDecls.end(); I != E; ++I) {
const FieldDecl *FD = *I;
@@ -472,20 +460,18 @@
if (FD->isBitField())
placeBitField(FD);
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);
+ addLLVMField(Ty);
+ CGT.addFieldInfo(FD, llvmFieldNo - 1);
+ Cursor = llvmSize;
}
}
- // 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);
+ unsigned StructAlign = RL.getAlignment();
+ if (llvmSize % StructAlign) {
+ unsigned StructPadding = StructAlign - (llvmSize % StructAlign);
+ addPaddingFields(llvmSize + StructPadding);
+ }
STy = llvm::StructType::get(LLVMFields);
}
@@ -493,38 +479,31 @@
/// addPaddingFields - Current cursor is not suitable place to add next field.
/// Add required padding fields.
void RecordOrganizer::addPaddingFields(unsigned WaterMark) {
- unsigned RequiredBits = WaterMark - Cursor;
- assert ((RequiredBits % 8) == 0 && "FIXME Invalid struct layout");
- unsigned RequiredBytes = RequiredBits / 8;
+ unsigned RequiredBits = WaterMark - llvmSize;
+ unsigned RequiredBytes = (RequiredBits + 7) / 8;
for (unsigned i = 0; i != RequiredBytes; ++i)
- addLLVMField(llvm::Type::Int8Ty,
- CGT.getTargetData().getABITypeSizeInBits(llvm::Type::Int8Ty));
+ addLLVMField(llvm::Type::Int8Ty);
}
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
-/// Update cursor and increment field count. If field decl FD is available than
-/// update field info at CodeGenTypes level.
-void RecordOrganizer::addLLVMField(const llvm::Type *Ty, uint64_t Size,
- const FieldDecl *FD, unsigned Begin,
- unsigned End) {
+/// Increment field count.
+void RecordOrganizer::addLLVMField(const llvm::Type *Ty) {
unsigned AlignmentInBits = CGT.getTargetData().getABITypeAlignment(Ty) * 8;
- unsigned WaterMark = Cursor + (Cursor % AlignmentInBits);
- if (Cursor != WaterMark)
+ if (llvmSize % AlignmentInBits) {
// At the moment, insert padding fields even if target specific llvm
// type alignment enforces implict padding fields for FD. Later on,
// optimize llvm fields by removing implicit padding fields and
// combining consequetive padding fields.
- addPaddingFields(WaterMark);
+ unsigned Padding = AlignmentInBits - (llvmSize % AlignmentInBits);
+ addPaddingFields(llvmSize + Padding);
+ }
- Offsets.push_back(Cursor);
- CurrentFieldStart = Cursor;
- Cursor += Size;
- llvmSize += Size;
+ unsigned TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
+ Offsets.push_back(llvmSize);
+ llvmSize += TySize;
LLVMFields.push_back(Ty);
- if (FD)
- CGT.addFieldInfo(FD, FieldNo, Begin, End);
- ++FieldNo;
+ ++llvmFieldNo;
}
/// layoutUnionFields - Do the actual work and lay out all fields. Create
@@ -535,7 +514,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);
unsigned Size = FieldDecls.size();
for(unsigned i = 1; i != Size; ++i) {
@@ -553,7 +532,7 @@
}
// In union, each field gets first slot.
- CGT.addFieldInfo(FD, 0, 0, 0);
+ CGT.addFieldInfo(FD, 0);
}
std::vector<const llvm::Type*> Fields;
@@ -562,35 +541,9 @@
STy = llvm::StructType::get(Fields);
}
-/// fixCursorPosition - When bit-field is followed by a normal field
-/// cursor position may require some adjustments.
-///
-/// For example, struct { char a; short b:2; char c; };
-///
-/// At the beginning of field 'c' layout, cursor position is 10.
-/// However, only llvm struct field allocated so far is of type i8.
-/// This happens because 'b' shares llvm field with 'a'. Add padding
-/// field of i8 type and reposition cursor to point at 16. This
-/// should be done only if next field (i.e. 'c' here) is not a bit-field
-/// or last record field is a bit-field.
-void RecordOrganizer::fixCursorPosition(const ASTRecordLayout &RL) {
- Cursor = llvmSize;
- unsigned llvmSizeBytes = llvmSize/8;
- unsigned StructAlign = RL.getAlignment() / 8;
- if (llvmSizeBytes % StructAlign) {
- unsigned StructPadding = StructAlign - (llvmSizeBytes % StructAlign);
- addPaddingFields(Cursor + StructPadding*8);
- }
-}
-
-/// placeBitField - Find a place for FD, which is a bit-field.
-/// There are three separate cases to handle
-/// 1) Cursor starts at byte boundry and there are no extra
-/// bits are available in last llvm struct field.
-/// 2) Extra bits from previous last llvm struct field are
-/// available and have enough space to hold entire FD.
-/// 3) Extra bits from previous last llvm struct field are
-/// available but they are not enough to hold FD entirly.
+/// placeBitField - Find a place for FD, which is a bit-field.
+/// This function searches for the last aligned field. If the bit-field fits in
+/// it, it is reused. Otherwise, the bit-field is placed in a new field.
void RecordOrganizer::placeBitField(const FieldDecl *FD) {
assert (FD->isBitField() && "FD is not a bit-field");
@@ -600,81 +553,48 @@
BitWidth->isIntegerConstantExpr(FieldSize, CGT.getContext());
assert (isBitField && "Invalid BitField size expression");
uint64_t BitFieldSize = FieldSize.getZExtValue();
- if (ExtraBits == 0) {
- // 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());
- // Calculate extra bits available in this bitfield.
- ExtraBits = CGT.getTargetData().getABITypeSizeInBits(Ty) - BitFieldSize;
-
- 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().getABITypeSizeInBits(PrevTy) >=
- CGT.getTargetData().getABITypeSizeInBits(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.
- 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, i, FieldBegin, FieldEnd);
- }
- }
- assert(FoundPrevField &&
- "Unable to find a place for bitfield in struct layout");
+
+ 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) >= 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);
+ CGT.addBitFieldInfo(FD, Cursor, 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.
+ addPaddingFields(O + TySize);
+ CGT.addFieldInfo(FD, llvmFieldNo);
+ CGT.addBitFieldInfo(FD, 0, BitFieldSize);
+ addPaddingFields(O + TySize + BitFieldSize);
+ Cursor = O + TySize + BitFieldSize;
}
+ break;
}
- } else if (ExtraBits >= BitFieldSize) {
- const llvm::Type *Ty = CGT.ConvertType(FD->getType());
- uint64_t TySize = CGT.getTargetData().getABITypeSizeInBits(Ty);
- if (Cursor - CurrentFieldStart + BitFieldSize > TySize) {
- // This is : struct { char a; int b:10; int c:18; };
- // where 'b' shares first field with 'a'. However 'c' needs
- // new llvm field.
-
- //unsigned ExtraBitsInCurrentByte = 8 - (Cursor % 8);
- //Cursor = Cursor + ExtraBitsInCurrentByte;
- //ExtraBits = 0;
- Cursor = llvmSize;
- unsigned EndOfCurrentType = CurrentFieldStart + TySize;
- addPaddingFields(EndOfCurrentType);
- addLLVMField(Ty, TySize, FD, 0, BitFieldSize);
- } else {
- // Reuse existing llvm field
- ExtraBits = ExtraBits - BitFieldSize;
- CGT.addFieldInfo(FD, FieldNo, Cursor - CurrentFieldStart, ExtraBits);
- Cursor = Cursor + BitFieldSize;
- ++FieldNo;
- }
- } 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().getABITypeSizeInBits(Ty);
- assert (CGT.getTargetData().getABITypeSizeInBits(PrevTy) >= TySize
- && "Unable to handle bit field");
-
- // 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);
}
+
+ assert(FoundPrevField &&
+ "Unable to find a place for bitfield in struct layout");
}
Modified: cfe/trunk/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.h?rev=46230&r1=46229&r2=46230&view=diff
==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.h Mon Jan 21 16:54:57 2008
@@ -78,18 +78,11 @@
class BitFieldInfo {
public:
- explicit BitFieldInfo(unsigned N, unsigned B, unsigned E)
- : No(N), Begin(B), End(E) {}
- private:
- // No - llvm struct field number that is used to
- // access this field. It may be not same as struct field number.
- // 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 No;
+ explicit BitFieldInfo(unsigned B, unsigned S)
+ : Begin(B), Size(S) {}
+
unsigned Begin;
- unsigned End;
+ unsigned Size;
};
llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields;
@@ -140,8 +133,13 @@
std::vector<const llvm::Type*> &ArgTys);
/// addFieldInfo - Assign field number to field FD.
- void addFieldInfo(const FieldDecl *FD, unsigned No, unsigned Begin,
- unsigned End);
+ void addFieldInfo(const FieldDecl *FD, unsigned No);
+
+ /// addBitFieldInfo - Assign a start bit and a size to field FD.
+ void addBitFieldInfo(const FieldDecl *FD, unsigned Begin, unsigned Size);
+
+ /// getBitFieldInfo - Return the BitFieldInfo that corresponds to the field FD.
+ BitFieldInfo getBitFieldInfo(const FieldDecl *FD);
};
} // 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=46230&r1=46229&r2=46230&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/struct-x86-darwin.c (original)
+++ cfe/trunk/test/CodeGen/struct-x86-darwin.c Mon Jan 21 16:54:57 2008
@@ -6,6 +6,8 @@
// RUN: grep "STestB2 = type { i8, i8, i8 }" %t1 &&
// RUN: grep "STestB3 = type { i8, i8 }" %t1 &&
// RUN: grep "STestB4 = type { i8, i8, i8, i8 }" %t1
+// RUN: grep "STestB5 = type { i8, i8, i8, i8, i8, i8 }" %t1
+// RUN: grep "STestB6 = 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
@@ -19,6 +21,7 @@
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 STestB5 {char a; short b:10; char c; } stb5;
+struct STestB6 {int a:1; char b; int c:13 } stb6;
-//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