181ad6265SDimitry Andric //===--- CSKYToolchain.cpp - CSKY ToolChain Implementations ---*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "CSKYToolChain.h"
1081ad6265SDimitry Andric #include "CommonArgs.h"
1181ad6265SDimitry Andric #include "clang/Driver/Compilation.h"
1281ad6265SDimitry Andric #include "clang/Driver/InputInfo.h"
1381ad6265SDimitry Andric #include "clang/Driver/Options.h"
1481ad6265SDimitry Andric #include "llvm/Option/ArgList.h"
1581ad6265SDimitry Andric #include "llvm/Support/FileSystem.h"
1681ad6265SDimitry Andric #include "llvm/Support/Path.h"
1781ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
1881ad6265SDimitry Andric 
1981ad6265SDimitry Andric using namespace clang::driver;
2081ad6265SDimitry Andric using namespace clang::driver::toolchains;
2181ad6265SDimitry Andric using namespace clang::driver::tools;
2281ad6265SDimitry Andric using namespace clang;
2381ad6265SDimitry Andric using namespace llvm::opt;
2481ad6265SDimitry Andric 
addMultilibsFilePaths(const Driver & D,const MultilibSet & Multilibs,const Multilib & Multilib,StringRef InstallPath,ToolChain::path_list & Paths)2581ad6265SDimitry Andric static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
2681ad6265SDimitry Andric                                   const Multilib &Multilib,
2781ad6265SDimitry Andric                                   StringRef InstallPath,
2881ad6265SDimitry Andric                                   ToolChain::path_list &Paths) {
2981ad6265SDimitry Andric   if (const auto &PathsCallback = Multilibs.filePathsCallback())
3081ad6265SDimitry Andric     for (const auto &Path : PathsCallback(Multilib))
3181ad6265SDimitry Andric       addPathIfExists(D, InstallPath + Path, Paths);
3281ad6265SDimitry Andric }
3381ad6265SDimitry Andric 
3481ad6265SDimitry Andric /// CSKY Toolchain
CSKYToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)3581ad6265SDimitry Andric CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
3681ad6265SDimitry Andric                              const ArgList &Args)
3781ad6265SDimitry Andric     : Generic_ELF(D, Triple, Args) {
3881ad6265SDimitry Andric   GCCInstallation.init(Triple, Args);
3981ad6265SDimitry Andric   if (GCCInstallation.isValid()) {
4081ad6265SDimitry Andric     Multilibs = GCCInstallation.getMultilibs();
4106c3fb27SDimitry Andric     SelectedMultilibs.assign({GCCInstallation.getMultilib()});
4281ad6265SDimitry Andric     path_list &Paths = getFilePaths();
4381ad6265SDimitry Andric     // Add toolchain/multilib specific file paths.
4406c3fb27SDimitry Andric     addMultilibsFilePaths(D, Multilibs, SelectedMultilibs.back(),
4581ad6265SDimitry Andric                           GCCInstallation.getInstallPath(), Paths);
4681ad6265SDimitry Andric     getFilePaths().push_back(GCCInstallation.getInstallPath().str() +
4706c3fb27SDimitry Andric                              SelectedMultilibs.back().osSuffix());
4881ad6265SDimitry Andric     ToolChain::path_list &PPaths = getProgramPaths();
4981ad6265SDimitry Andric     // Multilib cross-compiler GCC installations put ld in a triple-prefixed
5081ad6265SDimitry Andric     // directory off of the parent of the GCC installation.
5181ad6265SDimitry Andric     PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
5281ad6265SDimitry Andric                            GCCInstallation.getTriple().str() + "/bin")
5381ad6265SDimitry Andric                          .str());
5481ad6265SDimitry Andric     PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
5506c3fb27SDimitry Andric     getFilePaths().push_back(computeSysRoot() + "/lib" +
5606c3fb27SDimitry Andric                              SelectedMultilibs.back().osSuffix());
5781ad6265SDimitry Andric   } else {
5881ad6265SDimitry Andric     getProgramPaths().push_back(D.Dir);
5906c3fb27SDimitry Andric     getFilePaths().push_back(computeSysRoot() + "/lib");
6081ad6265SDimitry Andric   }
6181ad6265SDimitry Andric }
6281ad6265SDimitry Andric 
buildLinker() const6381ad6265SDimitry Andric Tool *CSKYToolChain::buildLinker() const {
6481ad6265SDimitry Andric   return new tools::CSKY::Linker(*this);
6581ad6265SDimitry Andric }
6681ad6265SDimitry Andric 
GetDefaultRuntimeLibType() const6781ad6265SDimitry Andric ToolChain::RuntimeLibType CSKYToolChain::GetDefaultRuntimeLibType() const {
6881ad6265SDimitry Andric   return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
6981ad6265SDimitry Andric                                    : ToolChain::RLT_CompilerRT;
7081ad6265SDimitry Andric }
7181ad6265SDimitry Andric 
7281ad6265SDimitry Andric ToolChain::UnwindLibType
GetUnwindLibType(const llvm::opt::ArgList & Args) const7381ad6265SDimitry Andric CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
7481ad6265SDimitry Andric   return ToolChain::UNW_None;
7581ad6265SDimitry Andric }
7681ad6265SDimitry Andric 
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind) const7781ad6265SDimitry Andric void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
7881ad6265SDimitry Andric                                           llvm::opt::ArgStringList &CC1Args,
7981ad6265SDimitry Andric                                           Action::OffloadKind) const {
8081ad6265SDimitry Andric   CC1Args.push_back("-nostdsysteminc");
8181ad6265SDimitry Andric }
8281ad6265SDimitry Andric 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const8381ad6265SDimitry Andric void CSKYToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
8481ad6265SDimitry Andric                                               ArgStringList &CC1Args) const {
8581ad6265SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc))
8681ad6265SDimitry Andric     return;
8781ad6265SDimitry Andric 
8881ad6265SDimitry Andric   if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
8981ad6265SDimitry Andric     SmallString<128> Dir(computeSysRoot());
9081ad6265SDimitry Andric     llvm::sys::path::append(Dir, "include");
9181ad6265SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Dir.str());
9281ad6265SDimitry Andric     SmallString<128> Dir2(computeSysRoot());
9381ad6265SDimitry Andric     llvm::sys::path::append(Dir2, "sys-include");
9481ad6265SDimitry Andric     addSystemInclude(DriverArgs, CC1Args, Dir2.str());
9581ad6265SDimitry Andric   }
9681ad6265SDimitry Andric }
9781ad6265SDimitry Andric 
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const9881ad6265SDimitry Andric void CSKYToolChain::addLibStdCxxIncludePaths(
9981ad6265SDimitry Andric     const llvm::opt::ArgList &DriverArgs,
10081ad6265SDimitry Andric     llvm::opt::ArgStringList &CC1Args) const {
10181ad6265SDimitry Andric   const GCCVersion &Version = GCCInstallation.getVersion();
10281ad6265SDimitry Andric   StringRef TripleStr = GCCInstallation.getTriple().str();
10381ad6265SDimitry Andric   const Multilib &Multilib = GCCInstallation.getMultilib();
10481ad6265SDimitry Andric   addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
10581ad6265SDimitry Andric                            TripleStr, Multilib.includeSuffix(), DriverArgs,
10681ad6265SDimitry Andric                            CC1Args);
10781ad6265SDimitry Andric }
10881ad6265SDimitry Andric 
computeSysRoot() const10981ad6265SDimitry Andric std::string CSKYToolChain::computeSysRoot() const {
11081ad6265SDimitry Andric   if (!getDriver().SysRoot.empty())
11181ad6265SDimitry Andric     return getDriver().SysRoot;
11281ad6265SDimitry Andric 
11381ad6265SDimitry Andric   SmallString<128> SysRootDir;
11481ad6265SDimitry Andric   if (GCCInstallation.isValid()) {
11581ad6265SDimitry Andric     StringRef LibDir = GCCInstallation.getParentLibPath();
11681ad6265SDimitry Andric     StringRef TripleStr = GCCInstallation.getTriple().str();
11781ad6265SDimitry Andric     llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
11881ad6265SDimitry Andric   } else {
11981ad6265SDimitry Andric     // Use the triple as provided to the driver. Unlike the parsed triple
12081ad6265SDimitry Andric     // this has not been normalized to always contain every field.
12181ad6265SDimitry Andric     llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
12281ad6265SDimitry Andric                             getDriver().getTargetTriple());
12381ad6265SDimitry Andric   }
12481ad6265SDimitry Andric 
12581ad6265SDimitry Andric   if (!llvm::sys::fs::exists(SysRootDir))
12681ad6265SDimitry Andric     return std::string();
12781ad6265SDimitry Andric 
128*7a6dacacSDimitry Andric   return std::string(SysRootDir);
12981ad6265SDimitry Andric }
13081ad6265SDimitry Andric 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const13181ad6265SDimitry Andric void CSKY::Linker::ConstructJob(Compilation &C, const JobAction &JA,
13281ad6265SDimitry Andric                                 const InputInfo &Output,
13381ad6265SDimitry Andric                                 const InputInfoList &Inputs,
13481ad6265SDimitry Andric                                 const ArgList &Args,
13581ad6265SDimitry Andric                                 const char *LinkingOutput) const {
13681ad6265SDimitry Andric   const ToolChain &ToolChain = getToolChain();
13781ad6265SDimitry Andric   const Driver &D = ToolChain.getDriver();
13881ad6265SDimitry Andric   ArgStringList CmdArgs;
13981ad6265SDimitry Andric 
14081ad6265SDimitry Andric   if (!D.SysRoot.empty())
14181ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
14281ad6265SDimitry Andric 
14381ad6265SDimitry Andric   CmdArgs.push_back("-m");
14481ad6265SDimitry Andric   CmdArgs.push_back("cskyelf");
14581ad6265SDimitry Andric 
14681ad6265SDimitry Andric   std::string Linker = getToolChain().GetLinkerPath();
14781ad6265SDimitry Andric 
14881ad6265SDimitry Andric   bool WantCRTs =
14981ad6265SDimitry Andric       !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
15081ad6265SDimitry Andric 
15181ad6265SDimitry Andric   const char *crtbegin, *crtend;
15281ad6265SDimitry Andric   auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
15381ad6265SDimitry Andric   if (RuntimeLib == ToolChain::RLT_Libgcc) {
15481ad6265SDimitry Andric     crtbegin = "crtbegin.o";
15581ad6265SDimitry Andric     crtend = "crtend.o";
15681ad6265SDimitry Andric   } else {
15781ad6265SDimitry Andric     assert(RuntimeLib == ToolChain::RLT_CompilerRT);
15881ad6265SDimitry Andric     crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
15981ad6265SDimitry Andric                                                 ToolChain::FT_Object);
16081ad6265SDimitry Andric     crtend =
16181ad6265SDimitry Andric         ToolChain.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object);
16281ad6265SDimitry Andric   }
16381ad6265SDimitry Andric 
16481ad6265SDimitry Andric   if (WantCRTs) {
16581ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
16681ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
16781ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
16881ad6265SDimitry Andric   }
16981ad6265SDimitry Andric 
17081ad6265SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_L);
17181ad6265SDimitry Andric   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
1725f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
1735f757f3fSDimitry Andric                             options::OPT_t, options::OPT_r});
17481ad6265SDimitry Andric 
17581ad6265SDimitry Andric   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
17681ad6265SDimitry Andric 
17781ad6265SDimitry Andric   // TODO: add C++ includes and libs if compiling C++.
17881ad6265SDimitry Andric 
17981ad6265SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib) &&
18081ad6265SDimitry Andric       !Args.hasArg(options::OPT_nodefaultlibs)) {
18181ad6265SDimitry Andric     if (ToolChain.ShouldLinkCXXStdlib(Args))
18281ad6265SDimitry Andric       ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
18381ad6265SDimitry Andric     CmdArgs.push_back("--start-group");
18481ad6265SDimitry Andric     CmdArgs.push_back("-lc");
18581ad6265SDimitry Andric     if (Args.hasArg(options::OPT_msim))
18681ad6265SDimitry Andric       CmdArgs.push_back("-lsemi");
18781ad6265SDimitry Andric     else
18881ad6265SDimitry Andric       CmdArgs.push_back("-lnosys");
18981ad6265SDimitry Andric     CmdArgs.push_back("--end-group");
19081ad6265SDimitry Andric     AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
19181ad6265SDimitry Andric   }
19281ad6265SDimitry Andric 
19381ad6265SDimitry Andric   if (WantCRTs) {
19481ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
19581ad6265SDimitry Andric     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
19681ad6265SDimitry Andric   }
19781ad6265SDimitry Andric 
19881ad6265SDimitry Andric   CmdArgs.push_back("-o");
19981ad6265SDimitry Andric   CmdArgs.push_back(Output.getFilename());
20081ad6265SDimitry Andric   C.addCommand(std::make_unique<Command>(
20181ad6265SDimitry Andric       JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
20281ad6265SDimitry Andric       CmdArgs, Inputs, Output));
20381ad6265SDimitry Andric }
20481ad6265SDimitry Andric // CSKY tools end.
205