diff options
author | Alex Bradbury <asb@lowrisc.org> | 2018-01-11 13:36:56 +0000 |
---|---|---|
committer | Alex Bradbury <asb@lowrisc.org> | 2018-01-11 13:36:56 +0000 |
commit | 71f45455e1bab13226eddfae5ee93e82aaf4b975 (patch) | |
tree | d5c410b904cae491f1adf9869cf9de4e8fdd96c7 /clang/lib/Driver | |
parent | 9b395a12edf98f6e0944f9a037862a3c022b3da3 (diff) | |
download | bcm5719-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.txt | 1 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 61 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Arch/RISCV.h | 32 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.h | 2 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Gnu.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Linux.cpp | 23 |
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"; |