[RISCV] Move architecture parsing code into its own function

I plan to reuse it in a later patch.

This is almost NFC except a small change in control flow when diagnosing
+d without +f.

Differential Revision: https://reviews.llvm.org/D66002

llvm-svn: 371492
This commit is contained in:
Roger Ferrer Ibanez 2019-09-10 07:47:34 +00:00
parent c190890c29
commit 60f0a6f6ff
1 changed files with 165 additions and 155 deletions

View File

@ -189,24 +189,23 @@ static void getExtensionFeatures(const Driver &D,
} }
} }
void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args, // Returns false if an error is diagnosed.
std::vector<StringRef> &Features) { static bool getArchFeatures(const Driver &D, StringRef MArch,
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { std::vector<StringRef> &Features,
StringRef MArch = A->getValue(); const ArgList &Args) {
// RISC-V ISA strings must be lowercase. // RISC-V ISA strings must be lowercase.
if (llvm::any_of(MArch, [](char c) { return isupper(c); })) { if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
D.Diag(diag::err_drv_invalid_riscv_arch_name) D.Diag(diag::err_drv_invalid_riscv_arch_name)
<< MArch << "string must be lowercase"; << MArch << "string must be lowercase";
return; return false;
} }
// ISA string must begin with rv32 or rv64. // ISA string must begin with rv32 or rv64.
if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) || if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
(MArch.size() < 5)) { (MArch.size() < 5)) {
D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch D.Diag(diag::err_drv_invalid_riscv_arch_name)
<< "string must begin with rv32{i,e,g} or rv64{i,g}"; << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
return; return false;
} }
bool HasRV64 = MArch.startswith("rv64"); bool HasRV64 = MArch.startswith("rv64");
@ -220,9 +219,9 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
// First letter should be 'e', 'i' or 'g'. // First letter should be 'e', 'i' or 'g'.
switch (Baseline) { switch (Baseline) {
default: default:
D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch D.Diag(diag::err_drv_invalid_riscv_arch_name)
<< "first letter should be 'e', 'i' or 'g'"; << MArch << "first letter should be 'e', 'i' or 'g'";
return; return false;
case 'e': { case 'e': {
StringRef Error; StringRef Error;
// Currently LLVM does not support 'e'. // Currently LLVM does not support 'e'.
@ -231,9 +230,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
Error = "standard user-level extension 'e' requires 'rv32'"; Error = "standard user-level extension 'e' requires 'rv32'";
else else
Error = "unsupported standard user-level extension 'e'"; Error = "unsupported standard user-level extension 'e'";
D.Diag(diag::err_drv_invalid_riscv_arch_name) D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error;
<< MArch << Error; return false;
return;
} }
case 'i': case 'i':
break; break;
@ -263,9 +261,9 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
} }
std::string Major, Minor; std::string Major, Minor;
if (!getExtensionVersion(D, MArch, std::string(1, Baseline), if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major,
Exts, Major, Minor)) Minor))
return; return false;
// TODO: Use version number when setting target features // TODO: Use version number when setting target features
// and consume the underscore '_' that might follow. // and consume the underscore '_' that might follow.
@ -290,7 +288,7 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
Error = "invalid standard user-level extension"; Error = "invalid standard user-level extension";
D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
<< MArch << Error << std::string(1, c); << MArch << Error << std::string(1, c);
return; return false;
} }
// Move to next char to prevent repeated letter. // Move to next char to prevent repeated letter.
@ -300,9 +298,8 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
// Skip c. // Skip c.
std::string Next = std::string(std::next(I), E); std::string Next = std::string(std::next(I), E);
std::string Major, Minor; std::string Major, Minor;
if (!getExtensionVersion(D, MArch, std::string(1, c), if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor))
Next, Major, Minor)) return false;
return;
// TODO: Use version number when setting target features // TODO: Use version number when setting target features
// and consume the underscore '_' that might follow. // and consume the underscore '_' that might follow.
@ -315,7 +312,7 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
<< MArch << "unsupported standard user-level extension" << MArch << "unsupported standard user-level extension"
<< std::string(1, c); << std::string(1, c);
return; return false;
case 'm': case 'm':
Features.push_back("+m"); Features.push_back("+m");
break; break;
@ -340,9 +337,11 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
// It's illegal to specify the 'd' (double-precision floating point) // It's illegal to specify the 'd' (double-precision floating point)
// extension without also specifying the 'f' (single precision // extension without also specifying the 'f' (single precision
// floating-point) extension. // floating-point) extension.
if (HasD && !HasF) if (HasD && !HasF) {
D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch D.Diag(diag::err_drv_invalid_riscv_arch_name)
<< "d requires f extension to also be specified"; << MArch << "d requires f extension to also be specified";
return false;
}
// Additional dependency checks. // Additional dependency checks.
// TODO: The 'q' extension requires rv64. // TODO: The 'q' extension requires rv64.
@ -350,6 +349,17 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
// Handle all other types of extensions. // Handle all other types of extensions.
getExtensionFeatures(D, Args, Features, MArch, OtherExts); getExtensionFeatures(D, Args, Features, MArch, OtherExts);
return true;
}
void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
std::vector<StringRef> &Features) {
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
StringRef MArch = A->getValue();
if (!getArchFeatures(D, MArch, Features, Args))
return;
} }
// -mrelax is default, unless -mno-relax is specified. // -mrelax is default, unless -mno-relax is specified.