forked from OSchip/llvm-project
Simplify bitfield codegen.
Fix codegen of struct { short a[3]; int b:15; }. llvm-svn: 46859
This commit is contained in:
parent
16d4bc3dc0
commit
9eff02d9f8
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
unsigned Idx = Cursor / TySize;
|
||||
unsigned BitsLeft = TySize - (Cursor % TySize);
|
||||
|
||||
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);
|
||||
addPaddingFields(BitFieldSize);
|
||||
Cursor = BitFieldSize;
|
||||
return;
|
||||
Cursor = (Idx + 1) * TySize + BitFieldSize;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
assert(FoundPrevField &&
|
||||
"Unable to find a place for bitfield in struct layout");
|
||||
addPaddingFields(Cursor);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue