summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Maksimovic <stefan.maksimovic@mips.com>2018-08-22 09:26:25 +0000
committerStefan Maksimovic <stefan.maksimovic@mips.com>2018-08-22 09:26:25 +0000
commit7aca6c1a08baf13366cb7c772e8838f46a6cf2c0 (patch)
tree16daae3c3b9c8cb25d4509c6382f22cf381f8e99
parent30d47f64ecab950181d18655e543bad3520ce72b (diff)
[clang][mips] Set __mips_fpr correctly for -mfpxx
Set __mips_fpr to 0 if o32 ABI is used with either -mfpxx or none of -mfp32, -mfpxx, -mfp64 being specified. Introduce additional checks: -mfpxx is only to be used in conjunction with the o32 ABI. report an error when incompatible options are provided. Formerly no errors were raised when combining n32/n64 ABIs with -mfp32 and -mfpxx. There are other cases when __mips_fpr should be set to 0 that are not covered, ex. using o32 on a mips64 cpu which is valid but not supported in the backend as of yet. Differential Revision: https://reviews.llvm.org/D50557 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@340391 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td3
-rw-r--r--lib/Basic/Targets/Mips.cpp65
-rw-r--r--lib/Basic/Targets/Mips.h14
-rw-r--r--test/Preprocessor/init.c41
4 files changed, 104 insertions, 19 deletions
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index b98b183c9d..c3e2aa8b5c 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -199,6 +199,9 @@ def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
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">;
diff --git a/lib/Basic/Targets/Mips.cpp b/lib/Basic/Targets/Mips.cpp
index cbd5a01c3d..d43edeae60 100644
--- a/lib/Basic/Targets/Mips.cpp
+++ b/lib/Basic/Targets/Mips.cpp
@@ -59,6 +59,16 @@ void MipsTargetInfo::fillValidCPUList(
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
}
+unsigned MipsTargetInfo::getISARev() const {
+ return llvm::StringSwitch<unsigned>(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 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("_MIPS_ISA", "_MIPS_ISA_MIPS64");
}
- const std::string ISARev = llvm::StringSwitch<std::string>(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());
+
if (!ISARev.empty())
Builder.defineMacro("__mips_isa_rev", ISARev);
@@ -129,9 +134,22 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
if (IsSingleFloat)
Builder.defineMacro("__mips_single_float", Twine(1));
- Builder.defineMacro("__mips_fpr", HasFP64 ? Twine(64) : Twine(32));
- Builder.defineMacro("_MIPS_FPSET",
- Twine(32 / (HasFP64 || IsSingleFloat ? 1 : 2)));
+ switch (FPMode) {
+ case FPXX:
+ Builder.defineMacro("__mips_fpr", Twine(0));
+ break;
+ case FP32:
+ Builder.defineMacro("__mips_fpr", Twine(32));
+ break;
+ case FP64:
+ Builder.defineMacro("__mips_fpr", Twine(64));
+ break;
+}
+
+ if (FPMode == FP64 || IsSingleFloat)
+ Builder.defineMacro("_MIPS_FPSET", Twine(32));
+ else
+ Builder.defineMacro("_MIPS_FPSET", Twine(16));
if (IsMips16)
Builder.defineMacro("__mips16", Twine(1));
@@ -189,7 +207,7 @@ void MipsTargetInfo::getTargetDefines(const LangOptions &Opts,
bool MipsTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("mips", true)
- .Case("fp64", HasFP64)
+ .Case("fp64", FPMode == FP64)
.Default(false);
}
@@ -235,5 +253,30 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const {
return false;
}
+ // -fpxx is valid only for the o32 ABI
+ if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) {
+ Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32";
+ return false;
+ }
+
+ // -mfp32 and n32/n64 ABIs are incompatible
+ if (FPMode != FP64 && FPMode != FPXX && !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 (FPMode != FP64 && FPMode != FPXX && (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 (FPMode == FP64 && (CPU == "mips1" || CPU == "mips2" ||
+ getISARev() < 2) && ABI == "o32") {
+ Diags.Report(diag::err_mips_fp64_req) << "-mfp64";
+ return false;
+ }
+
return true;
}
diff --git a/lib/Basic/Targets/Mips.h b/lib/Basic/Targets/Mips.h
index 11e9ac9144..fd1db5aa23 100644
--- a/lib/Basic/Targets/Mips.h
+++ b/lib/Basic/Targets/Mips.h
@@ -57,7 +57,7 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
bool UseIndirectJumpHazard;
protected:
- bool HasFP64;
+ enum FPModeEnum { FPXX, FP32, FP64 } FPMode;
std::string ABI;
public:
@@ -66,7 +66,7 @@ public:
IsNan2008(false), IsAbs2008(false), IsSingleFloat(false),
IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat),
DspRev(NoDSP), HasMSA(false), DisableMadd4(false),
- UseIndirectJumpHazard(false), HasFP64(false) {
+ UseIndirectJumpHazard(false), FPMode(FPXX) {
TheCXXABI.set(TargetCXXABI::GenericMIPS);
setABI(getTriple().isMIPS32() ? "o32" : "n64");
@@ -181,6 +181,8 @@ public:
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
}
+ unsigned getISARev() const;
+
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
@@ -305,7 +307,7 @@ public:
IsSingleFloat = false;
FloatABI = HardFloat;
DspRev = NoDSP;
- HasFP64 = isFP64Default();
+ FPMode = isFP64Default() ? FP64 : FPXX;
for (const auto &Feature : Features) {
if (Feature == "+single-float")
@@ -325,9 +327,11 @@ public:
else if (Feature == "+nomadd4")
DisableMadd4 = true;
else if (Feature == "+fp64")
- HasFP64 = true;
+ FPMode = FP64;
else if (Feature == "-fp64")
- HasFP64 = false;
+ FPMode = FP32;
+ else if (Feature == "+fpxx")
+ FPMode = FPXX;
else if (Feature == "+nan2008")
IsNan2008 = true;
else if (Feature == "-nan2008")
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index e61caecbb2..6e15bdc30a 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -3442,7 +3442,7 @@
// MIPS32BE:#define __mips 32
// MIPS32BE:#define __mips__ 1
// MIPS32BE:#define __mips_abicalls 1
-// MIPS32BE:#define __mips_fpr 32
+// MIPS32BE:#define __mips_fpr 0
// MIPS32BE:#define __mips_hard_float 1
// MIPS32BE:#define __mips_o32 1
// MIPS32BE:#define _mips 1
@@ -3649,7 +3649,7 @@
// MIPS32EL:#define __mips 32
// MIPS32EL:#define __mips__ 1
// MIPS32EL:#define __mips_abicalls 1
-// MIPS32EL:#define __mips_fpr 32
+// MIPS32EL:#define __mips_fpr 0
// MIPS32EL:#define __mips_hard_float 1
// MIPS32EL:#define __mips_o32 1
// MIPS32EL:#define _mips 1
@@ -4900,6 +4900,41 @@
// RUN: | FileCheck -match-full-lines -check-prefix NOMIPS-ABS2008 %s
// NOMIPS-ABS2008-NOT:#define __mips_abs2008 1
//
+// RUN: %clang_cc1 \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-NOFP %s
+// MIPS32-NOFP:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFPXX %s
+// MIPS32-MFPXX:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 -target-cpu mips32r6 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS32R6-MFPXX %s
+// MIPS32R6-MFPXX:#define __mips_fpr 0
+//
+// RUN: %clang_cc1 \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-NOFP %s
+// MIPS64-NOFP:#define __mips_fpr 64
+//
+// RUN: not %clang_cc1 -target-feature -fp64 \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFP32 %s
+// MIPS64-MFP32:error: option '-mfpxx' cannot be specified with 'mips64r2'
+//
+// RUN: not %clang_cc1 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFPXX %s
+// MIPS64-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
+//
+// RUN: not %clang_cc1 -target-cpu mips64r6 -target-feature +fpxx \
+// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
+// RUN: | FileCheck -match-full-lines -check-prefix MIPS64R6-MFPXX %s
+// MIPS64R6-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
+//
// RUN: %clang_cc1 -target-feature -fp64 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32 %s
@@ -4916,7 +4951,7 @@
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32SF %s
// MIPS32-MFP32SF:#define _MIPS_FPSET 32
-// MIPS32-MFP32SF:#define __mips_fpr 32
+// MIPS32-MFP32SF:#define __mips_fpr 0
//
// RUN: %clang_cc1 -target-feature +fp64 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \