Index: include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- include/clang/Basic/DiagnosticCommonKinds.td +++ include/clang/Basic/DiagnosticCommonKinds.td @@ -199,6 +199,9 @@ def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">; def err_target_unsupported_abi_for_triple : Error< "ABI '%0' is not supported for '%1'">; +def err_unsupported_abi_for_opt : Error<"'%0' can only be used with the '%1' ABI">; +def err_mips_fp64_req : Error< + "'%0' can only be used if the target supports the mfhc1 and mthc1 instructions">; def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">; def err_target_unsupported_fpmath : Error< "the '%0' unit is not supported with this instruction set">; Index: lib/Basic/Targets/Mips.h =================================================================== --- lib/Basic/Targets/Mips.h +++ lib/Basic/Targets/Mips.h @@ -58,6 +58,7 @@ protected: bool HasFP64; + bool HasFPXX; std::string ABI; public: @@ -66,7 +67,7 @@ IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), DspRev(NoDSP), HasMSA(false), DisableMadd4(false), - UseIndirectJumpHazard(false), HasFP64(false) { + UseIndirectJumpHazard(false), HasFP64(false), HasFPXX(false) { TheCXXABI.set(TargetCXXABI::GenericMIPS); setABI(getTriple().isMIPS32() ? "o32" : "n64"); @@ -181,6 +182,8 @@ return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } + unsigned getISARev(const std::string& CPU) const; + void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; @@ -328,6 +331,8 @@ HasFP64 = true; else if (Feature == "-fp64") HasFP64 = false; + else if (Feature == "+fpxx") + HasFPXX = true; else if (Feature == "+nan2008") IsNan2008 = true; else if (Feature == "-nan2008") Index: lib/Basic/Targets/Mips.cpp =================================================================== --- lib/Basic/Targets/Mips.cpp +++ lib/Basic/Targets/Mips.cpp @@ -59,6 +59,16 @@ Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames)); } +unsigned MipsTargetInfo::getISARev(const std::string& CPU) const { + return llvm::StringSwitch(getCPU()) + .Cases("mips32", "mips64", 1) + .Cases("mips32r2", "mips64r2", 2) + .Cases("mips32r3", "mips64r3", 3) + .Cases("mips32r5", "mips64r5", 5) + .Cases("mips32r6", "mips64r6", 6) + .Default(0); +} + void MipsTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { if (BigEndian) { @@ -84,13 +94,8 @@ Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64"); } - const std::string ISARev = llvm::StringSwitch(getCPU()) - .Cases("mips32", "mips64", "1") - .Cases("mips32r2", "mips64r2", "2") - .Cases("mips32r3", "mips64r3", "3") - .Cases("mips32r5", "mips64r5", "5") - .Cases("mips32r6", "mips64r6", "6") - .Default(""); + const std::string ISARev = std::to_string(getISARev(getCPU())); + if (!ISARev.empty()) Builder.defineMacro("__mips_isa_rev", ISARev); @@ -129,7 +134,8 @@ if (IsSingleFloat) Builder.defineMacro("__mips_single_float", Twine(1)); - Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32)); + Builder.defineMacro("__mips_fpr", + Twine(HasFPXX ? 0 : (HasFP64 ? 64 : 32))); Builder.defineMacro("_MIPS_FPSET", Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2))); @@ -235,5 +241,29 @@ return false; } + // -fpxx is valid only for the o32 ABI + if (HasFPXX && (ABI == "n32" || ABI == "n64")) { + Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32"; + return false; + } + + // -mfp32 and n32/n64 ABIs are incompatible + if (!HasFP64 && !HasFPXX && !IsSingleFloat && + (ABI == "n32" || ABI == "n64")) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfpxx" << CPU; + return false; + } + // Mips revision 6 and -mfp32 are incompatible + if (!HasFP64 && !HasFPXX && (CPU == "mips32r6" || CPU == "mips64r6")) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfp32" << CPU; + return false; + } + // Option -mfp64 permitted on Mips32 iff revision 2 or higher is present + if (HasFP64 && (CPU == "mips1" || CPU == "mips2" || + getISARev(CPU) < 2) && ABI == "o32") { + Diags.Report(diag::err_mips_fp64_req) << "-mfp64"; + return false; + } + return true; }