diff options
author | John McCall <rjmccall@apple.com> | 2011-02-26 08:07:02 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-26 08:07:02 +0000 |
commit | 53fcbd2718222d3c2abef0a39cf7bb73f2d63b8f (patch) | |
tree | 3f1e072918e6e59d4614a9176799273fad17894e /clang/lib/CodeGen/CGExpr.cpp | |
parent | bebede4d336a709d237fdbf20ddd5f2eac51101b (diff) | |
download | bcm5719-llvm-53fcbd2718222d3c2abef0a39cf7bb73f2d63b8f.tar.gz bcm5719-llvm-53fcbd2718222d3c2abef0a39cf7bb73f2d63b8f.zip |
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
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 5d69aad42ff..2abaadff4b6 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/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; } |