summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp75
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
OpenPOWER on IntegriCloud