diff options
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/target-builtin-error.o | bin | 0 -> 760 bytes | |||
-rw-r--r-- | clang/test/CodeGenCXX/target-features-error.cpp | 17 |
6 files changed, 37 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7b57f084822..705998d3b21 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3791,6 +3791,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo); const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) + // We can only guarantee that a function is called from the correct + // context/function based on the appropriate target attributes, + // so only check in the case where we have both always_inline and target + // since otherwise we could be making a conditional call after a check for + // the proper cpu features (and it won't cause code generation issues due to + // function based code generation). + if (TargetDecl->hasAttr<AlwaysInlineAttr>() && + TargetDecl->hasAttr<TargetAttr>()) + checkTargetFeatures(Loc, FD); #ifndef NDEBUG if (!(CallInfo.isVariadic() && CallInfo.getArgStruct())) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 17bb9e937bb..c2330e0844b 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4697,17 +4697,6 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee const Decl *TargetDecl = OrigCallee.getAbstractInfo().getCalleeDecl().getDecl(); - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) - // We can only guarantee that a function is called from the correct - // context/function based on the appropriate target attributes, - // so only check in the case where we have both always_inline and target - // since otherwise we could be making a conditional call after a check for - // the proper cpu features (and it won't cause code generation issues due to - // function based code generation). - if (TargetDecl->hasAttr<AlwaysInlineAttr>() && - TargetDecl->hasAttr<TargetAttr>()) - checkTargetFeatures(E, FD); - CalleeType = getContext().getCanonicalType(CalleeType); auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 581bbe5efaf..937648700a2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2179,6 +2179,13 @@ static bool hasRequiredFeatures(const SmallVectorImpl<StringRef> &ReqFeatures, // called function. void CodeGenFunction::checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl) { + return checkTargetFeatures(E->getBeginLoc(), TargetDecl); +} + +// Emits an error if we don't have a valid set of target features for the +// called function. +void CodeGenFunction::checkTargetFeatures(SourceLocation Loc, + const FunctionDecl *TargetDecl) { // Early exit if this is an indirect call. if (!TargetDecl) return; @@ -2203,7 +2210,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E, return; StringRef(FeatureList).split(ReqFeatures, ','); if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) - CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature) + CGM.getDiags().Report(Loc, diag::err_builtin_needs_feature) << TargetDecl->getDeclName() << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); @@ -2229,7 +2236,7 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E, ReqFeatures.push_back(F.getKey()); } if (!hasRequiredFeatures(ReqFeatures, CGM, FD, MissingFeature)) - CGM.getDiags().Report(E->getBeginLoc(), diag::err_function_needs_feature) + CGM.getDiags().Report(Loc, diag::err_function_needs_feature) << FD->getDeclName() << TargetDecl->getDeclName() << MissingFeature; } } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 3516e842ddc..b039d7da1f0 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3605,6 +3605,7 @@ public: CGCallee EmitCallee(const Expr *E); void checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl); + void checkTargetFeatures(SourceLocation Loc, const FunctionDecl *TargetDecl); llvm::CallInst *EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); diff --git a/clang/test/CodeGenCXX/target-builtin-error.o b/clang/test/CodeGenCXX/target-builtin-error.o Binary files differnew file mode 100644 index 00000000000..10da31ebce5 --- /dev/null +++ b/clang/test/CodeGenCXX/target-builtin-error.o diff --git a/clang/test/CodeGenCXX/target-features-error.cpp b/clang/test/CodeGenCXX/target-features-error.cpp new file mode 100644 index 00000000000..44179deaf35 --- /dev/null +++ b/clang/test/CodeGenCXX/target-features-error.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -S -verify -o - + +struct S { + __attribute__((always_inline, target("avx512f"))) + void foo(){} + __attribute__((always_inline, target("avx512f"))) + operator int(){ return 0; } + __attribute__((always_inline, target("avx512f"))) + void operator()(){ } + +}; + +void usage(S & s) { + s.foo(); // expected-error {{'foo' requires target feature 'avx512f'}} + (void)(int)s; // expected-error {{'operator int' requires target feature 'avx512f'}} + s(); // expected-error {{'operator()' requires target feature 'avx512f'}} +} |