diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Targets.cpp | 96 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 33 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 1 |
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)); |