Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -3662,84 +3662,103 @@ return false; } -LValue CodeGenFunction::EmitLValueForField(LValue base, - const FieldDecl *field) { - LValueBaseInfo BaseInfo = base.getBaseInfo(); - AlignmentSource fieldAlignSource = - getFieldAlignmentSource(BaseInfo.getAlignmentSource()); - LValueBaseInfo FieldBaseInfo(fieldAlignSource, BaseInfo.getMayAlias()); +LValue CodeGenFunction::EmitLValueForField(LValue BaseExpr, + const FieldDecl *Field) { + LValueBaseInfo BaseInfo = BaseExpr.getBaseInfo(); - QualType type = field->getType(); - const RecordDecl *rec = field->getParent(); - if (rec->isUnion() || rec->hasAttr() || type->isVectorType()) - FieldBaseInfo.setMayAlias(true); - bool mayAlias = FieldBaseInfo.getMayAlias(); - - if (field->isBitField()) { + if (Field->isBitField()) { const CGRecordLayout &RL = - CGM.getTypes().getCGRecordLayout(field->getParent()); - const CGBitFieldInfo &Info = RL.getBitFieldInfo(field); - Address Addr = base.getAddress(); - unsigned Idx = RL.getLLVMFieldNo(field); + CGM.getTypes().getCGRecordLayout(Field->getParent()); + const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field); + Address Addr = BaseExpr.getAddress(); + unsigned Idx = RL.getLLVMFieldNo(Field); if (Idx != 0) // For structs, we GEP to the field that the record layout suggests. Addr = Builder.CreateStructGEP(Addr, Idx, Info.StorageOffset, - field->getName()); + Field->getName()); // Get the access type. llvm::Type *FieldIntTy = llvm::Type::getIntNTy(getLLVMContext(), Info.StorageSize); if (Addr.getElementType() != FieldIntTy) Addr = Builder.CreateElementBitCast(Addr, FieldIntTy); - QualType fieldType = - field->getType().withCVRQualifiers(base.getVRQualifiers()); - return LValue::MakeBitfield(Addr, Info, fieldType, FieldBaseInfo); + QualType FieldType = + Field->getType().withCVRQualifiers(BaseExpr.getVRQualifiers()); + // TODO: Support TBAA for bit fields. + LValueBaseInfo FieldBaseInfo(BaseInfo.getAlignmentSource(), false); + return LValue::MakeBitfield(Addr, Info, FieldType, FieldBaseInfo); } - Address addr = base.getAddress(); - unsigned cvr = base.getVRQualifiers(); - bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; - if (rec->isUnion()) { - // For unions, there is no pointer adjustment. - assert(!type->isReferenceType() && "union has reference member"); - // TODO: handle path-aware TBAA for union. - TBAAPath = false; + // Fields of may-alias structures are may-alias themselves. + // FIXME: this should get propagated down through anonymous structs + // and unions. + QualType FieldType = Field->getType(); + const RecordDecl *Rec = Field->getParent(); + AlignmentSource BaseAlignSource = BaseInfo.getAlignmentSource(); + LValueBaseInfo FieldBaseInfo(getFieldAlignmentSource(BaseAlignSource), false); + TBAAAccessInfo FieldTBAAInfo; + if (BaseInfo.getMayAlias() || Rec->hasAttr() || + FieldType->isVectorType()) { + FieldBaseInfo.setMayAlias(true); + FieldTBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + } else if (Rec->isUnion()) { + // TODO: Support TBAA for unions. + FieldBaseInfo.setMayAlias(true); + FieldTBAAInfo = CGM.getTBAAMayAliasAccessInfo(); + } else { + // If no base type been assigned for the base access, then try to generate + // one for this base lvalue. + FieldTBAAInfo = BaseExpr.getTBAAInfo(); + if (!FieldTBAAInfo.BaseType) { + FieldTBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(BaseExpr.getType()); + assert(!FieldTBAAInfo.Offset && + "Nonzero offset for an access with no base type!"); + } + + // Adjust offset to be relative to the base type. + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(Field->getParent()); + unsigned CharWidth = getContext().getCharWidth(); + if (FieldTBAAInfo.BaseType) + FieldTBAAInfo.Offset += + Layout.getFieldOffset(Field->getFieldIndex()) / CharWidth; - const auto FieldType = field->getType(); + // Update the final access type. + FieldTBAAInfo.AccessType = CGM.getTBAATypeInfo(FieldType); + } + + Address Addr = BaseExpr.getAddress(); + unsigned CVR = BaseExpr.getVRQualifiers(); + if (Rec->isUnion()) { + // For unions, there is no pointer adjustment. + assert(!FieldType->isReferenceType() && "union has reference member"); if (CGM.getCodeGenOpts().StrictVTablePointers && hasAnyVptr(FieldType, getContext())) // Because unions can easily skip invariant.barriers, we need to add // a barrier every time CXXRecord field with vptr is referenced. - addr = Address(Builder.CreateInvariantGroupBarrier(addr.getPointer()), - addr.getAlignment()); + Addr = Address(Builder.CreateInvariantGroupBarrier(Addr.getPointer()), + Addr.getAlignment()); } else { // For structs, we GEP to the field that the record layout suggests. - addr = emitAddrOfFieldStorage(*this, addr, field); + Addr = emitAddrOfFieldStorage(*this, Addr, Field); // If this is a reference field, load the reference right now. - if (const ReferenceType *refType = type->getAs()) { - llvm::LoadInst *load = Builder.CreateLoad(addr, "ref"); - if (cvr & Qualifiers::Volatile) load->setVolatile(true); - - // Loading the reference will disable path-aware TBAA. - TBAAPath = false; - TBAAAccessInfo TBAAInfo = mayAlias ? CGM.getTBAAMayAliasAccessInfo() : - CGM.getTBAAAccessInfo(type); - CGM.DecorateInstructionWithTBAA(load, TBAAInfo); - - mayAlias = false; - type = refType->getPointeeType(); - - CharUnits alignment = - getNaturalTypeAlignment(type, &FieldBaseInfo, /* TBAAInfo= */ nullptr, - /* forPointeeType= */ true); - FieldBaseInfo.setMayAlias(false); - addr = Address(load, alignment); + if (const ReferenceType *RefType = FieldType->getAs()) { + llvm::LoadInst *load = Builder.CreateLoad(Addr, "ref"); + if (CVR & Qualifiers::Volatile) load->setVolatile(true); + + CGM.DecorateInstructionWithTBAA(load, FieldTBAAInfo); + + FieldType = RefType->getPointeeType(); + CharUnits Align = getNaturalTypeAlignment(FieldType, &FieldBaseInfo, + &FieldTBAAInfo, + /* forPointeeType= */ true); + Addr = Address(load, Align); // Qualifiers on the struct don't apply to the referencee, and // we'll pick up CVR from the actual type later, so reset these // additional qualifiers now. - cvr = 0; + CVR = 0; } } @@ -3747,45 +3766,14 @@ // for both unions and structs. A union needs a bitcast, a struct element // will need a bitcast if the LLVM type laid out doesn't match the desired // type. - addr = Builder.CreateElementBitCast(addr, - CGM.getTypes().ConvertTypeForMem(type), - field->getName()); - - if (field->hasAttr()) - addr = EmitFieldAnnotations(field, addr); - - LValue LV = MakeAddrLValue(addr, type, FieldBaseInfo, - CGM.getTBAAAccessInfo(type)); - LV.getQuals().addCVRQualifiers(cvr); + Addr = Builder.CreateElementBitCast( + Addr, CGM.getTypes().ConvertTypeForMem(FieldType), Field->getName()); - // 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.setTBAAInfo(CGM.getTBAAMayAliasAccessInfo()); - } else if (TBAAPath) { - // If no base type been assigned for the base access, then try to generate - // one for this base lvalue. - TBAAAccessInfo TBAAInfo = base.getTBAAInfo(); - if (!TBAAInfo.BaseType) { - TBAAInfo.BaseType = CGM.getTBAABaseTypeInfo(base.getType()); - assert(!TBAAInfo.Offset && - "Nonzero offset for an access with no base type!"); - } - - // Adjust offset to be relative to the base type. - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(field->getParent()); - unsigned CharWidth = getContext().getCharWidth(); - if (TBAAInfo.BaseType) - TBAAInfo.Offset += - Layout.getFieldOffset(field->getFieldIndex()) / CharWidth; - - // Update the final access type. - TBAAInfo.AccessType = LV.getTBAAInfo().AccessType; + if (Field->hasAttr()) + Addr = EmitFieldAnnotations(Field, Addr); - LV.setTBAAInfo(TBAAInfo); - } + LValue LV = MakeAddrLValue(Addr, FieldType, FieldBaseInfo, FieldTBAAInfo); + LV.getQuals().addCVRQualifiers(CVR); // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -3229,7 +3229,7 @@ llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); - LValue EmitLValueForField(LValue Base, const FieldDecl* Field); + LValue EmitLValueForField(LValue BaseExpr, const FieldDecl *Field); LValue EmitLValueForLambdaField(const FieldDecl *Field); /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that