1 //===--- RISCVToolchain.cpp - RISCV ToolChain Implementations ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "RISCVToolchain.h"
10 #include "CommonArgs.h"
11 #include "InputInfo.h"
12 #include "clang/Driver/Compilation.h"
13 #include "clang/Driver/Options.h"
14 #include "llvm/Option/ArgList.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/raw_ostream.h"
19 using namespace clang::driver;
20 using namespace clang::driver::toolchains;
21 using namespace clang::driver::tools;
22 using namespace clang;
23 using namespace llvm::opt;
25 static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
26 const Multilib &Multilib,
27 StringRef InstallPath,
28 ToolChain::path_list &Paths) {
29 if (const auto &PathsCallback = Multilibs.filePathsCallback())
30 for (const auto &Path : PathsCallback(Multilib))
31 addPathIfExists(D, InstallPath + Path, Paths);
35 RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
37 : Generic_ELF(D, Triple, Args) {
38 GCCInstallation.init(Triple, Args);
39 if (GCCInstallation.isValid()) {
40 Multilibs = GCCInstallation.getMultilibs();
41 SelectedMultilib = GCCInstallation.getMultilib();
42 path_list &Paths = getFilePaths();
43 // Add toolchain/multilib specific file paths.
44 addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
45 GCCInstallation.getInstallPath(), Paths);
46 getFilePaths().push_back(GCCInstallation.getInstallPath().str());
47 ToolChain::path_list &PPaths = getProgramPaths();
48 // Multilib cross-compiler GCC installations put ld in a triple-prefixed
49 // directory off of the parent of the GCC installation.
50 PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
51 GCCInstallation.getTriple().str() + "/bin")
53 PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
55 getProgramPaths().push_back(D.Dir);
57 getFilePaths().push_back(computeSysRoot() + "/lib");
60 Tool *RISCVToolChain::buildLinker() const {
61 return new tools::RISCV::Linker(*this);
64 ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
65 return GCCInstallation.isValid() ?
66 ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
69 ToolChain::UnwindLibType
70 RISCVToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
71 return ToolChain::UNW_None;
74 void RISCVToolChain::addClangTargetOptions(
75 const llvm::opt::ArgList &DriverArgs,
76 llvm::opt::ArgStringList &CC1Args,
77 Action::OffloadKind) const {
78 CC1Args.push_back("-nostdsysteminc");
81 void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
82 ArgStringList &CC1Args) const {
83 if (DriverArgs.hasArg(options::OPT_nostdinc))
86 if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
87 SmallString<128> Dir(computeSysRoot());
88 llvm::sys::path::append(Dir, "include");
89 addSystemInclude(DriverArgs, CC1Args, Dir.str());
93 void RISCVToolChain::addLibStdCxxIncludePaths(
94 const llvm::opt::ArgList &DriverArgs,
95 llvm::opt::ArgStringList &CC1Args) const {
96 const GCCVersion &Version = GCCInstallation.getVersion();
97 StringRef TripleStr = GCCInstallation.getTriple().str();
98 const Multilib &Multilib = GCCInstallation.getMultilib();
99 addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
100 "", TripleStr, "", "", Multilib.includeSuffix(), DriverArgs, CC1Args);
103 std::string RISCVToolChain::computeSysRoot() const {
104 if (!getDriver().SysRoot.empty())
105 return getDriver().SysRoot;
107 SmallString<128> SysRootDir;
108 if (GCCInstallation.isValid()) {
109 StringRef LibDir = GCCInstallation.getParentLibPath();
110 StringRef TripleStr = GCCInstallation.getTriple().str();
111 llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
113 // Use the triple as provided to the driver. Unlike the parsed triple
114 // this has not been normalized to always contain every field.
115 llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
116 getDriver().getTargetTriple());
119 if (!llvm::sys::fs::exists(SysRootDir))
120 return std::string();
122 return SysRootDir.str();
125 void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
126 const InputInfo &Output,
127 const InputInfoList &Inputs,
129 const char *LinkingOutput) const {
130 const ToolChain &ToolChain = getToolChain();
131 const Driver &D = ToolChain.getDriver();
132 ArgStringList CmdArgs;
134 if (!D.SysRoot.empty())
135 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
137 bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
138 CmdArgs.push_back("-m");
140 CmdArgs.push_back("elf64lriscv");
142 CmdArgs.push_back("elf32lriscv");
145 std::string Linker = getToolChain().GetProgramPath(getShortName());
148 !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
150 const char *crtbegin, *crtend;
151 auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
152 if (RuntimeLib == ToolChain::RLT_Libgcc) {
153 crtbegin = "crtbegin.o";
156 assert (RuntimeLib == ToolChain::RLT_CompilerRT);
157 crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
158 ToolChain::FT_Object);
159 crtend = ToolChain.getCompilerRTArgString(Args, "crtend",
160 ToolChain::FT_Object);
164 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
165 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
168 Args.AddAllArgs(CmdArgs, options::OPT_L);
169 ToolChain.AddFilePathLibArgs(Args, CmdArgs);
170 Args.AddAllArgs(CmdArgs,
171 {options::OPT_T_Group, options::OPT_e, options::OPT_s,
172 options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
174 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
176 // TODO: add C++ includes and libs if compiling C++.
178 if (!Args.hasArg(options::OPT_nostdlib) &&
179 !Args.hasArg(options::OPT_nodefaultlibs)) {
180 if (ToolChain.ShouldLinkCXXStdlib(Args))
181 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
182 CmdArgs.push_back("--start-group");
183 CmdArgs.push_back("-lc");
184 CmdArgs.push_back("-lgloss");
185 CmdArgs.push_back("--end-group");
186 AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
190 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
192 CmdArgs.push_back("-o");
193 CmdArgs.push_back(Output.getFilename());
194 C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),