forked from OSchip/llvm-project
Propagate lvalue alignment into bitfields. Per report on cfe-dev.
llvm-svn: 159295
This commit is contained in:
parent
090f345522
commit
c24e2fb1fb
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue