1//===--- Haiku.cpp - Haiku 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 "Haiku.h"
10#include "CommonArgs.h"
11#include "clang/Config/config.h"
12#include "clang/Driver/Compilation.h"
13#include "llvm/Support/Path.h"
14
15using namespace clang::driver;
16using namespace clang::driver::tools;
17using namespace clang::driver::toolchains;
18using namespace clang;
19using namespace llvm::opt;
20
21void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
22                                   const InputInfo &Output,
23                                   const InputInfoList &Inputs,
24                                   const ArgList &Args,
25                                   const char *LinkingOutput) const {
26  const auto &ToolChain = static_cast<const Haiku &>(getToolChain());
27  const Driver &D = ToolChain.getDriver();
28  const llvm::Triple::ArchType Arch = ToolChain.getArch();
29  const bool Static = Args.hasArg(options::OPT_static);
30  const bool Shared = Args.hasArg(options::OPT_shared);
31  ArgStringList CmdArgs;
32
33  // Silence warning for "clang -g foo.o -o foo"
34  Args.ClaimAllArgs(options::OPT_g_Group);
35  // and "clang -emit-llvm foo.o -o foo"
36  Args.ClaimAllArgs(options::OPT_emit_llvm);
37  // and for "clang -w foo.o -o foo". Other warning options are already
38  // handled somewhere else.
39  Args.ClaimAllArgs(options::OPT_w);
40
41  // Silence warning for "clang -pie foo.o -o foo"
42  Args.ClaimAllArgs(options::OPT_pie);
43
44  // -rdynamic is a no-op with Haiku. Claim argument to avoid warning.
45  Args.ClaimAllArgs(options::OPT_rdynamic);
46
47  if (!D.SysRoot.empty())
48    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
49
50  CmdArgs.push_back("--eh-frame-hdr");
51  if (Static) {
52    CmdArgs.push_back("-Bstatic");
53  } else {
54    if (Shared)
55      CmdArgs.push_back("-shared");
56    CmdArgs.push_back("--enable-new-dtags");
57  }
58
59  CmdArgs.push_back("-shared");
60
61  if (!Shared)
62    CmdArgs.push_back("--no-undefined");
63
64  if (Arch == llvm::Triple::riscv64)
65    CmdArgs.push_back("-X");
66
67  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
68  if (Output.isFilename()) {
69    CmdArgs.push_back("-o");
70    CmdArgs.push_back(Output.getFilename());
71  }
72
73  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
74                   options::OPT_r)) {
75    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
76    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
77    if (!Shared)
78      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("start_dyn.o")));
79    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("init_term_dyn.o")));
80  }
81
82  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
83                            options::OPT_s, options::OPT_t, options::OPT_r});
84  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
85
86  if (D.isUsingLTO()) {
87    assert(!Inputs.empty() && "Must have at least one input.");
88    // Find the first filename InputInfo object.
89    auto Input = llvm::find_if(
90        Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
91    if (Input == Inputs.end())
92      // For a very rare case, all of the inputs to the linker are
93      // InputArg. If that happens, just use the first InputInfo.
94      Input = Inputs.begin();
95
96    addLTOOptions(ToolChain, Args, CmdArgs, Output, *Input,
97                  D.getLTOMode() == LTOK_Thin);
98  }
99
100  addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
101  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
102
103  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
104                   options::OPT_r)) {
105    // Use the static OpenMP runtime with -static-openmp
106    bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;
107    addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
108
109    if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args))
110      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
111
112    // Silence warnings when linking C code with a C++ '-stdlib' argument.
113    Args.ClaimAllArgs(options::OPT_stdlib_EQ);
114
115    // Additional linker set-up and flags for Fortran. This is required in order
116    // to generate executables. As Fortran runtime depends on the C runtime,
117    // these dependencies need to be listed before the C runtime below (i.e.
118    // AddRunTimeLibs).
119    if (D.IsFlangMode()) {
120      addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
121      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
122    }
123
124    CmdArgs.push_back("-lgcc");
125
126    CmdArgs.push_back("--push-state");
127    CmdArgs.push_back("--as-needed");
128    CmdArgs.push_back("-lgcc_s");
129    CmdArgs.push_back("--no-as-needed");
130    CmdArgs.push_back("--pop-state");
131
132    CmdArgs.push_back("-lroot");
133
134    CmdArgs.push_back("-lgcc");
135
136    CmdArgs.push_back("--push-state");
137    CmdArgs.push_back("--as-needed");
138    CmdArgs.push_back("-lgcc_s");
139    CmdArgs.push_back("--no-as-needed");
140    CmdArgs.push_back("--pop-state");
141  }
142
143  // No need to do anything for pthreads. Claim argument to avoid warning.
144  Args.claimAllArgs(options::OPT_pthread, options::OPT_pthreads);
145
146  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
147                   options::OPT_r)) {
148    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
149    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
150  }
151
152  ToolChain.addProfileRTLibs(Args, CmdArgs);
153
154  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
155  C.addCommand(std::make_unique<Command>(JA, *this,
156                                         ResponseFileSupport::AtFileCurCP(),
157                                         Exec, CmdArgs, Inputs, Output));
158}
159
160/// Haiku - Haiku tool chain which can call as(1) and ld(1) directly.
161
162Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
163  : Generic_ELF(D, Triple, Args) {
164
165  GCCInstallation.init(Triple, Args);
166
167  getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/lib"));
168  getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/develop/lib"));
169
170  if (GCCInstallation.isValid())
171    getFilePaths().push_back(GCCInstallation.getInstallPath().str());
172}
173
174void Haiku::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
175                                      llvm::opt::ArgStringList &CC1Args) const {
176  const Driver &D = getDriver();
177
178  if (DriverArgs.hasArg(options::OPT_nostdinc))
179    return;
180
181  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
182    SmallString<128> Dir(D.ResourceDir);
183    llvm::sys::path::append(Dir, "include");
184    addSystemInclude(DriverArgs, CC1Args, Dir.str());
185  }
186
187  if (DriverArgs.hasArg(options::OPT_nostdlibinc))
188    return;
189
190  // Add dirs specified via 'configure --with-c-include-dirs'.
191  StringRef CIncludeDirs(C_INCLUDE_DIRS);
192  if (!CIncludeDirs.empty()) {
193    SmallVector<StringRef, 5> dirs;
194    CIncludeDirs.split(dirs, ":");
195    for (StringRef dir : dirs) {
196      StringRef Prefix =
197        llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
198      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
199    }
200    return;
201  }
202
203  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
204                   "/boot/system/non-packaged/develop/headers"));
205  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
206                   "/boot/system/develop/headers/os"));
207  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
208                   "/boot/system/develop/headers/os/app"));
209  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
210                   "/boot/system/develop/headers/os/device"));
211  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
212                   "/boot/system/develop/headers/os/drivers"));
213  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
214                   "/boot/system/develop/headers/os/game"));
215  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
216                   "/boot/system/develop/headers/os/interface"));
217  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
218                   "/boot/system/develop/headers/os/kernel"));
219  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
220                   "/boot/system/develop/headers/os/locale"));
221  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
222                   "/boot/system/develop/headers/os/mail"));
223  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
224                   "/boot/system/develop/headers/os/media"));
225  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
226                   "/boot/system/develop/headers/os/midi"));
227  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
228                   "/boot/system/develop/headers/os/midi2"));
229  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
230                   "/boot/system/develop/headers/os/net"));
231  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
232                   "/boot/system/develop/headers/os/opengl"));
233  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
234                   "/boot/system/develop/headers/os/storage"));
235  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
236                   "/boot/system/develop/headers/os/support"));
237  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
238                   "/boot/system/develop/headers/os/translation"));
239  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
240                   "/boot/system/develop/headers/os/add-ons/graphics"));
241  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
242                   "/boot/system/develop/headers/os/add-ons/input_server"));
243  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
244                   "/boot/system/develop/headers/os/add-ons/mail_daemon"));
245  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
246                   "/boot/system/develop/headers/os/add-ons/registrar"));
247  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
248                   "/boot/system/develop/headers/os/add-ons/screen_saver"));
249  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
250                   "/boot/system/develop/headers/os/add-ons/tracker"));
251  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
252                   "/boot/system/develop/headers/os/be_apps/Deskbar"));
253  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
254                   "/boot/system/develop/headers/os/be_apps/NetPositive"));
255  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
256                   "/boot/system/develop/headers/os/be_apps/Tracker"));
257  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
258                   "/boot/system/develop/headers/3rdparty"));
259  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
260                   "/boot/system/develop/headers/bsd"));
261  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
262                   "/boot/system/develop/headers/glibc"));
263  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
264                   "/boot/system/develop/headers/gnu"));
265  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
266                   "/boot/system/develop/headers/posix"));
267  addSystemInclude(DriverArgs, CC1Args, concat(D.SysRoot,
268                   "/boot/system/develop/headers"));
269}
270
271void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
272                                  llvm::opt::ArgStringList &CC1Args) const {
273  addSystemInclude(DriverArgs, CC1Args,
274                   concat(getDriver().SysRoot, "/boot/system/develop/headers/c++/v1"));
275}
276
277Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); }
278
279bool Haiku::HasNativeLLVMSupport() const { return true; }
280