CSKYToolChain.cpp revision 1.1.1.1
1//===--- CSKYToolchain.cpp - CSKY 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 "CSKYToolChain.h"
10#include "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#include "llvm/Support/raw_ostream.h"
18
19using namespace clang::driver;
20using namespace clang::driver::toolchains;
21using namespace clang::driver::tools;
22using namespace clang;
23using namespace llvm::opt;
24
25static 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);
32}
33
34/// CSKY Toolchain
35CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
36                             const ArgList &Args)
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                             SelectedMultilib.osSuffix());
48    ToolChain::path_list &PPaths = getProgramPaths();
49    // Multilib cross-compiler GCC installations put ld in a triple-prefixed
50    // directory off of the parent of the GCC installation.
51    PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
52                           GCCInstallation.getTriple().str() + "/bin")
53                         .str());
54    PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
55  } else {
56    getProgramPaths().push_back(D.Dir);
57  }
58  getFilePaths().push_back(computeSysRoot() + "/lib" +
59                           SelectedMultilib.osSuffix());
60}
61
62Tool *CSKYToolChain::buildLinker() const {
63  return new tools::CSKY::Linker(*this);
64}
65
66ToolChain::RuntimeLibType CSKYToolChain::GetDefaultRuntimeLibType() const {
67  return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
68                                   : ToolChain::RLT_CompilerRT;
69}
70
71ToolChain::UnwindLibType
72CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
73  return ToolChain::UNW_None;
74}
75
76void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
77                                          llvm::opt::ArgStringList &CC1Args,
78                                          Action::OffloadKind) const {
79  CC1Args.push_back("-nostdsysteminc");
80}
81
82void CSKYToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
83                                              ArgStringList &CC1Args) const {
84  if (DriverArgs.hasArg(options::OPT_nostdinc))
85    return;
86
87  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
88    SmallString<128> Dir(computeSysRoot());
89    llvm::sys::path::append(Dir, "include");
90    addSystemInclude(DriverArgs, CC1Args, Dir.str());
91    SmallString<128> Dir2(computeSysRoot());
92    llvm::sys::path::append(Dir2, "sys-include");
93    addSystemInclude(DriverArgs, CC1Args, Dir2.str());
94  }
95}
96
97void CSKYToolChain::addLibStdCxxIncludePaths(
98    const llvm::opt::ArgList &DriverArgs,
99    llvm::opt::ArgStringList &CC1Args) const {
100  const GCCVersion &Version = GCCInstallation.getVersion();
101  StringRef TripleStr = GCCInstallation.getTriple().str();
102  const Multilib &Multilib = GCCInstallation.getMultilib();
103  addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
104                           TripleStr, Multilib.includeSuffix(), DriverArgs,
105                           CC1Args);
106}
107
108std::string CSKYToolChain::computeSysRoot() const {
109  if (!getDriver().SysRoot.empty())
110    return getDriver().SysRoot;
111
112  SmallString<128> SysRootDir;
113  if (GCCInstallation.isValid()) {
114    StringRef LibDir = GCCInstallation.getParentLibPath();
115    StringRef TripleStr = GCCInstallation.getTriple().str();
116    llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
117  } else {
118    // Use the triple as provided to the driver. Unlike the parsed triple
119    // this has not been normalized to always contain every field.
120    llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
121                            getDriver().getTargetTriple());
122  }
123
124  if (!llvm::sys::fs::exists(SysRootDir))
125    return std::string();
126
127  return std::string(SysRootDir.str());
128}
129
130void CSKY::Linker::ConstructJob(Compilation &C, const JobAction &JA,
131                                const InputInfo &Output,
132                                const InputInfoList &Inputs,
133                                const ArgList &Args,
134                                const char *LinkingOutput) const {
135  const ToolChain &ToolChain = getToolChain();
136  const Driver &D = ToolChain.getDriver();
137  ArgStringList CmdArgs;
138
139  if (!D.SysRoot.empty())
140    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
141
142  CmdArgs.push_back("-m");
143  CmdArgs.push_back("cskyelf");
144
145  std::string Linker = getToolChain().GetLinkerPath();
146
147  bool WantCRTs =
148      !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
149
150  const char *crtbegin, *crtend;
151  auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
152  if (RuntimeLib == ToolChain::RLT_Libgcc) {
153    crtbegin = "crtbegin.o";
154    crtend = "crtend.o";
155  } else {
156    assert(RuntimeLib == ToolChain::RLT_CompilerRT);
157    crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
158                                                ToolChain::FT_Object);
159    crtend =
160        ToolChain.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object);
161  }
162
163  if (WantCRTs) {
164    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
165    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
166    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
167  }
168
169  Args.AddAllArgs(CmdArgs, options::OPT_L);
170  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
171  Args.AddAllArgs(CmdArgs,
172                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
173                   options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
174
175  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
176
177  // TODO: add C++ includes and libs if compiling C++.
178
179  if (!Args.hasArg(options::OPT_nostdlib) &&
180      !Args.hasArg(options::OPT_nodefaultlibs)) {
181    if (ToolChain.ShouldLinkCXXStdlib(Args))
182      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
183    CmdArgs.push_back("--start-group");
184    CmdArgs.push_back("-lc");
185    if (Args.hasArg(options::OPT_msim))
186      CmdArgs.push_back("-lsemi");
187    else
188      CmdArgs.push_back("-lnosys");
189    CmdArgs.push_back("--end-group");
190    AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
191  }
192
193  if (WantCRTs) {
194    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
195    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
196  }
197
198  CmdArgs.push_back("-o");
199  CmdArgs.push_back(Output.getFilename());
200  C.addCommand(std::make_unique<Command>(
201      JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
202      CmdArgs, Inputs, Output));
203}
204// CSKY tools end.
205