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