diff options
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 75 |
1 files changed, 68 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 99406715cbf..e32db8c56df 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3402,11 +3402,67 @@ static QualType getFixedSizeElementType(const ASTContext &ctx, return eltType; } +/// Given an array base, check whether its member access belongs to a record +/// with preserve_access_index attribute or not. +static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) { + if (!ArrayBase || !CGF.getDebugInfo()) + return false; + + const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(ArrayBase); + if (!ImplicitCast) + return false; + + // Only support base as either a MemberExpr or DeclRefExpr. + // DeclRefExpr to cover cases like: + // struct s { int a; int b[10]; }; + // struct s *p; + // p[1].a + // p[1] will generate a DeclRefExpr and p[1].a is a MemberExpr. + // p->b[5] is a MemberExpr example. + const Expr *E = ImplicitCast->getSubExpr(); + const auto *MemberCast = dyn_cast<MemberExpr>(E); + if (MemberCast) + return MemberCast->getMemberDecl()->hasAttr<BPFPreserveAccessIndexAttr>(); + + const auto *DeclRefCast = dyn_cast<DeclRefExpr>(E); + if (DeclRefCast) { + const VarDecl *VarDef = dyn_cast<VarDecl>(DeclRefCast->getDecl()); + if (!VarDef) + return false; + + const auto *PtrT = dyn_cast<PointerType>(VarDef->getType().getTypePtr()); + if (!PtrT) + return false; + const auto *PointeeT = PtrT->getPointeeType().getTypePtr(); + + // Peel off typedef's + const auto *TypedefT = dyn_cast<TypedefType>(PointeeT); + while (TypedefT) { + PointeeT = TypedefT->desugar().getTypePtr(); + TypedefT = dyn_cast<TypedefType>(PointeeT); + } + + // Not a typedef any more, it should be an elaborated type. + const auto ElaborateT = dyn_cast<ElaboratedType>(PointeeT); + if (!ElaborateT) + return false; + + const auto *RecT = dyn_cast<RecordType>(ElaborateT->desugar().getTypePtr()); + if (!RecT) + return false; + + return RecT->getDecl()->hasAttr<BPFPreserveAccessIndexAttr>(); + } + + return false; +} + static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, ArrayRef<llvm::Value *> indices, QualType eltType, bool inbounds, bool signedIndices, SourceLocation loc, QualType *arrayType = nullptr, + const Expr *Base = nullptr, const llvm::Twine &name = "arrayidx") { // All the indices except that last must be zero. #ifndef NDEBUG @@ -3428,7 +3484,8 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, llvm::Value *eltPtr; auto LastIndex = dyn_cast<llvm::ConstantInt>(indices.back()); - if (!CGF.IsInPreservedAIRegion || !LastIndex) { + if (!LastIndex || + (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { eltPtr = emitArraySubscriptGEP( CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name); @@ -3582,7 +3639,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, Addr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, - E->getExprLoc(), &arrayType); + E->getExprLoc(), &arrayType, E->getBase()); EltBaseInfo = ArrayLV.getBaseInfo(); EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); } else { @@ -3592,7 +3649,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, QualType ptrType = E->getBase()->getType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc(), &ptrType); + SignedIndices, E->getExprLoc(), &ptrType, + E->getBase()); } LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); @@ -3993,12 +4051,13 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const CGBitFieldInfo &Info = RL.getBitFieldInfo(field); Address Addr = base.getAddress(); unsigned Idx = RL.getLLVMFieldNo(field); - if (!IsInPreservedAIRegion) { + const RecordDecl *rec = field->getParent(); + if (!IsInPreservedAIRegion && + (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) { if (Idx != 0) // For structs, we GEP to the field that the record layout suggests. Addr = Builder.CreateStructGEP(Addr, Idx, field->getName()); } else { - const RecordDecl *rec = field->getParent(); llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( getContext().getRecordType(rec), rec->getLocation()); Addr = Builder.CreatePreserveStructAccessIndex(Addr, Idx, @@ -4081,7 +4140,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()), addr.getAlignment()); - if (IsInPreservedAIRegion) { + if (IsInPreservedAIRegion || + (getDebugInfo() && rec->hasAttr<BPFPreserveAccessIndexAttr>())) { // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( getContext().getRecordType(rec), rec->getLocation()); @@ -4095,7 +4155,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, addr = Builder.CreateElementBitCast( addr, CGM.getTypes().ConvertTypeForMem(FieldType), field->getName()); } else { - if (!IsInPreservedAIRegion) + if (!IsInPreservedAIRegion && + (!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) // For structs, we GEP to the field that the record layout suggests. addr = emitAddrOfFieldStorage(*this, addr, field); else |