diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2013-08-21 21:59:03 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2013-08-21 21:59:03 +0000 |
commit | eb26547177b9c5d1330100a7c988e8a792c07eba (patch) | |
tree | b1c465f4cd459ed09bad95ded37731fc4b8ce715 /clang/lib/Basic | |
parent | 3cba495abca1f41a17f4092c5cf3f01374271adc (diff) | |
download | bcm5719-llvm-eb26547177b9c5d1330100a7c988e8a792c07eba.tar.gz bcm5719-llvm-eb26547177b9c5d1330100a7c988e8a792c07eba.zip |
Move -mfpmath handling to -cc1 and implement it for x86.
The original idea was to implement it all on the driver, but to do that the
driver needs to know the sse level and to do that it has to know the default
features of a cpu.
Benjamin Kramer pointed out that if one day we decide to implement support for
' __attribute__ ((__target__ ("arch=core2")))', then the frontend needs to
keep its knowledge of default features of a cpu.
To avoid duplicating which part of clang handles default cpu features,
it is probably better to handle -mfpmath in the frontend.
For ARM this patch is just a small improvement. Instead of a cpu list, we
check if neon is enabled, which allows us to reject things like
-mcpu=cortex-a9 -mfpu=vfp -mfpmath=neon
For X86, since LLVM doesn't support an independent ssefp feature, we just
make sure the selected -mfpmath matches the sse level.
llvm-svn: 188939
Diffstat (limited to 'clang/lib/Basic')
-rw-r--r-- | clang/lib/Basic/Targets.cpp | 96 |
1 files changed, 87 insertions, 9 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(); } |