smaksimovic created this revision.
smaksimovic added a reviewer: atanasyan.
Herald added subscribers: arichardson, sdardis.

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.


https://reviews.llvm.org/D50557

Files:
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/Basic/Targets/Mips.cpp
  lib/Basic/Targets/Mips.h

Index: lib/Basic/Targets/Mips.h
===================================================================
--- lib/Basic/Targets/Mips.h
+++ lib/Basic/Targets/Mips.h
@@ -58,15 +58,16 @@
 
 protected:
   bool HasFP64;
+  bool HasFPXX;
   std::string ABI;
 
 public:
   MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
       : TargetInfo(Triple), IsMips16(false), IsMicromips(false),
         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<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 @@
     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(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;
 }
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">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to