RISCVToolchain.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "RISCVToolchain.h"
  9. #include "CommonArgs.h"
  10. #include "clang/Driver/Compilation.h"
  11. #include "clang/Driver/InputInfo.h"
  12. #include "clang/Driver/Options.h"
  13. #include "llvm/Option/ArgList.h"
  14. #include "llvm/Support/FileSystem.h"
  15. #include "llvm/Support/Path.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. using namespace clang::driver;
  18. using namespace clang::driver::toolchains;
  19. using namespace clang::driver::tools;
  20. using namespace clang;
  21. using namespace llvm::opt;
  22. static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
  23. const Multilib &Multilib,
  24. StringRef InstallPath,
  25. ToolChain::path_list &Paths) {
  26. if (const auto &PathsCallback = Multilibs.filePathsCallback())
  27. for (const auto &Path : PathsCallback(Multilib))
  28. addPathIfExists(D, InstallPath + Path, Paths);
  29. }
  30. // This function tests whether a gcc installation is present either
  31. // through gcc-toolchain argument or in the same prefix where clang
  32. // is installed. This helps decide whether to instantiate this toolchain
  33. // or Baremetal toolchain.
  34. bool RISCVToolChain::hasGCCToolchain(const Driver &D,
  35. const llvm::opt::ArgList &Args) {
  36. if (Args.getLastArg(options::OPT_gcc_toolchain))
  37. return true;
  38. SmallString<128> GCCDir;
  39. llvm::sys::path::append(GCCDir, D.Dir, "..", D.getTargetTriple(),
  40. "lib/crt0.o");
  41. return llvm::sys::fs::exists(GCCDir);
  42. }
  43. /// RISCV Toolchain
  44. RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
  45. const ArgList &Args)
  46. : Generic_ELF(D, Triple, Args) {
  47. GCCInstallation.init(Triple, Args);
  48. if (GCCInstallation.isValid()) {
  49. Multilibs = GCCInstallation.getMultilibs();
  50. SelectedMultilib = GCCInstallation.getMultilib();
  51. path_list &Paths = getFilePaths();
  52. // Add toolchain/multilib specific file paths.
  53. addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
  54. GCCInstallation.getInstallPath(), Paths);
  55. getFilePaths().push_back(GCCInstallation.getInstallPath().str());
  56. ToolChain::path_list &PPaths = getProgramPaths();
  57. // Multilib cross-compiler GCC installations put ld in a triple-prefixed
  58. // directory off of the parent of the GCC installation.
  59. PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
  60. GCCInstallation.getTriple().str() + "/bin")
  61. .str());
  62. PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
  63. } else {
  64. getProgramPaths().push_back(D.Dir);
  65. }
  66. getFilePaths().push_back(computeSysRoot() + "/lib");
  67. }
  68. Tool *RISCVToolChain::buildLinker() const {
  69. return new tools::RISCV::Linker(*this);
  70. }
  71. ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
  72. return GCCInstallation.isValid() ?
  73. ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
  74. }
  75. ToolChain::UnwindLibType
  76. RISCVToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
  77. return ToolChain::UNW_None;
  78. }
  79. void RISCVToolChain::addClangTargetOptions(
  80. const llvm::opt::ArgList &DriverArgs,
  81. llvm::opt::ArgStringList &CC1Args,
  82. Action::OffloadKind) const {
  83. CC1Args.push_back("-nostdsysteminc");
  84. }
  85. void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  86. ArgStringList &CC1Args) const {
  87. if (DriverArgs.hasArg(options::OPT_nostdinc))
  88. return;
  89. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  90. SmallString<128> Dir(getDriver().ResourceDir);
  91. llvm::sys::path::append(Dir, "include");
  92. addSystemInclude(DriverArgs, CC1Args, Dir.str());
  93. }
  94. if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
  95. SmallString<128> Dir(computeSysRoot());
  96. llvm::sys::path::append(Dir, "include");
  97. addSystemInclude(DriverArgs, CC1Args, Dir.str());
  98. }
  99. }
  100. void RISCVToolChain::addLibStdCxxIncludePaths(
  101. const llvm::opt::ArgList &DriverArgs,
  102. llvm::opt::ArgStringList &CC1Args) const {
  103. const GCCVersion &Version = GCCInstallation.getVersion();
  104. StringRef TripleStr = GCCInstallation.getTriple().str();
  105. const Multilib &Multilib = GCCInstallation.getMultilib();
  106. addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
  107. TripleStr, Multilib.includeSuffix(), DriverArgs,
  108. CC1Args);
  109. }
  110. std::string RISCVToolChain::computeSysRoot() const {
  111. if (!getDriver().SysRoot.empty())
  112. return getDriver().SysRoot;
  113. SmallString<128> SysRootDir;
  114. if (GCCInstallation.isValid()) {
  115. StringRef LibDir = GCCInstallation.getParentLibPath();
  116. StringRef TripleStr = GCCInstallation.getTriple().str();
  117. llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
  118. } else {
  119. // Use the triple as provided to the driver. Unlike the parsed triple
  120. // this has not been normalized to always contain every field.
  121. llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
  122. getDriver().getTargetTriple());
  123. }
  124. if (!llvm::sys::fs::exists(SysRootDir))
  125. return std::string();
  126. return std::string(SysRootDir.str());
  127. }
  128. void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  129. const InputInfo &Output,
  130. const InputInfoList &Inputs,
  131. const ArgList &Args,
  132. const char *LinkingOutput) const {
  133. const ToolChain &ToolChain = getToolChain();
  134. const Driver &D = ToolChain.getDriver();
  135. ArgStringList CmdArgs;
  136. if (!D.SysRoot.empty())
  137. CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
  138. bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
  139. CmdArgs.push_back("-m");
  140. if (IsRV64) {
  141. CmdArgs.push_back("elf64lriscv");
  142. } else {
  143. CmdArgs.push_back("elf32lriscv");
  144. }
  145. CmdArgs.push_back("-X");
  146. std::string Linker = getToolChain().GetLinkerPath();
  147. bool WantCRTs =
  148. !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
  149. const char *crtbegin, *crtend;
  150. auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
  151. if (RuntimeLib == ToolChain::RLT_Libgcc) {
  152. crtbegin = "crtbegin.o";
  153. crtend = "crtend.o";
  154. } else {
  155. assert (RuntimeLib == ToolChain::RLT_CompilerRT);
  156. crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
  157. ToolChain::FT_Object);
  158. crtend = ToolChain.getCompilerRTArgString(Args, "crtend",
  159. ToolChain::FT_Object);
  160. }
  161. if (WantCRTs) {
  162. CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
  163. CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
  164. }
  165. AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
  166. Args.AddAllArgs(CmdArgs, options::OPT_L);
  167. Args.AddAllArgs(CmdArgs, options::OPT_u);
  168. ToolChain.AddFilePathLibArgs(Args, CmdArgs);
  169. Args.AddAllArgs(CmdArgs,
  170. {options::OPT_T_Group, options::OPT_e, options::OPT_s,
  171. options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
  172. // TODO: add C++ includes and libs if compiling C++.
  173. if (!Args.hasArg(options::OPT_nostdlib) &&
  174. !Args.hasArg(options::OPT_nodefaultlibs)) {
  175. if (D.CCCIsCXX()) {
  176. if (ToolChain.ShouldLinkCXXStdlib(Args))
  177. ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
  178. CmdArgs.push_back("-lm");
  179. }
  180. CmdArgs.push_back("--start-group");
  181. CmdArgs.push_back("-lc");
  182. CmdArgs.push_back("-lgloss");
  183. CmdArgs.push_back("--end-group");
  184. AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
  185. }
  186. if (WantCRTs)
  187. CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
  188. CmdArgs.push_back("-o");
  189. CmdArgs.push_back(Output.getFilename());
  190. C.addCommand(std::make_unique<Command>(
  191. JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
  192. CmdArgs, Inputs, Output));
  193. }
  194. // RISCV tools end.