summaryrefslogtreecommitdiffstats
path: root/clang/lib/Driver
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2018-01-11 13:36:56 +0000
committerAlex Bradbury <asb@lowrisc.org>2018-01-11 13:36:56 +0000
commit71f45455e1bab13226eddfae5ee93e82aaf4b975 (patch)
treed5c410b904cae491f1adf9869cf9de4e8fdd96c7 /clang/lib/Driver
parent9b395a12edf98f6e0944f9a037862a3c022b3da3 (diff)
downloadbcm5719-llvm-71f45455e1bab13226eddfae5ee93e82aaf4b975.tar.gz
bcm5719-llvm-71f45455e1bab13226eddfae5ee93e82aaf4b975.zip
[RISCV] Add the RISCV target and compiler driver
As RV64 codegen has not yet been upstreamed into LLVM, we focus on RV32 driver support (RV64 to follow). Differential Revision: https://reviews.llvm.org/D39963 llvm-svn: 322276
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r--clang/lib/Driver/CMakeLists.txt1
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.cpp61
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.h32
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp39
-rw-r--r--clang/lib/Driver/ToolChains/Clang.h2
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp60
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp23
7 files changed, 217 insertions, 1 deletions
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 5bf91f2be98..afb1cdf3753 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -25,6 +25,7 @@ add_clang_library(clangDriver
ToolChains/Arch/ARM.cpp
ToolChains/Arch/Mips.cpp
ToolChains/Arch/PPC.cpp
+ ToolChains/Arch/RISCV.cpp
ToolChains/Arch/Sparc.cpp
ToolChains/Arch/SystemZ.cpp
ToolChains/Arch/X86.cpp
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
new file mode 100644
index 00000000000..2b4ae88365a
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -0,0 +1,61 @@
+//===--- 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/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"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+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();
+ // TODO: handle rv64
+ std::pair<StringRef, StringRef> MArchSplit = StringRef(MArch).split("rv32");
+ if (!MArchSplit.second.size())
+ return;
+
+ for (char c : MArchSplit.second) {
+ switch (c) {
+ case 'i':
+ break;
+ case 'm':
+ Features.push_back("+m");
+ break;
+ case 'a':
+ Features.push_back("+a");
+ break;
+ case 'f':
+ Features.push_back("+f");
+ break;
+ case 'd':
+ Features.push_back("+d");
+ break;
+ case 'c':
+ Features.push_back("+c");
+ break;
+ }
+ }
+ }
+}
+
+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/clang/lib/Driver/ToolChains/Arch/RISCV.h b/clang/lib/Driver/ToolChains/Arch/RISCV.h
new file mode 100644
index 00000000000..beda14979fa
--- /dev/null
+++ b/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/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 5c536575da9..3d374a4c6f5 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -12,6 +12,7 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
@@ -327,6 +328,10 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
case llvm::Triple::ppc64le:
ppc::getPPCTargetFeatures(D, Triple, Args, Features);
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ riscv::getRISCVTargetFeatures(D, Args, Features);
+ break;
case llvm::Triple::systemz:
systemz::getSystemZTargetFeatures(Args, Features);
break;
@@ -547,6 +552,14 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
}
}
+ switch (Triple.getArch()) {
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return !areOptimizationsEnabled(Args);
+ default:
+ break;
+ }
+
if (Triple.isOSWindows()) {
switch (Triple.getArch()) {
case llvm::Triple::x86:
@@ -1282,6 +1295,8 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) {
case llvm::Triple::hexagon:
case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
case llvm::Triple::systemz:
case llvm::Triple::xcore:
return false;
@@ -1391,6 +1406,11 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
AddPPCTargetArgs(Args, CmdArgs);
break;
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ AddRISCVTargetArgs(Args, CmdArgs);
+ break;
+
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
@@ -1668,6 +1688,25 @@ void Clang::AddPPCTargetArgs(const ArgList &Args,
}
}
+void Clang::AddRISCVTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ // FIXME: currently defaults to the soft-float ABIs. Will need to be
+ // expanded to select ilp32f, ilp32d, lp64f, lp64d when appropiate.
+ const char *ABIName = nullptr;
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
+ ABIName = A->getValue();
+ else if (Triple.getArch() == llvm::Triple::riscv32)
+ ABIName = "ilp32";
+ else if (Triple.getArch() == llvm::Triple::riscv64)
+ ABIName = "lp64";
+ else
+ llvm_unreachable("Unexpected triple!");
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName);
+}
+
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
sparc::FloatABI FloatABI =
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index e23822b9c67..8893d88a8ca 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -60,6 +60,8 @@ private:
llvm::opt::ArgStringList &CmdArgs) const;
void AddR600TargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
+ void AddRISCVTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 7845781f12c..d7cc101a60f 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -8,13 +8,14 @@
//===----------------------------------------------------------------------===//
#include "Gnu.h"
-#include "Linux.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "CommonArgs.h"
+#include "Linux.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX
#include "clang/Driver/Compilation.h"
@@ -271,6 +272,10 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf64ppc";
case llvm::Triple::ppc64le:
return "elf64lppc";
+ case llvm::Triple::riscv32:
+ return "elf32lriscv";
+ case llvm::Triple::riscv64:
+ return "elf64lriscv";
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
return "elf32_sparc";
@@ -856,6 +861,10 @@ static bool isMicroMips(const ArgList &Args) {
return A && A->getOption().matches(options::OPT_mmicromips);
}
+static bool isRISCV(llvm::Triple::ArchType Arch) {
+ return Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
+}
+
static Multilib makeMultilib(StringRef commonSuffix) {
return Multilib(commonSuffix, commonSuffix, commonSuffix);
}
@@ -1401,6 +1410,41 @@ static void findAndroidArmMultilibs(const Driver &D,
Result.Multilibs = AndroidArmMultilibs;
}
+static void findRISCVMultilibs(const Driver &D,
+ const llvm::Triple &TargetTriple, StringRef Path,
+ const ArgList &Args, DetectedMultilibs &Result) {
+
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+ Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32");
+ Multilib Ilp32f =
+ makeMultilib("lib32/ilp32f").flag("+m32").flag("+mabi=ilp32f");
+ Multilib Ilp32d =
+ makeMultilib("lib32/ilp32d").flag("+m32").flag("+mabi=ilp32d");
+ Multilib Lp64 = makeMultilib("lib64/lp64").flag("+m64").flag("+mabi=lp64");
+ Multilib Lp64f = makeMultilib("lib64/lp64f").flag("+m64").flag("+mabi=lp64f");
+ Multilib Lp64d = makeMultilib("lib64/lp64d").flag("+m64").flag("+mabi=lp64d");
+ MultilibSet RISCVMultilibs =
+ MultilibSet()
+ .Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
+ .FilterOut(NonExistent);
+
+ Multilib::flags_list Flags;
+ bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
+
+ addMultilibFlag(!IsRV64, "m32", Flags);
+ addMultilibFlag(IsRV64, "m64", Flags);
+ addMultilibFlag(ABIName == "ilp32", "mabi=ilp32", Flags);
+ addMultilibFlag(ABIName == "ilp32f", "mabi=ilp32f", Flags);
+ addMultilibFlag(ABIName == "ilp32d", "mabi=ilp32d", Flags);
+ addMultilibFlag(ABIName == "lp64", "mabi=lp64", Flags);
+ addMultilibFlag(ABIName == "lp64f", "mabi=lp64f", Flags);
+ addMultilibFlag(ABIName == "lp64d", "mabi=lp64d", Flags);
+
+ if (RISCVMultilibs.select(Flags, Result.SelectedMultilib))
+ Result.Multilibs = RISCVMultilibs;
+}
+
static bool findBiarchMultilibs(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
@@ -1783,6 +1827,10 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
"powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu",
"powerpc64le-suse-linux", "ppc64le-redhat-linux"};
+ static const char *const RISCV32LibDirs[] = {"/lib", "/lib32"};
+ static const char *const RISCVTriples[] = {"riscv32-unknown-linux-gnu",
+ "riscv64-unknown-linux-gnu"};
+
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
"sparcv8-linux-gnu"};
@@ -1928,6 +1976,12 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
LibDirs.append(begin(PPC64LELibDirs), end(PPC64LELibDirs));
TripleAliases.append(begin(PPC64LETriples), end(PPC64LETriples));
break;
+ case llvm::Triple::riscv32:
+ LibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
+ BiarchLibDirs.append(begin(RISCV32LibDirs), end(RISCV32LibDirs));
+ TripleAliases.append(begin(RISCVTriples), end(RISCVTriples));
+ BiarchTripleAliases.append(begin(RISCVTriples), end(RISCVTriples));
+ break;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
LibDirs.append(begin(SPARCv8LibDirs), end(SPARCv8LibDirs));
@@ -2025,6 +2079,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
} else if (tools::isMipsArch(TargetArch)) {
if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
return false;
+ } else if (isRISCV(TargetArch)) {
+ findRISCVMultilibs(D, TargetTriple, Path, Args, Detected);
} else if (!findBiarchMultilibs(D, TargetTriple, Path, Args,
NeedsBiarchSuffix, Detected)) {
return false;
@@ -2240,6 +2296,8 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
case llvm::Triple::systemz:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 1301cdf114a..9ce2407d991 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -11,6 +11,7 @@
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
+#include "Arch/RISCV.h"
#include "CommonArgs.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "clang/Config/config.h"
@@ -176,6 +177,9 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Triple.getEnvironment() == llvm::Triple::GNUX32)
return "libx32";
+ if (Triple.getArch() == llvm::Triple::riscv32)
+ return "lib32";
+
return Triple.isArch32Bit() ? "lib" : "lib64";
}
@@ -226,6 +230,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsAndroid = Triple.isAndroid();
const bool IsMips = tools::isMipsArch(Arch);
const bool IsHexagon = Arch == llvm::Triple::hexagon;
+ const bool IsRISCV =
+ Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64;
if (IsMips && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);
@@ -333,6 +339,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ if (IsRISCV) {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
+ addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
+ }
// Try walking via the GCC triple path in case of biarch or multiarch GCC
// installations with strange symlinks.
@@ -511,6 +522,18 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader =
(tools::ppc::hasPPCAbiArg(Args, "elfv1")) ? "ld64.so.1" : "ld64.so.2";
break;
+ case llvm::Triple::riscv32: {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ LibDir = "lib";
+ Loader = ("ld-linux-riscv32-" + ABIName + ".so.1").str();
+ break;
+ }
+ case llvm::Triple::riscv64: {
+ StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
+ LibDir = "lib";
+ Loader = ("ld-linux-riscv64-" + ABIName + ".so.1").str();
+ break;
+ }
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
LibDir = "lib";
OpenPOWER on IntegriCloud