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