#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue);
}
+// Returns true if we have a valid set of target features.
+bool CodeGenFunction::checkBuiltinTargetFeatures(
+ const FunctionDecl *TargetDecl) {
+ // Early exit if this is an indirect call.
+ if (!TargetDecl)
+ return true;
+
+ // Get the current enclosing function if it exists.
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) {
+ unsigned BuiltinID = TargetDecl->getBuiltinID();
+ const char *FeatureList =
+ CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
+ if (FeatureList && StringRef(FeatureList) != "") {
+ StringRef TargetCPU = Target.getTargetOpts().CPU;
+ llvm::StringMap<bool> FeatureMap;
+
+ if (const auto *TD = FD->getAttr<TargetAttr>()) {
+ // If we have a TargetAttr build up the feature map based on that.
+ TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
+
+ // Make a copy of the features as passed on the command line into the
+ // beginning of the additional features from the function to override.
+ ParsedAttr.first.insert(
+ ParsedAttr.first.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.begin(),
+ Target.getTargetOpts().FeaturesAsWritten.end());
+
+ if (ParsedAttr.second != "")
+ TargetCPU = ParsedAttr.second;
+
+ // Now populate the feature map, first with the TargetCPU which is
+ // either
+ // the default or a new one from the target attribute string. Then we'll
+ // use the passed in features (FeaturesAsWritten) along with the new
+ // ones
+ // from the attribute.
+ Target.initFeatureMap(FeatureMap, CGM.getDiags(), TargetCPU,
+ ParsedAttr.first);
+ } else {
+ Target.initFeatureMap(FeatureMap, CGM.getDiags(), TargetCPU,
+ Target.getTargetOpts().Features);
+ }
+
+ // 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, ",");
+ for (const auto &Feature : AttrFeatures)
+ if (FeatureMap[Feature])
+ return true;
+ return false;
+ }
+ }
+ return true;
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
unsigned BuiltinID, const CallExpr *E,
ReturnValueSlot ReturnValue) {
if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return emitLibraryCall(*this, FD, E, EmitScalarExpr(E->getCallee()));
+ // Check that a call to a target specific builtin has the correct target
+ // features.
+ // This is down here to avoid non-target specific builtins, however, if
+ // generic builtins start to require generic target features then we
+ // can move this up to the beginning of the function.
+ if (!checkBuiltinTargetFeatures(FD))
+ CGM.getDiags().Report(E->getLocStart(), diag::err_builtin_needs_feature)
+ << FD->getDeclName()
+ << CGM.getContext().BuiltinInfo.getRequiredFeatures(BuiltinID);
+
// See if we have a target specific intrinsic.
const char *Name = getContext().BuiltinInfo.getName(BuiltinID);
Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;