mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 09:26:06 +00:00
Pretty up the emission of field l-values and use volatile and TBAA when
loading references as part of that. Use 'char' TBAA when accessing (immediate!) fields of a may_alias struct; fixes PR9307. llvm-svn: 126540
This commit is contained in:
parent
bebede4d33
commit
53fcbd2718
@ -1610,39 +1610,67 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
|
||||
}
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitLValueForField(llvm::Value *BaseValue,
|
||||
const FieldDecl *Field,
|
||||
unsigned CVRQualifiers) {
|
||||
if (Field->isBitField())
|
||||
return EmitLValueForBitfield(BaseValue, Field, CVRQualifiers);
|
||||
LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
|
||||
const FieldDecl *field,
|
||||
unsigned cvr) {
|
||||
if (field->isBitField())
|
||||
return EmitLValueForBitfield(baseAddr, field, cvr);
|
||||
|
||||
const CGRecordLayout &RL =
|
||||
CGM.getTypes().getCGRecordLayout(Field->getParent());
|
||||
unsigned idx = RL.getLLVMFieldNo(Field);
|
||||
llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp");
|
||||
const RecordDecl *rec = field->getParent();
|
||||
QualType type = field->getType();
|
||||
|
||||
// Match union field type.
|
||||
if (Field->getParent()->isUnion()) {
|
||||
const llvm::Type *FieldTy =
|
||||
CGM.getTypes().ConvertTypeForMem(Field->getType());
|
||||
const llvm::PointerType *BaseTy =
|
||||
cast<llvm::PointerType>(BaseValue->getType());
|
||||
unsigned AS = BaseTy->getAddressSpace();
|
||||
V = Builder.CreateBitCast(V,
|
||||
llvm::PointerType::get(FieldTy, AS),
|
||||
"tmp");
|
||||
bool mayAlias = rec->hasAttr<MayAliasAttr>();
|
||||
|
||||
llvm::Value *addr;
|
||||
if (rec->isUnion()) {
|
||||
// For unions, we just cast to the appropriate type.
|
||||
assert(!type->isReferenceType() && "union has reference member");
|
||||
|
||||
const llvm::Type *llvmType = CGM.getTypes().ConvertTypeForMem(type);
|
||||
unsigned AS =
|
||||
cast<llvm::PointerType>(baseAddr->getType())->getAddressSpace();
|
||||
addr = Builder.CreateBitCast(baseAddr, llvmType->getPointerTo(AS),
|
||||
field->getName());
|
||||
} else {
|
||||
// For structs, we GEP to the field that the record layout suggests.
|
||||
unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field);
|
||||
addr = Builder.CreateStructGEP(baseAddr, idx, field->getName());
|
||||
|
||||
// If this is a reference field, load the reference right now.
|
||||
if (const ReferenceType *refType = type->getAs<ReferenceType>()) {
|
||||
llvm::LoadInst *load = Builder.CreateLoad(addr, "ref");
|
||||
if (cvr & Qualifiers::Volatile) load->setVolatile(true);
|
||||
|
||||
if (CGM.shouldUseTBAA()) {
|
||||
llvm::MDNode *tbaa;
|
||||
if (mayAlias)
|
||||
tbaa = CGM.getTBAAInfo(getContext().CharTy);
|
||||
else
|
||||
tbaa = CGM.getTBAAInfo(type);
|
||||
CGM.DecorateInstruction(load, tbaa);
|
||||
}
|
||||
|
||||
addr = load;
|
||||
mayAlias = false;
|
||||
type = refType->getPointeeType();
|
||||
cvr = 0; // qualifiers don't recursively apply to referencee
|
||||
}
|
||||
}
|
||||
if (Field->getType()->isReferenceType())
|
||||
V = Builder.CreateLoad(V, "tmp");
|
||||
|
||||
unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
|
||||
LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
|
||||
LV.getQuals().addCVRQualifiers(CVRQualifiers);
|
||||
unsigned alignment = getContext().getDeclAlign(field).getQuantity();
|
||||
LValue LV = MakeAddrLValue(addr, type, alignment);
|
||||
LV.getQuals().addCVRQualifiers(cvr);
|
||||
|
||||
// __weak attribute on a field is ignored.
|
||||
if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
|
||||
LV.getQuals().removeObjCGCAttr();
|
||||
|
||||
|
||||
// Fields of may_alias structs act like 'char' for TBAA purposes.
|
||||
// FIXME: this should get propagated down through anonymous structs
|
||||
// and unions.
|
||||
if (mayAlias && LV.getTBAAInfo())
|
||||
LV.setTBAAInfo(CGM.getTBAAInfo(getContext().CharTy));
|
||||
|
||||
return LV;
|
||||
}
|
||||
|
||||
|
@ -295,6 +295,8 @@ public:
|
||||
const TargetCodeGenInfo &getTargetCodeGenInfo();
|
||||
bool isTargetDarwin() const;
|
||||
|
||||
bool shouldUseTBAA() const { return TBAA != 0; }
|
||||
|
||||
llvm::MDNode *getTBAAInfo(QualType QTy);
|
||||
|
||||
static void DecorateInstruction(llvm::Instruction *Inst,
|
||||
|
@ -8,12 +8,21 @@ typedef int __attribute__((may_alias)) aliasing_int;
|
||||
|
||||
void test0(aliasing_int *ai, int *i)
|
||||
{
|
||||
// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1
|
||||
*ai = 0;
|
||||
// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3
|
||||
*i = 1;
|
||||
}
|
||||
|
||||
// CHECK: store i32 0, i32* %{{.*}}, !tbaa !1
|
||||
// CHECK: store i32 1, i32* %{{.*}}, !tbaa !3
|
||||
// PR9307
|
||||
struct Test1 { int x; };
|
||||
struct Test1MA { int x; } __attribute__((may_alias));
|
||||
void test1(struct Test1MA *p1, struct Test1 *p2) {
|
||||
// CHECK: store i32 2, i32* {{%.*}}, !tbaa !1
|
||||
p1->x = 2;
|
||||
// CHECK: store i32 3, i32* {{%.*}}, !tbaa !3
|
||||
p2->x = 3;
|
||||
}
|
||||
|
||||
// CHECK: !0 = metadata !{metadata !"any pointer", metadata !1}
|
||||
// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2}
|
||||
|
@ -84,11 +84,11 @@ namespace test3 {
|
||||
// CHECK: define void @_ZN5test31AC2Ev(
|
||||
// CHECK: [[THIS:%.*]] = load
|
||||
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
|
||||
// CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
|
||||
// CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]]
|
||||
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to
|
||||
// CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1
|
||||
// CHECK-NEXT: store i8* null, i8** [[CVALUE]]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user