summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Targets.cpp96
-rw-r--r--clang/lib/Driver/Tools.cpp33
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp1
3 files changed, 93 insertions, 37 deletions
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 8674b2a4a40..fd3cfa6eff3 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -1709,6 +1709,12 @@ class X86TargetInfo : public TargetInfo {
//@}
} CPU;
+ enum FPMathKind {
+ FP_Default,
+ FP_SSE,
+ FP_387
+ } FPMath;
+
public:
X86TargetInfo(const llvm::Triple &Triple)
: TargetInfo(Triple), SSELevel(NoSSE), MMX3DNowLevel(NoMMX3DNow),
@@ -1716,7 +1722,7 @@ public:
HasRDRND(false), HasBMI(false), HasBMI2(false), HasPOPCNT(false),
HasRTM(false), HasPRFCHW(false), HasRDSEED(false), HasFMA(false),
HasF16C(false), HasAVX512CD(false), HasAVX512ER(false),
- HasAVX512PF(false), CPU(CK_Generic) {
+ HasAVX512PF(false), CPU(CK_Generic), FPMath(FP_Default) {
BigEndian = false;
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
}
@@ -1763,7 +1769,8 @@ public:
bool Enabled) const;
virtual void getDefaultFeatures(llvm::StringMap<bool> &Features) const;
virtual bool hasFeature(StringRef Feature) const;
- virtual void HandleTargetFeatures(std::vector<std::string> &Features);
+ virtual bool HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags);
virtual const char* getABI() const {
if (getTriple().getArch() == llvm::Triple::x86_64 && SSELevel >= AVX)
return "avx";
@@ -1895,6 +1902,8 @@ public:
llvm_unreachable("Unhandled CPU kind");
}
+ virtual bool setFPMath(StringRef Name);
+
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
// We accept all non-ARM calling conventions
return (CC == CC_X86ThisCall ||
@@ -1910,6 +1919,18 @@ public:
}
};
+bool X86TargetInfo::setFPMath(StringRef Name) {
+ if (Name == "387") {
+ FPMath = FP_387;
+ return true;
+ }
+ if (Name == "sse") {
+ FPMath = FP_SSE;
+ return true;
+ }
+ return false;
+}
+
void X86TargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const {
// FIXME: This *really* should not be here.
@@ -2246,7 +2267,8 @@ void X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
/// HandleTargetOptions - Perform initialization based on the user
/// configured set of features.
-void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
+bool X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
// Remember the maximum enabled sselevel.
for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
// Ignore disabled features.
@@ -2360,12 +2382,23 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
XOPLevel = std::max(XOPLevel, XLevel);
}
+ // LLVM doesn't have a separate switch for fpmath, so only accept it if it
+ // matches the selected sse level.
+ if (FPMath == FP_SSE && SSELevel < SSE1) {
+ Diags.Report(diag::err_target_unsupported_fpmath) << "sse";
+ return false;
+ } else if (FPMath == FP_387 && SSELevel >= SSE1) {
+ Diags.Report(diag::err_target_unsupported_fpmath) << "387";
+ return false;
+ }
+
// Don't tell the backend if we're turning off mmx; it will end up disabling
// SSE, which we don't want.
std::vector<std::string>::iterator it;
it = std::find(Features.begin(), Features.end(), "-mmx");
if (it != Features.end())
Features.erase(it);
+ return true;
}
/// X86TargetInfo::getTargetDefines - Return the set of the X86-specific macro
@@ -3280,12 +3313,14 @@ public:
return Feature == "aarch64" || (Feature == "neon" && FPU == NeonMode);
}
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ virtual bool HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
FPU = FPUMode;
for (unsigned i = 0, e = Features.size(); i != e; ++i) {
if (Features[i] == "+neon")
FPU = NeonMode;
}
+ return true;
}
virtual void getGCCRegNames(const char *const *&Names,
@@ -3421,6 +3456,12 @@ class ARMTargetInfo : public TargetInfo {
std::string ABI, CPU;
+ enum {
+ FP_Default,
+ FP_VFP,
+ FP_Neon
+ } FPMath;
+
unsigned FPU : 4;
unsigned IsAAPCS : 1;
@@ -3465,7 +3506,7 @@ class ARMTargetInfo : public TargetInfo {
public:
ARMTargetInfo(const llvm::Triple &Triple)
: TargetInfo(Triple), ABI("aapcs-linux"), CPU("arm1136j-s"),
- IsAAPCS(true) {
+ FPMath(FP_Default), IsAAPCS(true) {
BigEndian = false;
SizeType = UnsignedInt;
PtrDiffType = SignedInt;
@@ -3571,7 +3612,8 @@ public:
}
}
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ virtual bool HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
FPU = 0;
SoftFloat = SoftFloatABI = false;
for (unsigned i = 0, e = Features.size(); i != e; ++i) {
@@ -3589,6 +3631,16 @@ public:
FPU |= NeonFPU;
}
+ if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
+ Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
+ return false;
+ }
+
+ if (FPMath == FP_Neon)
+ Features.push_back("+neonfp");
+ else if (FPMath == FP_VFP)
+ Features.push_back("-neonfp");
+
// Remove front-end specific options which the backend handles differently.
std::vector<std::string>::iterator it;
it = std::find(Features.begin(), Features.end(), "+soft-float");
@@ -3597,6 +3649,7 @@ public:
it = std::find(Features.begin(), Features.end(), "+soft-float-abi");
if (it != Features.end())
Features.erase(it);
+ return true;
}
virtual bool hasFeature(StringRef Feature) const {
@@ -3649,6 +3702,7 @@ public:
CPU = Name;
return true;
}
+ virtual bool setFPMath(StringRef Name);
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
@@ -3820,6 +3874,18 @@ public:
}
};
+bool ARMTargetInfo::setFPMath(StringRef Name) {
+ if (Name == "neon") {
+ FPMath = FP_Neon;
+ return true;
+ } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
+ Name == "vfp4") {
+ FPMath = FP_VFP;
+ return true;
+ }
+ return false;
+}
+
const char * const ARMTargetInfo::GCCRegNames[] = {
// Integer registers
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -4070,11 +4136,13 @@ class SparcTargetInfo : public TargetInfo {
public:
SparcTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple) {}
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ virtual bool HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
SoftFloat = false;
for (unsigned i = 0, e = Features.size(); i != e; ++i)
if (Features[i] == "+soft-float")
SoftFloat = true;
+ return true;
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
@@ -4642,7 +4710,8 @@ public:
return "";
}
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
+ virtual bool HandleTargetFeatures(std::vector<std::string> &Features,
+ DiagnosticsEngine &Diags) {
IsMips16 = false;
IsMicromips = false;
IsSingleFloat = false;
@@ -4672,6 +4741,8 @@ public:
std::find(Features.begin(), Features.end(), "+soft-float");
if (it != Features.end())
Features.erase(it);
+
+ return true;
}
virtual int getEHDataRegisterNumber(unsigned RegNo) const {
@@ -5488,6 +5559,12 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
return 0;
}
+ // Set the fp math unit.
+ if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) {
+ Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath;
+ return 0;
+ }
+
// Compute the default target features, we need the target to handle this
// because features may have dependencies on one another.
llvm::StringMap<bool> Features;
@@ -5510,7 +5587,8 @@ TargetInfo *TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
ie = Features.end(); it != ie; ++it)
Opts->Features.push_back((it->second ? "+" : "-") + it->first().str());
- Target->HandleTargetFeatures(Opts->Features);
+ if (!Target->HandleTargetFeatures(Opts->Features, Diags))
+ return 0;
return Target.take();
}
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index 746300000f2..25be6b48b66 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -602,30 +602,6 @@ static void getFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
-// Handle -mfpmath=.
-static void getFPMathFeatures(const Driver &D, const Arg *A,
- const ArgList &Args,
- std::vector<const char *> &Features,
- StringRef CPU) {
- StringRef FPMath = A->getValue();
-
- // Set the target features based on the FPMath.
- if (FPMath == "neon") {
- Features.push_back("+neonfp");
-
- if (CPU != "cortex-a5" && CPU != "cortex-a7" &&
- CPU != "cortex-a8" && CPU != "cortex-a9" &&
- CPU != "cortex-a9-mp" && CPU != "cortex-a15")
- D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU;
-
- } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" ||
- FPMath == "vfp4") {
- Features.push_back("-neonfp");
- // FIXME: Add warnings when disabling a feature not present for a given CPU.
- } else
- D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
-}
-
// Select the float ABI as determined by -msoft-float, -mhard-float, and
// -mfloat-abi=.
static StringRef getARMFloatABI(const Driver &D,
@@ -725,10 +701,6 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ))
getFPUFeatures(D, A, Args, Features);
- // Honor -mfpmath=.
- if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ))
- getFPMathFeatures(D, A, Args, Features, getARMTargetCPU(Args, Triple));
-
// Setting -msoft-float effectively disables NEON because of the GCC
// implementation, although the same isn't true of VFP or VFP3.
if (FloatABI == "soft")
@@ -2409,6 +2381,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(CPU));
}
+ if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
+ CmdArgs.push_back("-mfpmath");
+ CmdArgs.push_back(A->getValue());
+ }
+
// Add the target features
getTargetFeatures(D, ETriple, Args, CmdArgs);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 9e606190080..b637938735c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1541,6 +1541,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
+ Opts.FPMath = Args.getLastArgValue(OPT_mfpmath);
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
OpenPOWER on IntegriCloud