yonghong-song updated this revision to Diff 200639. yonghong-song retitled this revision from "[BPF] Preserve debuginfo array/union/struct type name/access index" to "[BPF] Preserve debuginfo array/union/struct type/access index". yonghong-song edited the summary of this revision. yonghong-song added a comment.
add clang builtin __builtin_preserve_access_index Repository: rC Clang CHANGES SINCE LAST ACTION https://reviews.llvm.org/D61809/new/ https://reviews.llvm.org/D61809 Files: include/clang/Basic/Builtins.def lib/Basic/Targets/BPF.h lib/CodeGen/CGBuilder.h lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaChecking.cpp test/CodeGen/bpf-offsetreloc.c
Index: test/CodeGen/bpf-offsetreloc.c =================================================================== --- /dev/null +++ test/CodeGen/bpf-offsetreloc.c @@ -0,0 +1,19 @@ +// RUN: %clang -target bpf -emit-llvm -S -g -O2 -o - %s > %t1 +// RUN: grep "llvm.preserve.struct.access.index" %t1 +// RUN: grep "llvm.preserve.array.access.index" %t1 +// RUN: grep "llvm.preserve.union.access.index" %t1 + +struct t { + int i:1; + int j:2; + union { + int a; + int b; + } c[4]; +}; + +#define _(x) (__builtin_preserve_access_index(x)) + +void *test(struct t *arg) { + return _(&arg->c[3].b); +} Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -190,6 +190,16 @@ return false; } +/// Check the number of arguments, and set the result type to +/// the argument type. +static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) { + if (checkArgCount(S, TheCall, 1)) + return true; + + TheCall->setType(TheCall->getArg(0)->getType()); + return false; +} + static bool SemaBuiltinOverflow(Sema &S, CallExpr *TheCall) { if (checkArgCount(S, TheCall, 3)) return true; @@ -1407,6 +1417,10 @@ TheCall->setType(Context.IntTy); break; } + case Builtin::BI__builtin_preserve_access_index: + if (SemaBuiltinPreserveAI(*this, TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_call_with_static_chain: if (SemaBuiltinCallWithStaticChain(*this, TheCall)) return ExprError(); Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -1027,6 +1027,10 @@ store->setAlignment(addr.getAlignment().getQuantity()); } + /// isPreserveDIAccessIndexNeeded - Return true if it is needed to + /// preserve the Debuginfo access index. + bool isPreserveDIAccessIndexNeeded(const Expr *E); + /// An RAII object to record that we're evaluating a statement /// expression. class StmtExprEvaluation { @@ -3545,7 +3549,8 @@ llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); - LValue EmitLValueForField(LValue Base, const FieldDecl* Field); + LValue EmitLValueForField(LValue Base, const FieldDecl* Field, + const Expr *E = nullptr); LValue EmitLValueForLambdaField(const FieldDecl *Field); /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -25,6 +25,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/NSAPI.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" @@ -649,6 +650,52 @@ SanOpts.has(SanitizerKind::Vptr); } +/// The expression E is a candidate for preserving debuginfo access index +/// if it is inside an __builtin_preserve_access_index intrinsic call. +bool CodeGenFunction::isPreserveDIAccessIndexNeeded(const Expr *E) { + if (!E) + return false; + + if (!getDebugInfo()) + return false; + + while (true) { + const auto &Parents = getContext().getParents(*E); + if (Parents.size() != 1) + return false; + + E = Parents[0].get<Expr>(); + if (!E) + return false; + + // Check whether E is a BI__builtin_preserve_access_index + // intrinsic call. + const auto *CE = dyn_cast<CallExpr>(E); + if (CE) { + // Callee must a builtin function. + const Expr *Callee = CE->getCallee()->IgnoreParens(); + auto ICE = dyn_cast<ImplicitCastExpr>(Callee); + if (!ICE) + return false; + if (ICE->getCastKind() != CK_BuiltinFnToFnPtr) + return false; + + auto DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr()); + if (!DRE) + return false; + + if (auto FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { + if (FD->getBuiltinID() == Builtin::BI__builtin_preserve_access_index) + return true; + } + + break; + } + } + + return false; +} + void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *Ptr, QualType Ty, CharUnits Alignment, @@ -3330,7 +3377,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, ArrayRef<llvm::Value *> indices, QualType eltType, bool inbounds, - bool signedIndices, SourceLocation loc, + bool signedIndices, const Expr *E, const llvm::Twine &name = "arrayidx") { // All the indices except that last must be zero. #ifndef NDEBUG @@ -3350,8 +3397,20 @@ CharUnits eltAlign = getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); - llvm::Value *eltPtr = emitArraySubscriptGEP( - CGF, addr.getPointer(), indices, inbounds, signedIndices, loc, name); + llvm::Value *eltPtr; + auto LastIndex = dyn_cast<llvm::ConstantInt>(indices.back()); + if (!CGF.isPreserveDIAccessIndexNeeded(E) || !LastIndex) { + eltPtr = emitArraySubscriptGEP( + CGF, addr.getPointer(), indices, inbounds, signedIndices, + E->getExprLoc(), name); + } else { + // Remember the original array subscript for bpf target + unsigned idx = LastIndex->getZExtValue(); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getPointer(), + indices.size() - 1, + idx); + } + return Address(eltPtr, eltAlign); } @@ -3406,7 +3465,7 @@ QualType EltType = LV.getType()->castAs<VectorType>()->getElementType(); Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true, - SignedIndices, E->getExprLoc()); + SignedIndices, E); return MakeAddrLValue(Addr, EltType, LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, EltType)); } @@ -3437,7 +3496,7 @@ Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc()); + SignedIndices, E); } else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){ // Indexing over an interface, as in "NSString *P; P[4];" @@ -3489,7 +3548,7 @@ Addr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, - E->getExprLoc()); + E); EltBaseInfo = ArrayLV.getBaseInfo(); EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); } else { @@ -3498,7 +3557,7 @@ auto *Idx = EmitIdxAfterBase(/*Promote*/true); Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), !getLangOpts().isSignedOverflowDefined(), - SignedIndices, E->getExprLoc()); + SignedIndices, E); } LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); @@ -3668,7 +3727,7 @@ Idx = Builder.CreateNSWMul(Idx, NumElements); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*SignedIndices=*/false, E); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the // base to be a ArrayToPointerDecay implicit cast. While correct, it is @@ -3688,7 +3747,7 @@ EltPtr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*SignedIndices=*/false, E); BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { @@ -3697,7 +3756,7 @@ IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*SignedIndices=*/false, E); } return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo); @@ -3789,7 +3848,7 @@ NamedDecl *ND = E->getMemberDecl(); if (auto *Field = dyn_cast<FieldDecl>(ND)) { - LValue LV = EmitLValueForField(BaseLV, Field); + LValue LV = EmitLValueForField(BaseLV, Field, E); setObjCGCLValueClass(getContext(), E, LV); return LV; } @@ -3825,6 +3884,19 @@ return CGF.Builder.CreateStructGEP(base, idx, field->getName()); } +static Address emitPreserveStructAccess(CodeGenFunction &CGF, Address base, + const FieldDecl *field) { + const RecordDecl *rec = field->getParent(); + llvm::DIType *DbgInfo = CGF.getDebugInfo()->getOrCreateRecordType( + CGF.getContext().getRecordType(rec), rec->getLocation()); + + unsigned idx = + CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); + + return CGF.Builder.CreatePreserveStructAccessIndex( + base, idx, field->getFieldIndex(), DbgInfo); +} + static bool hasAnyVptr(const QualType Type, const ASTContext &Context) { const auto *RD = Type.getTypePtr()->getAsCXXRecordDecl(); if (!RD) @@ -3845,7 +3917,8 @@ } LValue CodeGenFunction::EmitLValueForField(LValue base, - const FieldDecl *field) { + const FieldDecl *field, + const Expr *E) { LValueBaseInfo BaseInfo = base.getBaseInfo(); if (field->isBitField()) { @@ -3932,9 +4005,24 @@ // a barrier every time CXXRecord field with vptr is referenced. addr = Address(Builder.CreateLaunderInvariantGroup(addr.getPointer()), addr.getAlignment()); + + if (isPreserveDIAccessIndexNeeded(E)) { + // Remember the original union field index + llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( + getContext().getRecordType(rec), rec->getLocation()); + addr = Address( + Builder.CreatePreserveUnionAccessIndex( + addr.getPointer(), field->getFieldIndex(), DbgInfo), + addr.getAlignment()); + } } else { - // For structs, we GEP to the field that the record layout suggests. - addr = emitAddrOfFieldStorage(*this, addr, field); + + if (!isPreserveDIAccessIndexNeeded(E)) + // For structs, we GEP to the field that the record layout suggests. + addr = emitAddrOfFieldStorage(*this, addr, field); + else + // Remember the original struct field index + addr = emitPreserveStructAccess(*this, addr, field); // If this is a reference field, load the reference right now. if (FieldType->isReferenceType()) { Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -1804,6 +1804,11 @@ return RValue::get(Res); } + case Builtin::BI__builtin_preserve_access_index: { + Value *Res = EmitScalarExpr(E->getArg(0)); + return RValue::get(Res); + } + case Builtin::BI__builtin_cimag: case Builtin::BI__builtin_cimagf: case Builtin::BI__builtin_cimagl: Index: lib/CodeGen/CGBuilder.h =================================================================== --- lib/CodeGen/CGBuilder.h +++ lib/CodeGen/CGBuilder.h @@ -298,6 +298,21 @@ return CreateMemSet(Dest.getPointer(), Value, Size, Dest.getAlignment().getQuantity(), IsVolatile); } + + using CGBuilderBaseTy::CreatePreserveStructAccessIndex; + Address CreatePreserveStructAccessIndex(Address Addr, + unsigned Index, + unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); + auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); + + return Address(CreatePreserveStructAccessIndex(Addr.getPointer(), + Index, FieldIndex, DbgInfo), + Addr.getAlignment().alignmentAtOffset(Offset)); + } }; } // end namespace CodeGen Index: lib/Basic/Targets/BPF.h =================================================================== --- lib/Basic/Targets/BPF.h +++ lib/Basic/Targets/BPF.h @@ -46,7 +46,8 @@ MacroBuilder &Builder) const override; bool hasFeature(StringRef Feature) const override { - return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris"; + return Feature == "bpf" || Feature == "alu32" || Feature == "dwarfris" || + Feature == "checkoffsetreloc"; } void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -1445,6 +1445,7 @@ BUILTIN(__builtin_operator_delete, "vv*", "tn") BUILTIN(__builtin_char_memchr, "c*cC*iz", "n") BUILTIN(__builtin_dump_struct, "ivC*v*", "tn") +BUILTIN(__builtin_preserve_access_index, "v*v*", "nc") // Safestack builtins BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits