diff options
author | Eric Christopher <echristo@gmail.com> | 2015-11-12 00:44:12 +0000 |
---|---|---|
committer | Eric Christopher <echristo@gmail.com> | 2015-11-12 00:44:12 +0000 |
commit | 2b2d56f059e75553eac0c1d172ef5b6e4278607f (patch) | |
tree | 3b1284a56de9e24db3c9ca43261af66459acf2cb /clang/lib/CodeGen/CodeGenFunction.cpp | |
parent | fbfd97ed5c514ddf3bb79da0bd2cdb546e56abb1 (diff) | |
download | bcm5719-llvm-2b2d56f059e75553eac0c1d172ef5b6e4278607f.tar.gz bcm5719-llvm-2b2d56f059e75553eac0c1d172ef5b6e4278607f.zip |
Provide a frontend based error for always_inline functions that require
target features that the caller function doesn't provide. This matches
the existing backend failure to inline functions that don't have
matching target features - and diagnoses earlier in the case of
always_inline.
Fix up a few test cases that were, in fact, invalid if you tried
to generate code from the backend with the specified target features
and add a couple of tests to illustrate what's going on.
This should fix PR25246.
llvm-svn: 252834
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 90 |
1 files changed, 65 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 879c1577dbc..8596f97a3b1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1843,7 +1843,8 @@ template void CGBuilderInserter<PreserveNames>::InsertHelper( llvm::BasicBlock::iterator InsertPt) const; #undef PreserveNames -// Returns true if we have a valid set of target features. +// Emits an error if we don't have a valid set of target features for the +// called function. void CodeGenFunction::checkTargetFeatures(const CallExpr *E, const FunctionDecl *TargetDecl) { // Early exit if this is an indirect call. @@ -1856,31 +1857,70 @@ void CodeGenFunction::checkTargetFeatures(const CallExpr *E, if (!FD) return; + // Grab the required features for the call. For a builtin this is listed in + // the td file with the default cpu, for an always_inline function this is any + // listed cpu and any listed features. unsigned BuiltinID = TargetDecl->getBuiltinID(); - const char *FeatureList = - CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); + if (BuiltinID) { + SmallVector<StringRef, 1> ReqFeatures; + const char *FeatureList = + CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); + // Return if the builtin doesn't have any required features. + if (!FeatureList || StringRef(FeatureList) == "") + return; + StringRef(FeatureList).split(ReqFeatures, ","); - if (!FeatureList || StringRef(FeatureList) == "") - return; + // If there aren't any required features listed then go ahead and return. + if (ReqFeatures.empty()) + return; - llvm::StringMap<bool> FeatureMap; - CGM.getFunctionFeatureMap(FeatureMap, FD); - - // If we have at least one of the features in the feature list return - // true, otherwise return false. - SmallVector<StringRef, 1> AttrFeatures; - StringRef(FeatureList).split(AttrFeatures, ","); - if (!std::all_of(AttrFeatures.begin(), AttrFeatures.end(), - [&](StringRef &Feature) { - SmallVector<StringRef, 1> OrFeatures; - Feature.split(OrFeatures, "|"); - return std::any_of(OrFeatures.begin(), OrFeatures.end(), - [&](StringRef &Feature) { - return FeatureMap[Feature]; - }); - })) - CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature) - << TargetDecl->getDeclName() - << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); -} + // Now build up the set of caller features and verify that all the required + // features are there. + llvm::StringMap<bool> CallerFeatureMap; + CGM.getFunctionFeatureMap(CallerFeatureMap, FD); + + // If we have at least one of the features in the feature list return + // true, otherwise return false. + if (!std::all_of( + ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef &Feature) { + SmallVector<StringRef, 1> OrFeatures; + Feature.split(OrFeatures, "|"); + return std::any_of(OrFeatures.begin(), OrFeatures.end(), + [&](StringRef &Feature) { + return CallerFeatureMap.lookup(Feature); + }); + })) + CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature) + << TargetDecl->getDeclName() + << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID); + + } else if (TargetDecl->hasAttr<TargetAttr>()) { + // Get the required features for the callee. + SmallVector<StringRef, 1> ReqFeatures; + llvm::StringMap<bool> CalleeFeatureMap; + CGM.getFunctionFeatureMap(CalleeFeatureMap, TargetDecl); + for (const auto &F : CalleeFeatureMap) + ReqFeatures.push_back(F.getKey()); + // If there aren't any required features listed then go ahead and return. + if (ReqFeatures.empty()) + return; + // Now get the features that the caller provides. + llvm::StringMap<bool> CallerFeatureMap; + CGM.getFunctionFeatureMap(CallerFeatureMap, FD); + + // If we have at least one of the features in the feature list return + // true, otherwise return false. + if (!std::all_of( + ReqFeatures.begin(), ReqFeatures.end(), [&](StringRef &Feature) { + SmallVector<StringRef, 1> OrFeatures; + Feature.split(OrFeatures, "|"); + return std::any_of(OrFeatures.begin(), OrFeatures.end(), + [&](StringRef &Feature) { + return CallerFeatureMap.lookup(Feature); + }); + })) + CGM.getDiags().Report(E->getLocStart(), diag::err_function_needs_feature) + << FD->getDeclName() << TargetDecl->getDeclName(); + } +} |