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:
John McCall 2011-02-26 08:07:02 +00:00
parent bebede4d33
commit 53fcbd2718
4 changed files with 68 additions and 29 deletions

View File

@ -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);
}
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);
addr = load;
mayAlias = false;
type = refType->getPointeeType();
cvr = 0; // qualifiers don't recursively apply to referencee
}
}
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;
}

View File

@ -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,

View File

@ -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}

View File

@ -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]]
}