diff options
author | Zakk Chen <zakk0610@gmail.com> | 2019-11-18 22:15:50 -0800 |
---|---|---|
committer | Zakk Chen <zakk.chen@sifive.com> | 2019-11-19 02:10:39 -0800 |
commit | b6d7bbfa004310777cd41448ffc377aea082fc8c (patch) | |
tree | 4aa6ca1785980bf3baf6e3cf8716609662e15ab9 /clang/lib | |
parent | 4ef9315c4be0217ed9eb511a0e89228d32dc98cd (diff) | |
download | bcm5719-llvm-b6d7bbfa004310777cd41448ffc377aea082fc8c.tar.gz bcm5719-llvm-b6d7bbfa004310777cd41448ffc377aea082fc8c.zip |
[RISCV] Support mutilib in baremetal environment
Currently only support the set of multilibs same to riscv-gnu-toolchain.
Reviewers: espindola, asb, kito-cheng, lenary
Reviewed By: lenary
Differential Revision: https://reviews.llvm.org/D67508
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Driver/ToolChains/Gnu.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/RISCVToolchain.cpp | 34 |
2 files changed, 87 insertions, 3 deletions
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 2dd3450dd1b..eb84a99a16b 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1503,9 +1503,65 @@ static bool findMSP430Multilibs(const Driver &D, return false; } +static void findRISCVBareMetalMultilibs(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); + struct RiscvMultilib { + StringRef march; + StringRef mabi; + }; + // currently only support the set of multilibs like riscv-gnu-toolchain does. + // TODO: support MULTILIB_REUSE + SmallVector<RiscvMultilib, 8> RISCVMultilibSet = { + {"rv32i", "ilp32"}, {"rv32im", "ilp32"}, {"rv32iac", "ilp32"}, + {"rv32imac", "ilp32"}, {"rv32imafc", "ilp32f"}, {"rv64imac", "lp64"}, + {"rv64imafdc", "lp64d"}}; + + std::vector<Multilib> Ms; + for (auto Element : RISCVMultilibSet) { + // multilib path rule is ${march}/${mabi} + Ms.emplace_back( + makeMultilib((Twine(Element.march) + "/" + Twine(Element.mabi)).str()) + .flag(Twine("+march=", Element.march).str()) + .flag(Twine("+mabi=", Element.mabi).str())); + } + MultilibSet RISCVMultilibs = + MultilibSet() + .Either(ArrayRef<Multilib>(Ms)) + .FilterOut(NonExistent) + .setFilePathsCallback([](const Multilib &M) { + return std::vector<std::string>( + {M.gccSuffix(), + "/../../../../riscv64-unknown-elf/lib" + M.gccSuffix(), + "/../../../../riscv32-unknown-elf/lib" + M.gccSuffix()}); + }); + + + Multilib::flags_list Flags; + llvm::StringSet<> Added_ABIs; + StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple); + StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple); + for (auto Element : RISCVMultilibSet) { + addMultilibFlag(MArch == Element.march, + Twine("march=", Element.march).str().c_str(), Flags); + if (!Added_ABIs.count(Element.mabi)) { + Added_ABIs.insert(Element.mabi); + addMultilibFlag(ABIName == Element.mabi, + Twine("mabi=", Element.mabi).str().c_str(), Flags); + } + } + + if (RISCVMultilibs.select(Flags, Result.SelectedMultilib)) + Result.Multilibs = RISCVMultilibs; +} + static void findRISCVMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, DetectedMultilibs &Result) { + if (TargetTriple.getOS() == llvm::Triple::UnknownOS) + return findRISCVBareMetalMultilibs(D, TargetTriple, Path, Args, Result); FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); Multilib Ilp32 = makeMultilib("lib32/ilp32").flag("+m32").flag("+mabi=ilp32"); diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp index 8019940b521..bd63873e3c6 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -22,19 +22,39 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs, + const Multilib &Multilib, + StringRef InstallPath, + ToolChain::path_list &Paths) { + if (const auto &PathsCallback = Multilibs.filePathsCallback()) + for (const auto &Path : PathsCallback(Multilib)) + addPathIfExists(D, InstallPath + Path, Paths); +} + /// RISCV Toolchain RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { GCCInstallation.init(Triple, Args); - getFilePaths().push_back(computeSysRoot() + "/lib"); if (GCCInstallation.isValid()) { + Multilibs = GCCInstallation.getMultilibs(); + SelectedMultilib = GCCInstallation.getMultilib(); + path_list &Paths = getFilePaths(); + // Add toolchain/multilib specific file paths. + addMultilibsFilePaths(D, Multilibs, SelectedMultilib, + GCCInstallation.getInstallPath(), Paths); getFilePaths().push_back(GCCInstallation.getInstallPath().str()); - getProgramPaths().push_back( - (GCCInstallation.getParentLibPath() + "/../bin").str()); + ToolChain::path_list &PPaths = getProgramPaths(); + // Multilib cross-compiler GCC installations put ld in a triple-prefixed + // directory off of the parent of the GCC installation. + PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" + + GCCInstallation.getTriple().str() + "/bin") + .str()); + PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str()); } else { getProgramPaths().push_back(D.Dir); } + getFilePaths().push_back(computeSysRoot() + "/lib"); } Tool *RISCVToolChain::buildLinker() const { @@ -105,6 +125,14 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64; + CmdArgs.push_back("-m"); + if (IsRV64) { + CmdArgs.push_back("elf64lriscv"); + } else { + CmdArgs.push_back("elf32lriscv"); + } + std::string Linker = getToolChain().GetProgramPath(getShortName()); bool WantCRTs = |