Propagate lvalue alignment into bitfields. Per report on cfe-dev.

llvm-svn: 159295
This commit is contained in:
Eli Friedman 2012-06-27 21:19:48 +00:00
parent 090f345522
commit c24e2fb1fb
7 changed files with 46 additions and 32 deletions

View File

@ -1047,6 +1047,9 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
llvm::Value *Res = 0;
for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
CharUnits AccessAlignment = AI.AccessAlignment;
if (!LV.getAlignment().isZero())
AccessAlignment = std::min(AccessAlignment, LV.getAlignment());
// Get the field pointer.
llvm::Value *Ptr = LV.getBitFieldBaseAddr();
@ -1070,8 +1073,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
// Perform the load.
llvm::LoadInst *Load = Builder.CreateLoad(Ptr, LV.isVolatileQualified());
if (!AI.AccessAlignment.isZero())
Load->setAlignment(AI.AccessAlignment.getQuantity());
Load->setAlignment(AccessAlignment.getQuantity());
// Shift out unused low bits and mask out unused high bits.
llvm::Value *Val = Load;
@ -1270,6 +1272,9 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// Iterate over the components, writing each piece to memory.
for (unsigned i = 0, e = Info.getNumComponents(); i != e; ++i) {
const CGBitFieldInfo::AccessInfo &AI = Info.getComponent(i);
CharUnits AccessAlignment = AI.AccessAlignment;
if (!Dst.getAlignment().isZero())
AccessAlignment = std::min(AccessAlignment, Dst.getAlignment());
// Get the field pointer.
llvm::Value *Ptr = Dst.getBitFieldBaseAddr();
@ -1316,8 +1321,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// If necessary, load and OR in bits that are outside of the bit-field.
if (AI.TargetBitWidth != AI.AccessWidth) {
llvm::LoadInst *Load = Builder.CreateLoad(Ptr, Dst.isVolatileQualified());
if (!AI.AccessAlignment.isZero())
Load->setAlignment(AI.AccessAlignment.getQuantity());
Load->setAlignment(AccessAlignment.getQuantity());
// Compute the mask for zeroing the bits that are part of the bit-field.
llvm::APInt InvMask =
@ -1331,8 +1335,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// Write the value.
llvm::StoreInst *Store = Builder.CreateStore(Val, Ptr,
Dst.isVolatileQualified());
if (!AI.AccessAlignment.isZero())
Store->setAlignment(AI.AccessAlignment.getQuantity());
Store->setAlignment(AccessAlignment.getQuantity());
}
}
@ -2084,16 +2087,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
llvm_unreachable("Unhandled member declaration!");
}
LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value *BaseValue,
const FieldDecl *Field,
unsigned CVRQualifiers) {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field);
return LValue::MakeBitfield(BaseValue, Info,
Field->getType().withCVRQualifiers(CVRQualifiers));
}
/// EmitLValueForAnonRecordField - Given that the field is a member of
/// an anonymous struct or union buried inside a record, and given
/// that the base value is a pointer to the enclosing record, derive
@ -2118,9 +2111,15 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
LValue CodeGenFunction::EmitLValueForField(LValue base,
const FieldDecl *field) {
if (field->isBitField())
return EmitLValueForBitfield(base.getAddress(), field,
base.getVRQualifiers());
if (field->isBitField()) {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(field->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(field);
QualType fieldType =
field->getType().withCVRQualifiers(base.getVRQualifiers());
return LValue::MakeBitfield(base.getAddress(), Info, fieldType,
base.getAlignment());
}
const RecordDecl *rec = field->getParent();
QualType type = field->getType();

View File

@ -120,6 +120,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
uint64_t ContainingTypeAlign = CGF.CGM.getContext().getTargetInfo().getCharAlign();
uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset);
uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext());
CharUnits ContainingTypeAlignCharUnits =
CGF.CGM.getContext().toCharUnitsFromBits(ContainingTypeAlign);
// Allocate a new CGBitFieldInfo object to describe this access.
//
@ -132,7 +134,8 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
ContainingTypeSize, ContainingTypeAlign));
return LValue::MakeBitfield(V, *Info,
IvarTy.withCVRQualifiers(CVRQualifiers));
IvarTy.withCVRQualifiers(CVRQualifiers),
ContainingTypeAlignCharUnits);
}
namespace {

View File

@ -64,12 +64,7 @@ public:
/// Bit width of the memory access to perform.
unsigned AccessWidth;
/// The alignment of the memory access, or 0 if the default alignment should
/// be used.
//
// FIXME: Remove use of 0 to encode default, instead have IRgen do the right
// thing when it generates the code, if avoiding align directives is
// desired.
/// The alignment of the memory access, assuming the parent is aligned.
CharUnits AccessAlignment;
/// Offset for the target value.

View File

@ -235,6 +235,8 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
uint64_t FieldSize,
uint64_t ContainingTypeSizeInBits,
unsigned ContainingTypeAlign) {
assert(ContainingTypeAlign && "Expected alignment to be specified");
llvm::Type *Ty = Types.ConvertTypeForMem(FD->getType());
CharUnits TypeSizeInBytes =
CharUnits::fromQuantity(Types.getTargetData().getTypeAllocSize(Ty));

View File

@ -153,7 +153,7 @@ class LValue {
private:
void Initialize(QualType Type, Qualifiers Quals,
CharUnits Alignment = CharUnits(),
CharUnits Alignment,
llvm::MDNode *TBAAInfo = 0) {
this->Type = Type;
this->Quals = Quals;
@ -295,12 +295,12 @@ public:
/// access.
static LValue MakeBitfield(llvm::Value *BaseValue,
const CGBitFieldInfo &Info,
QualType type) {
QualType type, CharUnits Alignment) {
LValue R;
R.LVType = BitField;
R.V = BaseValue;
R.BitFieldInfo = &Info;
R.Initialize(type, type.getQualifiers());
R.Initialize(type, type.getQualifiers(), Alignment);
return R;
}

View File

@ -2166,9 +2166,6 @@ public:
llvm::Value* Base, const ObjCIvarDecl *Ivar,
unsigned CVRQualifiers);
LValue EmitLValueForBitfield(llvm::Value* Base, const FieldDecl* Field,
unsigned CVRQualifiers);
LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
LValue EmitLambdaLValue(const LambdaExpr *E);

View File

@ -45,3 +45,21 @@ void test6() {
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y* @g, i32 0, i32 1) to i8*), i8* %{{.*}}, i64 24, i32 1, i1 false)
g.y = foo();
}
struct XBitfield {
unsigned b1 : 10;
unsigned b2 : 12;
unsigned b3 : 10;
};
struct YBitfield {
char x;
struct XBitfield y;
} __attribute((packed));
struct YBitfield gbitfield;
unsigned test7() {
// CHECK: @test7
// CHECK: load i32* bitcast (%struct.XBitfield* getelementptr inbounds (%struct.YBitfield* @gbitfield, i32 0, i32 1) to i32*), align 1
return gbitfield.y.b2;
}