[mips] Defer validity check for CPU/ABI pairs and improve error message for invalid cases.

Summary:
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'

Reviewers: atanasyan

Subscribers: sdardis, cfe-commits

Differential Revision: http://reviews.llvm.org/D21023

llvm-svn: 272645
This commit is contained in:
Daniel Sanders 2016-06-14 08:58:50 +00:00
parent bae1d89e45
commit 32b2d6b160
4 changed files with 103 additions and 39 deletions

View File

@ -180,6 +180,9 @@ def err_target_unknown_triple : Error<
"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">;

View File

@ -982,6 +982,11 @@ public:
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;

View File

@ -7112,34 +7112,38 @@ public:
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;
}
@ -7189,26 +7193,25 @@ public:
}
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; }
@ -7537,6 +7540,45 @@ public:
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[] = {
@ -8473,5 +8515,8 @@ TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
Target->setSupportedOpenCLOpts();
if (!Target->validateTarget(Diags))
return nullptr;
return Target.release();
}

View File

@ -1,9 +1,18 @@
// 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
@ -11,6 +20,8 @@
// 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 \