dsanders created this revision.
dsanders added a reviewer: atanasyan.
dsanders added a subscriber: cfe-commits.
Herald added a subscriber: sdardis.

The validity of ABI/CPU pairs is no longer checked on the fly but is
instead checked after initialization. As a result, invalid CPU/ABI pairs
can be reported as being known but invalid instead of being unknown. For
example, we now emit:
  error: ABI 'n32' is not supported on CPU 'mips32r2'
instead of:
  error: unknown target ABI 'n64'

http://reviews.llvm.org/D21023

Files:
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/TargetInfo.h
  lib/Basic/Targets.cpp
  test/Driver/mips-abi.c

Index: test/Driver/mips-abi.c
===================================================================
--- test/Driver/mips-abi.c
+++ test/Driver/mips-abi.c
@@ -1,16 +1,27 @@
 // Check passing Mips ABI options to the backend.
 //
 // RUN: %clang -target mips-linux-gnu -### -c %s 2>&1 \
-// RUN:   | FileCheck -check-prefix=MIPS-DEF %s
-// MIPS-DEF: "-target-cpu" "mips32r2"
-// MIPS-DEF: "-target-abi" "o32"
+// RUN:   | FileCheck -check-prefix=MIPS32R2-O32 %s
+// RUN: %clang -target mips64-linux-gnu -mips32r2 -mabi=32 -### -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=MIPS32R2-O32 %s
+// MIPS32R2-O32: "-target-cpu" "mips32r2"
+// MIPS32R2-O32: "-target-abi" "o32"
+//
+// FIXME: This is a valid combination of options but we reject it at the moment
+//        because the backend can't handle it.
+// RUN: not %clang -target mips-linux-gnu -c %s \
+// RUN:        -march=mips64r2 -mabi=32 2>&1 \
+// RUN:   | FileCheck -check-prefix=MIPS64R2-O32 %s
+// MIPS64R2-O32: error: ABI 'o32' is not supported on CPU 'mips64r2'
 //
 // RUN: %clang -target mips64-linux-gnu -### -c %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=MIPS64R2-N64 %s
 // RUN: %clang -target mips-img-linux-gnu -mips64r2 -### -c %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=MIPS64R2-N64 %s
 // RUN: %clang -target mips-mti-linux-gnu -mips64r2 -### -c %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=MIPS64R2-N64 %s
+// RUN: %clang -target mips-linux-gnu -mips64r2 -mabi=64 -### -c %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=MIPS64R2-N64 %s
 // MIPS64R2-N64: "-target-cpu" "mips64r2"
 // MIPS64R2-N64: "-target-abi" "n64"
 //
@@ -114,7 +125,7 @@
 // RUN: not %clang -target mips-linux-gnu -c %s \
 // RUN:        -march=p5600 -mabi=64 2>&1 \
 // RUN:   | FileCheck -check-prefix=MIPS-ARCH-P5600-N64 %s
-// MIPS-ARCH-P5600-N64: error: unknown target ABI 'n64'
+// MIPS-ARCH-P5600-N64: error: ABI 'n64' is not supported on CPU 'p5600'
 //
 // RUN: %clang -target mips-linux-gnu -### -c %s \
 // RUN:        -march=mips64 2>&1 \
@@ -143,7 +154,7 @@
 // RUN: not %clang -target mips64-linux-gnu -c %s \
 // RUN:        -march=mips32 2>&1 \
 // RUN:   | FileCheck -check-prefix=MIPS-ARCH-6432 %s
-// MIPS-ARCH-6432: error: unknown target CPU 'mips32'
+// MIPS-ARCH-6432: error: ABI 'n64' is not supported on CPU 'mips32'
 //
 // RUN: not %clang -target mips-linux-gnu -c %s \
 // RUN:        -march=unknown 2>&1 \
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -7074,34 +7074,38 @@
     return IsNan2008;
   }
 
+  bool processorSupportsGPR64() const {
+    return llvm::StringSwitch<bool>(CPU)
+        .Case("mips3", true)
+        .Case("mips4", true)
+        .Case("mips5", true)
+        .Case("mips64", true)
+        .Case("mips64r2", true)
+        .Case("mips64r3", true)
+        .Case("mips64r5", true)
+        .Case("mips64r6", true)
+        .Case("octeon", true)
+        .Default(false);
+    return false;
+  }
+
   StringRef getABI() const override { return ABI; }
   bool setABI(const std::string &Name) override {
-    // FIXME: The Arch component on the triple actually has no bearing on
-    //        whether the ABI is valid or not. It's features of the CPU that
-    //        matters and the size of the GPR's in particular.
-    //        However, we can't allow O32 on 64-bit processors just yet because
-    //        the backend still checks the Arch component instead of the ABI in
-    //        a few places.
-    if (getTriple().getArch() == llvm::Triple::mips ||
-        getTriple().getArch() == llvm::Triple::mipsel) {
-      if (Name == "o32") {
-        setO32ABITypes();
-        ABI = Name;
-        return true;
-      }
+    if (Name == "o32") {
+      setO32ABITypes();
+      ABI = Name;
+      return true;
     }
-    if (getTriple().getArch() == llvm::Triple::mips64 ||
-        getTriple().getArch() == llvm::Triple::mips64el) {
-      if (Name == "n32") {
-        setN32ABITypes();
-        ABI = Name;
-        return true;
-      }
-      if (Name == "n64") {
-        setN64ABITypes();
-        ABI = Name;
-        return true;
-      }
+
+    if (Name == "n32") {
+      setN32ABITypes();
+      ABI = Name;
+      return true;
+    }
+    if (Name == "n64") {
+      setN64ABITypes();
+      ABI = Name;
+      return true;
     }
     return false;
   }
@@ -7151,26 +7155,25 @@
   }
 
   bool setCPU(const std::string &Name) override {
-    bool GPR64Required = ABI == "n32" || ABI == "n64";
     CPU = Name;
     return llvm::StringSwitch<bool>(Name)
-        .Case("mips1", !GPR64Required)
-        .Case("mips2", !GPR64Required)
+        .Case("mips1", true)
+        .Case("mips2", true)
         .Case("mips3", true)
         .Case("mips4", true)
         .Case("mips5", true)
-        .Case("mips32", !GPR64Required)
-        .Case("mips32r2", !GPR64Required)
-        .Case("mips32r3", !GPR64Required)
-        .Case("mips32r5", !GPR64Required)
-        .Case("mips32r6", !GPR64Required)
+        .Case("mips32", true)
+        .Case("mips32r2", true)
+        .Case("mips32r3", true)
+        .Case("mips32r5", true)
+        .Case("mips32r6", true)
         .Case("mips64", true)
         .Case("mips64r2", true)
         .Case("mips64r3", true)
         .Case("mips64r5", true)
         .Case("mips64r6", true)
         .Case("octeon", true)
-        .Case("p5600", !GPR64Required)
+        .Case("p5600", true)
         .Default(false);
   }
   const std::string& getCPU() const { return CPU; }
@@ -7499,6 +7502,45 @@
   bool hasInt128Type() const override {
     return ABI == "n32" || ABI == "n64";
   }
+
+  bool validateTarget(DiagnosticsEngine &Diags) const override {
+    // FIXME: It's valid to use O32 on a 64-bit CPU but the backend can't handle
+    //        this yet. It's better to fail here than on the backend assertion.
+    if (processorSupportsGPR64() && ABI == "o32") {
+      Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+      return false;
+    }
+
+    // 64-bit ABI's require 64-bit CPU's.
+    if (!processorSupportsGPR64() && (ABI == "n32" || ABI == "n64")) {
+      Diags.Report(diag::err_target_unsupported_abi) << ABI << CPU;
+      return false;
+    }
+
+    // FIXME: It's valid to use O32 on a mips64/mips64el triple but the backend
+    //        can't handle this yet. It's better to fail here than on the
+    //        backend assertion.
+    if ((getTriple().getArch() == llvm::Triple::mips64 ||
+         getTriple().getArch() == llvm::Triple::mips64el) &&
+        ABI == "o32") {
+      Diags.Report(diag::err_target_unsupported_abi_for_triple)
+          << ABI << getTriple().str();
+      return false;
+    }
+
+    // FIXME: It's valid to use N32/N64 on a mips/mipsel triple but the backend
+    //        can't handle this yet. It's better to fail here than on the
+    //        backend assertion.
+    if ((getTriple().getArch() == llvm::Triple::mips ||
+         getTriple().getArch() == llvm::Triple::mipsel) &&
+        (ABI == "n32" || ABI == "n64")) {
+      Diags.Report(diag::err_target_unsupported_abi_for_triple)
+          << ABI << getTriple().str();
+      return false;
+    }
+
+    return true;
+  }
 };
 
 const Builtin::Info MipsTargetInfo::BuiltinInfo[] = {
@@ -8435,5 +8477,8 @@
 
   Target->setSupportedOpenCLOpts();
 
+  if (!Target->validateTarget(Diags))
+    return nullptr;
+
   return Target.release();
 }
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -982,6 +982,11 @@
       return getTargetOpts().SupportedOpenCLOptions;
   }
 
+  /// \brief Check the target is valid after it is fully initialized.
+  virtual bool validateTarget(DiagnosticsEngine &Diags) const {
+    return true;
+  }
+
 protected:
   virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
     return PointerWidth;
Index: include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- include/clang/Basic/DiagnosticCommonKinds.td
+++ include/clang/Basic/DiagnosticCommonKinds.td
@@ -180,6 +180,9 @@
   "unknown target triple '%0', please use -triple or -arch">;
 def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
 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_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