1//===--- RISCVToolchain.cpp - RISC-V 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
9#include "RISCVToolchain.h"
10#include "clang/Driver/CommonArgs.h"
11#include "clang/Driver/Compilation.h"
12#include "clang/Driver/InputInfo.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
18using namespace clang::driver;
19using namespace clang::driver::toolchains;
20using namespace clang::driver::tools;
21using namespace clang;
22using namespace llvm::opt;
23
24static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
25 const Multilib &Multilib,
26 StringRef InstallPath,
27 ToolChain::path_list &Paths) {
28 if (const auto &PathsCallback = Multilibs.filePathsCallback())
29 for (const auto &Path : PathsCallback(Multilib))
30 addPathIfExists(D, Path: InstallPath + Path, Paths);
31}
32
33// This function tests whether a gcc installation is present either
34// through gcc-toolchain argument or in the same prefix where clang
35// is installed. This helps decide whether to instantiate this toolchain
36// or Baremetal toolchain.
37bool RISCVToolChain::hasGCCToolchain(const Driver &D,
38 const llvm::opt::ArgList &Args) {
39 if (Args.getLastArg(options::OPT_gcc_toolchain))
40 return true;
41
42 SmallString<128> GCCDir;
43 llvm::sys::path::append(path&: GCCDir, a: D.Dir, b: "..", c: D.getTargetTriple(),
44 d: "lib/crt0.o");
45 return llvm::sys::fs::exists(Path: GCCDir);
46}
47
48/// RISC-V Toolchain
49RISCVToolChain::RISCVToolChain(const Driver &D, const llvm::Triple &Triple,
50 const ArgList &Args)
51 : Generic_ELF(D, Triple, Args) {
52 GCCInstallation.init(TargetTriple: Triple, Args);
53 if (GCCInstallation.isValid()) {
54 Multilibs = GCCInstallation.getMultilibs();
55 SelectedMultilibs.assign(IL: {GCCInstallation.getMultilib()});
56 path_list &Paths = getFilePaths();
57 // Add toolchain/multilib specific file paths.
58 addMultilibsFilePaths(D, Multilibs, Multilib: SelectedMultilibs.back(),
59 InstallPath: GCCInstallation.getInstallPath(), Paths);
60 getFilePaths().push_back(Elt: GCCInstallation.getInstallPath().str());
61 ToolChain::path_list &PPaths = getProgramPaths();
62 // Multilib cross-compiler GCC installations put ld in a triple-prefixed
63 // directory off of the parent of the GCC installation.
64 PPaths.push_back(Elt: Twine(GCCInstallation.getParentLibPath() + "/../" +
65 GCCInstallation.getTriple().str() + "/bin")
66 .str());
67 PPaths.push_back(Elt: (GCCInstallation.getParentLibPath() + "/../bin").str());
68 } else {
69 getProgramPaths().push_back(Elt: D.Dir);
70 }
71 getFilePaths().push_back(Elt: computeSysRoot() + "/lib");
72}
73
74Tool *RISCVToolChain::buildLinker() const {
75 return new tools::RISCV::Linker(*this);
76}
77
78ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
79 return GCCInstallation.isValid() ?
80 ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
81}
82
83ToolChain::UnwindLibType
84RISCVToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
85 return ToolChain::UNW_None;
86}
87
88ToolChain::UnwindTableLevel RISCVToolChain::getDefaultUnwindTableLevel(
89 const llvm::opt::ArgList &Args) const {
90 return UnwindTableLevel::None;
91}
92
93void RISCVToolChain::addClangTargetOptions(
94 const llvm::opt::ArgList &DriverArgs,
95 llvm::opt::ArgStringList &CC1Args,
96 Action::OffloadKind) const {
97 CC1Args.push_back(Elt: "-nostdsysteminc");
98}
99
100void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
101 ArgStringList &CC1Args) const {
102 if (DriverArgs.hasArg(options::OPT_nostdinc))
103 return;
104
105 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
106 SmallString<128> Dir(getDriver().ResourceDir);
107 llvm::sys::path::append(path&: Dir, a: "include");
108 addSystemInclude(DriverArgs, CC1Args, Path: Dir.str());
109 }
110
111 if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
112 SmallString<128> Dir(computeSysRoot());
113 llvm::sys::path::append(path&: Dir, a: "include");
114 addSystemInclude(DriverArgs, CC1Args, Path: Dir.str());
115 }
116}
117
118void RISCVToolChain::addLibStdCxxIncludePaths(
119 const llvm::opt::ArgList &DriverArgs,
120 llvm::opt::ArgStringList &CC1Args) const {
121 const GCCVersion &Version = GCCInstallation.getVersion();
122 StringRef TripleStr = GCCInstallation.getTriple().str();
123 const Multilib &Multilib = GCCInstallation.getMultilib();
124 addLibStdCXXIncludePaths(IncludeDir: computeSysRoot() + "/include/c++/" + Version.Text,
125 Triple: TripleStr, IncludeSuffix: Multilib.includeSuffix(), DriverArgs,
126 CC1Args);
127}
128
129std::string RISCVToolChain::computeSysRoot() const {
130 if (!getDriver().SysRoot.empty())
131 return getDriver().SysRoot;
132
133 SmallString<128> SysRootDir;
134 if (GCCInstallation.isValid()) {
135 StringRef LibDir = GCCInstallation.getParentLibPath();
136 StringRef TripleStr = GCCInstallation.getTriple().str();
137 llvm::sys::path::append(path&: SysRootDir, a: LibDir, b: "..", c: TripleStr);
138 } else {
139 // Use the triple as provided to the driver. Unlike the parsed triple
140 // this has not been normalized to always contain every field.
141 llvm::sys::path::append(path&: SysRootDir, a: getDriver().Dir, b: "..",
142 c: getDriver().getTargetTriple());
143 }
144
145 if (!llvm::sys::fs::exists(Path: SysRootDir))
146 return std::string();
147
148 return std::string(SysRootDir);
149}
150
151void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
152 const InputInfo &Output,
153 const InputInfoList &Inputs,
154 const ArgList &Args,
155 const char *LinkingOutput) const {
156 const ToolChain &ToolChain = getToolChain();
157 const Driver &D = ToolChain.getDriver();
158 ArgStringList CmdArgs;
159
160 if (!D.SysRoot.empty())
161 CmdArgs.push_back(Elt: Args.MakeArgString(Str: "--sysroot=" + D.SysRoot));
162
163 if (Args.hasArg(options::OPT_mno_relax))
164 CmdArgs.push_back(Elt: "--no-relax");
165
166 bool IsRV64 = ToolChain.getArch() == llvm::Triple::riscv64;
167 CmdArgs.push_back(Elt: "-m");
168 if (IsRV64) {
169 CmdArgs.push_back(Elt: "elf64lriscv");
170 } else {
171 CmdArgs.push_back(Elt: "elf32lriscv");
172 }
173 CmdArgs.push_back(Elt: "-X");
174
175 std::string Linker = getToolChain().GetLinkerPath();
176
177 bool WantCRTs =
178 !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
179
180 const char *crtbegin, *crtend;
181 auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
182 if (RuntimeLib == ToolChain::RLT_Libgcc) {
183 crtbegin = "crtbegin.o";
184 crtend = "crtend.o";
185 } else {
186 assert (RuntimeLib == ToolChain::RLT_CompilerRT);
187 crtbegin = ToolChain.getCompilerRTArgString(Args, Component: "crtbegin",
188 Type: ToolChain::FT_Object);
189 crtend = ToolChain.getCompilerRTArgString(Args, Component: "crtend",
190 Type: ToolChain::FT_Object);
191 }
192
193 if (WantCRTs) {
194 CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "crt0.o")));
195 CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: crtbegin)));
196 }
197
198 AddLinkerInputs(TC: ToolChain, Inputs, Args, CmdArgs, JA);
199
200 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
201
202 ToolChain.AddFilePathLibArgs(Args, CmdArgs);
203 Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
204 options::OPT_t, options::OPT_r});
205
206 // TODO: add C++ includes and libs if compiling C++.
207
208 if (!Args.hasArg(options::OPT_nostdlib) &&
209 !Args.hasArg(options::OPT_nodefaultlibs)) {
210 if (D.CCCIsCXX()) {
211 if (ToolChain.ShouldLinkCXXStdlib(Args))
212 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
213 CmdArgs.push_back(Elt: "-lm");
214 }
215 CmdArgs.push_back(Elt: "--start-group");
216 CmdArgs.push_back(Elt: "-lc");
217 CmdArgs.push_back(Elt: "-lgloss");
218 CmdArgs.push_back(Elt: "--end-group");
219 AddRunTimeLibs(TC: ToolChain, D: ToolChain.getDriver(), CmdArgs, Args);
220 }
221
222 if (WantCRTs)
223 CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: crtend)));
224
225 CmdArgs.push_back(Elt: "-o");
226 CmdArgs.push_back(Elt: Output.getFilename());
227 C.addCommand(C: std::make_unique<Command>(
228 args: JA, args: *this, args: ResponseFileSupport::AtFileCurCP(), args: Args.MakeArgString(Str: Linker),
229 args&: CmdArgs, args: Inputs, args: Output));
230}
231// RISCV tools end.
232

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Driver/ToolChains/RISCVToolchain.cpp