diff options
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 80 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 2 | ||||
-rw-r--r-- | test/CodeGen/may-alias.c | 13 | ||||
-rw-r--r-- | test/CodeGenCXX/anonymous-union-member-initializer.cpp | 4 |
4 files changed, 69 insertions, 30 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 5d69aad42f..2abaadff4b 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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); - - const CGRecordLayout &RL = - CGM.getTypes().getCGRecordLayout(Field->getParent()); - unsigned idx = RL.getLLVMFieldNo(Field); - llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx, "tmp"); +LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr, + const FieldDecl *field, + unsigned cvr) { + if (field->isBitField()) + return EmitLValueForBitfield(baseAddr, field, cvr); + + const RecordDecl *rec = field->getParent(); + QualType type = field->getType(); + + 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); + } - // 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"); + 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; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 1528e4b4a8..73e6ece147 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -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, diff --git a/test/CodeGen/may-alias.c b/test/CodeGen/may-alias.c index f3ea792da3..6171be763d 100644 --- a/test/CodeGen/may-alias.c +++ b/test/CodeGen/may-alias.c @@ -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} diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp index d97a2ae366..85e931b50c 100644 --- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp +++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp @@ -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]] } |