aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp6
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp39
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h2
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp10
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h7
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp378
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h32
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp43
10 files changed, 506 insertions, 58 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index ad04aedd098e..5114279b4b45 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -69,6 +69,9 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu, StringRef &CPU,
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
+ if (CPU == "native")
+ CPU = llvm::sys::getHostCPUName();
+
if (CPU == "generic") {
Features.push_back("+neon");
} else {
@@ -198,6 +201,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args,
if (Args.hasArg(options::OPT_ffixed_x18))
Features.push_back("+reserve-x18");
+ if (Args.hasArg(options::OPT_ffixed_x20))
+ Features.push_back("+reserve-x20");
+
if (Args.hasArg(options::OPT_mno_neg_immediates))
Features.push_back("+no-neg-immediates");
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 44c8871d0e1f..886d947c586b 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -232,7 +232,7 @@ arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) {
break;
case llvm::Triple::OpenBSD:
- ABI = FloatABI::Soft;
+ ABI = FloatABI::SoftFP;
break;
default:
@@ -391,12 +391,22 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
} else if (HDivArg)
getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features);
- // Setting -msoft-float effectively disables NEON because of the GCC
- // implementation, although the same isn't true of VFP or VFP3.
+ // Setting -msoft-float/-mfloat-abi=soft effectively disables the FPU (GCC
+ // ignores the -mfpu options in this case).
+ // Note that the ABI can also be set implicitly by the target selected.
if (ABI == arm::FloatABI::Soft) {
- Features.push_back("-neon");
- // Also need to explicitly disable features which imply NEON.
- Features.push_back("-crypto");
+ llvm::ARM::getFPUFeatures(llvm::ARM::FK_NONE, Features);
+
+ // Disable hardware FP features which have been enabled.
+ // FIXME: Disabling vfp2 and neon should be enough as all the other
+ // features are dependent on these 2 features in LLVM. However
+ // there is currently no easy way to test this in clang, so for
+ // now just be explicit and disable all known dependent features
+ // as well.
+ for (std::string Feature : {"vfp2", "vfp3", "vfp4", "fp-armv8", "fullfp16",
+ "neon", "crypto", "dotprod"})
+ if (std::find(std::begin(Features), std::end(Features), "+" + Feature) != std::end(Features))
+ Features.push_back(Args.MakeArgString("-" + Feature));
}
// En/disable crc code generation.
@@ -438,7 +448,7 @@ void arm::getARMTargetFeatures(const ToolChain &TC,
if (B->getOption().matches(options::OPT_mlong_calls))
D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args);
}
- Features.push_back("+execute-only");
+ Features.push_back("+execute-only");
}
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
index e72754d5ad53..6d814631d05f 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -20,11 +20,6 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-bool tools::isMipsArch(llvm::Triple::ArchType Arch) {
- return Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel ||
- Arch == llvm::Triple::mips64 || Arch == llvm::Triple::mips64el;
-}
-
// Get CPU and ABI names. They are not independent
// so we have to calculate them together.
void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
@@ -50,6 +45,13 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (Triple.getOS() == llvm::Triple::OpenBSD)
DefMips64CPU = "mips3";
+ // MIPS2 is the default for mips(el)?-unknown-freebsd.
+ // MIPS3 is the default for mips64(el)?-unknown-freebsd.
+ if (Triple.getOS() == llvm::Triple::FreeBSD) {
+ DefMips32CPU = "mips2";
+ DefMips64CPU = "mips3";
+ }
+
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
options::OPT_mcpu_EQ))
CPUName = A->getValue();
@@ -106,11 +108,7 @@ void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
if (ABIName.empty()) {
// Deduce ABI name from the target triple.
- if (Triple.getArch() == llvm::Triple::mips ||
- Triple.getArch() == llvm::Triple::mipsel)
- ABIName = "o32";
- else
- ABIName = "n64";
+ ABIName = Triple.isMIPS32() ? "o32" : "n64";
}
if (CPUName.empty()) {
@@ -214,6 +212,7 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// For case (a) we need to add +noabicalls for N64.
bool IsN64 = ABIName == "64";
+ bool IsPIC = false;
bool NonPIC = false;
Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
@@ -225,6 +224,9 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
NonPIC =
(O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
+ IsPIC =
+ (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
+ O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));
}
bool UseAbiCalls = false;
@@ -234,9 +236,14 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
UseAbiCalls =
!ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
- if (UseAbiCalls && IsN64 && NonPIC) {
- D.Diag(diag::warn_drv_unsupported_abicalls);
- UseAbiCalls = false;
+ if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
+ D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
+ << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
+ NonPIC = false;
+ }
+
+ if (ABICallsArg && !UseAbiCalls && IsPIC) {
+ D.Diag(diag::err_drv_unsupported_noabicalls_pic);
}
if (!UseAbiCalls)
@@ -343,6 +350,12 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
"nomadd4");
AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
+ AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
+ "crc");
+ AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
+ "virt");
+ AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
+ "ginv");
if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
StringRef Val = StringRef(A->getValue());
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
index 7e90488363a5..a232ddbc8f3d 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -21,8 +21,6 @@ namespace clang {
namespace driver {
namespace tools {
-bool isMipsArch(llvm::Triple::ArchType Arch);
-
namespace mips {
typedef enum { Legacy = 1, Std2008 = 2 } IEEE754Standard;
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
index 7c7e1c70e550..f6a95962ace3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp
@@ -106,6 +106,16 @@ void ppc::getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
if (FloatABI == ppc::FloatABI::Soft)
Features.push_back("-hard-float");
+
+ ppc::ReadGOTPtrMode ReadGOT = ppc::getPPCReadGOTPtrMode(D, Args);
+ if (ReadGOT == ppc::ReadGOTPtrMode::SecurePlt)
+ Features.push_back("+secure-plt");
+}
+
+ppc::ReadGOTPtrMode ppc::getPPCReadGOTPtrMode(const Driver &D, const ArgList &Args) {
+ if (Args.getLastArg(options::OPT_msecure_plt))
+ return ppc::ReadGOTPtrMode::SecurePlt;
+ return ppc::ReadGOTPtrMode::Bss;
}
ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
index 7d7c68101b7b..3acee91a2ac3 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.h
@@ -29,10 +29,17 @@ enum class FloatABI {
Hard,
};
+enum class ReadGOTPtrMode {
+ Bss,
+ SecurePlt,
+};
+
FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args);
const char *getPPCAsmModeForCPU(StringRef Name);
+ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D,
+ const llvm::opt::ArgList &Args);
void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
new file mode 100644
index 000000000000..11ce8a1fd769
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -0,0 +1,378 @@
+//===--- RISCV.cpp - RISCV Helpers for Tools --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCV.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/raw_ostream.h"
+#include "ToolChains/CommonArgs.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static StringRef getExtensionTypeDesc(StringRef Ext) {
+ if (Ext.startswith("sx"))
+ return "non-standard supervisor-level extension";
+ if (Ext.startswith("s"))
+ return "standard supervisor-level extension";
+ if (Ext.startswith("x"))
+ return "non-standard user-level extension";
+ return StringRef();
+}
+
+static StringRef getExtensionType(StringRef Ext) {
+ if (Ext.startswith("sx"))
+ return "sx";
+ if (Ext.startswith("s"))
+ return "s";
+ if (Ext.startswith("x"))
+ return "x";
+ return StringRef();
+}
+
+static bool isSupportedExtension(StringRef Ext) {
+ // LLVM does not support "sx", "s" nor "x" extensions.
+ return false;
+}
+
+// Extensions may have a version number, and may be separated by
+// an underscore '_' e.g.: rv32i2_m2.
+// Version number is divided into major and minor version numbers,
+// separated by a 'p'. If the minor version is 0 then 'p0' can be
+// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
+static bool getExtensionVersion(const Driver &D, StringRef MArch,
+ StringRef Ext, StringRef In,
+ std::string &Major, std::string &Minor) {
+ auto I = In.begin();
+ auto E = In.end();
+
+ while (I != E && isDigit(*I))
+ Major.append(1, *I++);
+
+ if (Major.empty())
+ return true;
+
+ if (I != E && *I == 'p') {
+ ++I;
+
+ while (I != E && isDigit(*I))
+ Minor.append(1, *I++);
+
+ // Expected 'p' to be followed by minor version number.
+ if (Minor.empty()) {
+ std::string Error =
+ "minor version number missing after 'p' for extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return false;
+ }
+ }
+
+ // TODO: Handle extensions with version number.
+ std::string Error = "unsupported version number " + Major;
+ if (!Minor.empty())
+ Error += "." + Minor;
+ Error += " for extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
+
+ return false;
+}
+
+// Handle other types of extensions other than the standard
+// general purpose and standard user-level extensions.
+// Parse the ISA string containing non-standard user-level
+// extensions, standard supervisor-level extensions and
+// non-standard supervisor-level extensions.
+// These extensions start with 'x', 's', 'sx' prefixes, follow a
+// canonical order, might have a version number (major, minor)
+// and are separated by a single underscore '_'.
+// Set the hardware features for the extensions that are supported.
+static void getExtensionFeatures(const Driver &D,
+ const ArgList &Args,
+ std::vector<StringRef> &Features,
+ StringRef &MArch, StringRef &Exts) {
+ if (Exts.empty())
+ return;
+
+ // Multi-letter extensions are seperated by a single underscore
+ // as described in RISC-V User-Level ISA V2.2.
+ SmallVector<StringRef, 8> Split;
+ Exts.split(Split, StringRef("_"));
+
+ SmallVector<StringRef, 3> Prefix;
+ Prefix.push_back("x");
+ Prefix.push_back("s");
+ Prefix.push_back("sx");
+ auto I = Prefix.begin();
+ auto E = Prefix.end();
+
+ SmallVector<StringRef, 8> AllExts;
+
+ for (StringRef Ext : Split) {
+
+ if (Ext.empty()) {
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "extension name missing after separator '_'";
+ return;
+ }
+
+ StringRef Type = getExtensionType(Ext);
+ StringRef Name(Ext.substr(Type.size()));
+ StringRef Desc = getExtensionTypeDesc(Ext);
+
+ if (Type.empty()) {
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << "invalid extension prefix" << Ext;
+ return;
+ }
+
+ // Check ISA extensions are specified in the canonical order.
+ while (I != E && *I != Type)
+ ++I;
+
+ if (I == E) {
+ std::string Error = Desc;
+ Error += " not given in canonical order";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ // The order is OK, do not advance I to the next prefix
+ // to allow repeated extension type, e.g.: rv32ixabc_xdef.
+
+ if (Name.empty()) {
+ std::string Error = Desc;
+ Error += " name missing after";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ std::string Major, Minor;
+ auto Pos = Name.find_if(isDigit);
+ if (Pos != StringRef::npos) {
+ auto Next = Name.substr(Pos);
+ Name = Name.substr(0, Pos);
+ if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
+ return;
+ }
+
+ // Check if duplicated extension.
+ if (std::find(AllExts.begin(), AllExts.end(), Ext) != AllExts.end()) {
+ std::string Error = "duplicated ";
+ Error += Desc;
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+
+ // Extension format is correct, keep parsing the extensions.
+ // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
+ AllExts.push_back(Ext);
+ }
+
+ // Set target features.
+ // TODO: Hardware features to be handled in Support/TargetParser.cpp.
+ // TODO: Use version number when setting target features.
+ for (auto Ext : AllExts) {
+ if (!isSupportedExtension(Ext)) {
+ StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
+ std::string Error = "unsupported ";
+ Error += Desc;
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << Ext;
+ return;
+ }
+ Features.push_back(Args.MakeArgString("+" + Ext));
+ }
+}
+
+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();
+
+ // RISC-V ISA strings must be lowercase.
+ if (std::any_of(std::begin(MArch), std::end(MArch),
+ [](char c) { return isupper(c); })) {
+
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "string must be lowercase";
+ return;
+ }
+
+ // ISA string must begin with rv32 or rv64.
+ if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
+ (MArch.size() < 5)) {
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "string must begin with rv32{i,e,g} or rv64{i,g}";
+ return;
+ }
+
+ bool HasRV64 = MArch.startswith("rv64") ? true : false;
+
+ // The canonical order specified in ISA manual.
+ // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
+ StringRef StdExts = "mafdqlcbjtpvn";
+ bool HasF = false, HasD = false;
+ char Baseline = MArch[4];
+
+ // First letter should be 'e', 'i' or 'g'.
+ switch (Baseline) {
+ default:
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "first letter should be 'e', 'i' or 'g'";
+ return;
+ case 'e': {
+ StringRef Error;
+ // Currently LLVM does not support 'e'.
+ // Extension 'e' is not allowed in rv64.
+ if (HasRV64)
+ Error = "standard user-level extension 'e' requires 'rv32'";
+ else
+ Error = "unsupported standard user-level extension 'e'";
+ D.Diag(diag::err_drv_invalid_riscv_arch_name)
+ << MArch << Error;
+ return;
+ }
+ case 'i':
+ break;
+ case 'g':
+ // g = imafd
+ StdExts = StdExts.drop_front(4);
+ Features.push_back("+m");
+ Features.push_back("+a");
+ Features.push_back("+f");
+ Features.push_back("+d");
+ HasF = true;
+ HasD = true;
+ break;
+ }
+
+ // Skip rvxxx
+ StringRef Exts = MArch.substr(5);
+
+ // Remove non-standard extensions and supervisor-level extensions.
+ // They have 'x', 's', 'sx' prefixes. Parse them at the end.
+ // Find the very first occurrence of 's' or 'x'.
+ StringRef OtherExts;
+ size_t Pos = Exts.find_first_of("sx");
+ if (Pos != StringRef::npos) {
+ OtherExts = Exts.substr(Pos);
+ Exts = Exts.substr(0, Pos);
+ }
+
+ std::string Major, Minor;
+ if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
+ Exts, Major, Minor))
+ return;
+
+ // TODO: Use version number when setting target features
+ // and consume the underscore '_' that might follow.
+
+ auto StdExtsItr = StdExts.begin();
+ auto StdExtsEnd = StdExts.end();
+
+ for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
+ char c = *I;
+
+ // Check ISA extensions are specified in the canonical order.
+ while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
+ ++StdExtsItr;
+
+ if (StdExtsItr == StdExtsEnd) {
+ // Either c contains a valid extension but it was not given in
+ // canonical order or it is an invalid extension.
+ StringRef Error;
+ if (StdExts.contains(c))
+ Error = "standard user-level extension not given in canonical order";
+ else
+ Error = "invalid standard user-level extension";
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << Error << std::string(1, c);
+ return;
+ }
+
+ // Move to next char to prevent repeated letter.
+ ++StdExtsItr;
+
+ if (std::next(I) != E) {
+ // Skip c.
+ std::string Next = std::string(std::next(I), E);
+ std::string Major, Minor;
+ if (!getExtensionVersion(D, MArch, std::string(1, c),
+ Next, Major, Minor))
+ return;
+
+ // TODO: Use version number when setting target features
+ // and consume the underscore '_' that might follow.
+ }
+
+ // The order is OK, then push it into features.
+ switch (c) {
+ default:
+ // Currently LLVM supports only "mafdc".
+ D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+ << MArch << "unsupported standard user-level extension"
+ << std::string(1, c);
+ return;
+ case 'm':
+ Features.push_back("+m");
+ break;
+ case 'a':
+ Features.push_back("+a");
+ break;
+ case 'f':
+ Features.push_back("+f");
+ HasF = true;
+ break;
+ case 'd':
+ Features.push_back("+d");
+ HasD = true;
+ break;
+ case 'c':
+ Features.push_back("+c");
+ break;
+ }
+ }
+
+ // Dependency check.
+ // It's illegal to specify the 'd' (double-precision floating point)
+ // extension without also specifying the 'f' (single precision
+ // floating-point) extension.
+ if (HasD && !HasF)
+ D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
+ << "d requires f extension to also be specified";
+
+ // Additional dependency checks.
+ // TODO: The 'q' extension requires rv64.
+ // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
+
+ // Handle all other types of extensions.
+ getExtensionFeatures(D, Args, Features, MArch, OtherExts);
+ }
+
+ // Now add any that the user explicitly requested on the command line,
+ // which may override the defaults.
+ handleTargetFeaturesGroup(Args, Features, options::OPT_m_riscv_Features_Group);
+}
+
+StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ return A->getValue();
+
+ return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";
+}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h
new file mode 100644
index 000000000000..beda14979fab
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -0,0 +1,32 @@
+//===--- RISCV.h - RISCV-specific Tool Helpers ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_RISCV_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_RISCV_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace riscv {
+void getRISCVTargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
+ std::vector<llvm::StringRef> &Features);
+StringRef getRISCVABI(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+} // end namespace riscv
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_RISCV_H
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
index 594ec9986d8e..c177031b9f75 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/Sparc.cpp
@@ -45,14 +45,29 @@ const char *sparc::getSparcAsmModeForCPU(StringRef Name,
.Case("niagara2", "-Av8plusb")
.Case("niagara3", "-Av8plusd")
.Case("niagara4", "-Av8plusd")
+ .Case("ma2100", "-Aleon")
+ .Case("ma2150", "-Aleon")
+ .Case("ma2155", "-Aleon")
+ .Case("ma2450", "-Aleon")
+ .Case("ma2455", "-Aleon")
+ .Case("ma2x5x", "-Aleon")
+ .Case("ma2080", "-Aleon")
+ .Case("ma2085", "-Aleon")
+ .Case("ma2480", "-Aleon")
+ .Case("ma2485", "-Aleon")
+ .Case("ma2x8x", "-Aleon")
+ .Case("myriad2", "-Aleon")
+ .Case("myriad2.1", "-Aleon")
+ .Case("myriad2.2", "-Aleon")
+ .Case("myriad2.3", "-Aleon")
.Case("leon2", "-Av8")
.Case("at697e", "-Av8")
.Case("at697f", "-Av8")
- .Case("leon3", "-Av8")
+ .Case("leon3", "-Aleon")
.Case("ut699", "-Av8")
- .Case("gr712rc", "-Av8")
- .Case("leon4", "-Av8")
- .Case("gr740", "-Av8")
+ .Case("gr712rc", "-Aleon")
+ .Case("leon4", "-Aleon")
+ .Case("gr740", "-Aleon")
.Default("-Av8");
}
}
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
index a18b2aa35b03..7a4f836d2e1a 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -40,26 +40,29 @@ const char *x86::getX86TargetCPU(const ArgList &Args,
return Args.MakeArgString(CPU);
}
- if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
- // Mapping built by referring to X86TargetInfo::getDefaultFeatures().
+ if (const Arg *A = Args.getLastArgNoClaim(options::OPT__SLASH_arch)) {
+ // Mapping built by looking at lib/Basic's X86TargetInfo::initFeatureMap().
StringRef Arch = A->getValue();
- const char *CPU;
- if (Triple.getArch() == llvm::Triple::x86) {
+ const char *CPU = nullptr;
+ if (Triple.getArch() == llvm::Triple::x86) { // 32-bit-only /arch: flags.
CPU = llvm::StringSwitch<const char *>(Arch)
.Case("IA32", "i386")
.Case("SSE", "pentium3")
.Case("SSE2", "pentium4")
- .Case("AVX", "sandybridge")
- .Case("AVX2", "haswell")
.Default(nullptr);
- } else {
+ }
+ if (CPU == nullptr) { // 32-bit and 64-bit /arch: flags.
CPU = llvm::StringSwitch<const char *>(Arch)
.Case("AVX", "sandybridge")
.Case("AVX2", "haswell")
+ .Case("AVX512F", "knl")
+ .Case("AVX512", "skylake-avx512")
.Default(nullptr);
}
- if (CPU)
+ if (CPU) {
+ A->claim();
return CPU;
+ }
}
// Select the default CPU if none was given (or detection failed).
@@ -141,30 +144,6 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+ssse3");
}
- // Set features according to the -arch flag on MSVC.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
- StringRef Arch = A->getValue();
- bool ArchUsed = false;
- // First, look for flags that are shared in x86 and x86-64.
- if (ArchType == llvm::Triple::x86_64 || ArchType == llvm::Triple::x86) {
- if (Arch == "AVX" || Arch == "AVX2") {
- ArchUsed = true;
- Features.push_back(Args.MakeArgString("+" + Arch.lower()));
- }
- }
- // Then, look for x86-specific flags.
- if (ArchType == llvm::Triple::x86) {
- if (Arch == "IA32") {
- ArchUsed = true;
- } else if (Arch == "SSE" || Arch == "SSE2") {
- ArchUsed = true;
- Features.push_back(Args.MakeArgString("+" + Arch.lower()));
- }
- }
- if (!ArchUsed)
- D.Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(Args);
- }
-
// Now add any that the user explicitly requested on the command line,
// which may override the defaults.
handleTargetFeaturesGroup(Args, Features, options::OPT_m_x86_Features_Group);