xref: /openbsd-src/gnu/llvm/clang/lib/Driver/ToolChains/NetBSD.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- NetBSD.cpp - NetBSD ToolChain Implementations ----------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "NetBSD.h"
10e5dd7070Spatrick #include "Arch/ARM.h"
11e5dd7070Spatrick #include "Arch/Mips.h"
12e5dd7070Spatrick #include "Arch/Sparc.h"
13e5dd7070Spatrick #include "CommonArgs.h"
14*12c85518Srobert #include "clang/Config/config.h"
15e5dd7070Spatrick #include "clang/Driver/Compilation.h"
16e5dd7070Spatrick #include "clang/Driver/Driver.h"
17e5dd7070Spatrick #include "clang/Driver/Options.h"
18e5dd7070Spatrick #include "clang/Driver/SanitizerArgs.h"
19e5dd7070Spatrick #include "llvm/Option/ArgList.h"
20e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h"
21e5dd7070Spatrick 
22e5dd7070Spatrick using namespace clang::driver;
23e5dd7070Spatrick using namespace clang::driver::tools;
24e5dd7070Spatrick using namespace clang::driver::toolchains;
25e5dd7070Spatrick using namespace clang;
26e5dd7070Spatrick using namespace llvm::opt;
27e5dd7070Spatrick 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const28e5dd7070Spatrick void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
29e5dd7070Spatrick                                      const InputInfo &Output,
30e5dd7070Spatrick                                      const InputInfoList &Inputs,
31e5dd7070Spatrick                                      const ArgList &Args,
32e5dd7070Spatrick                                      const char *LinkingOutput) const {
33*12c85518Srobert   const toolchains::NetBSD &ToolChain =
34*12c85518Srobert     static_cast<const toolchains::NetBSD &>(getToolChain());
35*12c85518Srobert   const Driver &D = ToolChain.getDriver();
36*12c85518Srobert   const llvm::Triple &Triple = ToolChain.getTriple();
37*12c85518Srobert 
38e5dd7070Spatrick   claimNoWarnArgs(Args);
39e5dd7070Spatrick   ArgStringList CmdArgs;
40e5dd7070Spatrick 
41e5dd7070Spatrick   // GNU as needs different flags for creating the correct output format
42e5dd7070Spatrick   // on architectures with different ABIs or optional feature sets.
43*12c85518Srobert   switch (ToolChain.getArch()) {
44e5dd7070Spatrick   case llvm::Triple::x86:
45e5dd7070Spatrick     CmdArgs.push_back("--32");
46e5dd7070Spatrick     break;
47e5dd7070Spatrick   case llvm::Triple::arm:
48e5dd7070Spatrick   case llvm::Triple::armeb:
49e5dd7070Spatrick   case llvm::Triple::thumb:
50e5dd7070Spatrick   case llvm::Triple::thumbeb: {
51e5dd7070Spatrick     StringRef MArch, MCPU;
52e5dd7070Spatrick     arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
53*12c85518Srobert     std::string Arch = arm::getARMTargetCPU(MCPU, MArch, Triple);
54e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
55e5dd7070Spatrick     break;
56e5dd7070Spatrick   }
57e5dd7070Spatrick 
58e5dd7070Spatrick   case llvm::Triple::mips:
59e5dd7070Spatrick   case llvm::Triple::mipsel:
60e5dd7070Spatrick   case llvm::Triple::mips64:
61e5dd7070Spatrick   case llvm::Triple::mips64el: {
62e5dd7070Spatrick     StringRef CPUName;
63e5dd7070Spatrick     StringRef ABIName;
64*12c85518Srobert     mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
65e5dd7070Spatrick 
66e5dd7070Spatrick     CmdArgs.push_back("-march");
67e5dd7070Spatrick     CmdArgs.push_back(CPUName.data());
68e5dd7070Spatrick 
69e5dd7070Spatrick     CmdArgs.push_back("-mabi");
70e5dd7070Spatrick     CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
71e5dd7070Spatrick 
72*12c85518Srobert     if (Triple.isLittleEndian())
73e5dd7070Spatrick       CmdArgs.push_back("-EL");
74e5dd7070Spatrick     else
75e5dd7070Spatrick       CmdArgs.push_back("-EB");
76e5dd7070Spatrick 
77*12c85518Srobert     AddAssemblerKPIC(ToolChain, Args, CmdArgs);
78e5dd7070Spatrick     break;
79e5dd7070Spatrick   }
80e5dd7070Spatrick 
81e5dd7070Spatrick   case llvm::Triple::sparc:
82e5dd7070Spatrick   case llvm::Triple::sparcel: {
83e5dd7070Spatrick     CmdArgs.push_back("-32");
84*12c85518Srobert     std::string CPU = getCPUName(D, Args, Triple);
85*12c85518Srobert     CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));
86*12c85518Srobert     AddAssemblerKPIC(ToolChain, Args, CmdArgs);
87e5dd7070Spatrick     break;
88e5dd7070Spatrick   }
89e5dd7070Spatrick 
90e5dd7070Spatrick   case llvm::Triple::sparcv9: {
91e5dd7070Spatrick     CmdArgs.push_back("-64");
92*12c85518Srobert     std::string CPU = getCPUName(D, Args, Triple);
93*12c85518Srobert     CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));
94*12c85518Srobert     AddAssemblerKPIC(ToolChain, Args, CmdArgs);
95e5dd7070Spatrick     break;
96e5dd7070Spatrick   }
97e5dd7070Spatrick 
98e5dd7070Spatrick   default:
99e5dd7070Spatrick     break;
100e5dd7070Spatrick   }
101e5dd7070Spatrick 
102e5dd7070Spatrick   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
103e5dd7070Spatrick 
104e5dd7070Spatrick   CmdArgs.push_back("-o");
105e5dd7070Spatrick   CmdArgs.push_back(Output.getFilename());
106e5dd7070Spatrick 
107e5dd7070Spatrick   for (const auto &II : Inputs)
108e5dd7070Spatrick     CmdArgs.push_back(II.getFilename());
109e5dd7070Spatrick 
110*12c85518Srobert   const char *Exec = Args.MakeArgString((ToolChain.GetProgramPath("as")));
111a9ac8606Spatrick   C.addCommand(std::make_unique<Command>(JA, *this,
112a9ac8606Spatrick                                          ResponseFileSupport::AtFileCurCP(),
113a9ac8606Spatrick                                          Exec, CmdArgs, Inputs, Output));
114e5dd7070Spatrick }
115e5dd7070Spatrick 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const116e5dd7070Spatrick void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
117e5dd7070Spatrick                                   const InputInfo &Output,
118e5dd7070Spatrick                                   const InputInfoList &Inputs,
119e5dd7070Spatrick                                   const ArgList &Args,
120e5dd7070Spatrick                                   const char *LinkingOutput) const {
121e5dd7070Spatrick   const toolchains::NetBSD &ToolChain =
122e5dd7070Spatrick     static_cast<const toolchains::NetBSD &>(getToolChain());
123e5dd7070Spatrick   const Driver &D = ToolChain.getDriver();
124*12c85518Srobert   const llvm::Triple &Triple = ToolChain.getTriple();
125*12c85518Srobert 
126e5dd7070Spatrick   ArgStringList CmdArgs;
127e5dd7070Spatrick 
128e5dd7070Spatrick   if (!D.SysRoot.empty())
129e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
130e5dd7070Spatrick 
131e5dd7070Spatrick   CmdArgs.push_back("--eh-frame-hdr");
132e5dd7070Spatrick   if (Args.hasArg(options::OPT_static)) {
133e5dd7070Spatrick     CmdArgs.push_back("-Bstatic");
134e5dd7070Spatrick     if (Args.hasArg(options::OPT_pie)) {
135e5dd7070Spatrick       Args.AddAllArgs(CmdArgs, options::OPT_pie);
136e5dd7070Spatrick       CmdArgs.push_back("--no-dynamic-linker");
137e5dd7070Spatrick     }
138e5dd7070Spatrick   } else {
139e5dd7070Spatrick     if (Args.hasArg(options::OPT_rdynamic))
140e5dd7070Spatrick       CmdArgs.push_back("-export-dynamic");
141e5dd7070Spatrick     if (Args.hasArg(options::OPT_shared)) {
142e5dd7070Spatrick       CmdArgs.push_back("-Bshareable");
143*12c85518Srobert     } else if (!Args.hasArg(options::OPT_r)) {
144e5dd7070Spatrick       Args.AddAllArgs(CmdArgs, options::OPT_pie);
145e5dd7070Spatrick       CmdArgs.push_back("-dynamic-linker");
146e5dd7070Spatrick       CmdArgs.push_back("/libexec/ld.elf_so");
147e5dd7070Spatrick     }
148e5dd7070Spatrick   }
149e5dd7070Spatrick 
150e5dd7070Spatrick   // Many NetBSD architectures support more than one ABI.
151e5dd7070Spatrick   // Determine the correct emulation for ld.
152e5dd7070Spatrick   switch (ToolChain.getArch()) {
153e5dd7070Spatrick   case llvm::Triple::x86:
154e5dd7070Spatrick     CmdArgs.push_back("-m");
155e5dd7070Spatrick     CmdArgs.push_back("elf_i386");
156e5dd7070Spatrick     break;
157e5dd7070Spatrick   case llvm::Triple::arm:
158e5dd7070Spatrick   case llvm::Triple::thumb:
159e5dd7070Spatrick     CmdArgs.push_back("-m");
160*12c85518Srobert     switch (Triple.getEnvironment()) {
161e5dd7070Spatrick     case llvm::Triple::EABI:
162e5dd7070Spatrick     case llvm::Triple::GNUEABI:
163e5dd7070Spatrick       CmdArgs.push_back("armelf_nbsd_eabi");
164e5dd7070Spatrick       break;
165e5dd7070Spatrick     case llvm::Triple::EABIHF:
166e5dd7070Spatrick     case llvm::Triple::GNUEABIHF:
167e5dd7070Spatrick       CmdArgs.push_back("armelf_nbsd_eabihf");
168e5dd7070Spatrick       break;
169e5dd7070Spatrick     default:
170e5dd7070Spatrick       CmdArgs.push_back("armelf_nbsd");
171e5dd7070Spatrick       break;
172e5dd7070Spatrick     }
173e5dd7070Spatrick     break;
174e5dd7070Spatrick   case llvm::Triple::armeb:
175e5dd7070Spatrick   case llvm::Triple::thumbeb:
176e5dd7070Spatrick     arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple());
177e5dd7070Spatrick     CmdArgs.push_back("-m");
178*12c85518Srobert     switch (Triple.getEnvironment()) {
179e5dd7070Spatrick     case llvm::Triple::EABI:
180e5dd7070Spatrick     case llvm::Triple::GNUEABI:
181e5dd7070Spatrick       CmdArgs.push_back("armelfb_nbsd_eabi");
182e5dd7070Spatrick       break;
183e5dd7070Spatrick     case llvm::Triple::EABIHF:
184e5dd7070Spatrick     case llvm::Triple::GNUEABIHF:
185e5dd7070Spatrick       CmdArgs.push_back("armelfb_nbsd_eabihf");
186e5dd7070Spatrick       break;
187e5dd7070Spatrick     default:
188e5dd7070Spatrick       CmdArgs.push_back("armelfb_nbsd");
189e5dd7070Spatrick       break;
190e5dd7070Spatrick     }
191e5dd7070Spatrick     break;
192e5dd7070Spatrick   case llvm::Triple::mips64:
193e5dd7070Spatrick   case llvm::Triple::mips64el:
194e5dd7070Spatrick     if (mips::hasMipsAbiArg(Args, "32")) {
195e5dd7070Spatrick       CmdArgs.push_back("-m");
196e5dd7070Spatrick       if (ToolChain.getArch() == llvm::Triple::mips64)
197e5dd7070Spatrick         CmdArgs.push_back("elf32btsmip");
198e5dd7070Spatrick       else
199e5dd7070Spatrick         CmdArgs.push_back("elf32ltsmip");
200e5dd7070Spatrick     } else if (mips::hasMipsAbiArg(Args, "64")) {
201e5dd7070Spatrick       CmdArgs.push_back("-m");
202e5dd7070Spatrick       if (ToolChain.getArch() == llvm::Triple::mips64)
203e5dd7070Spatrick         CmdArgs.push_back("elf64btsmip");
204e5dd7070Spatrick       else
205e5dd7070Spatrick         CmdArgs.push_back("elf64ltsmip");
206e5dd7070Spatrick     }
207e5dd7070Spatrick     break;
208e5dd7070Spatrick   case llvm::Triple::ppc:
209e5dd7070Spatrick     CmdArgs.push_back("-m");
210e5dd7070Spatrick     CmdArgs.push_back("elf32ppc_nbsd");
211e5dd7070Spatrick     break;
212e5dd7070Spatrick 
213e5dd7070Spatrick   case llvm::Triple::ppc64:
214e5dd7070Spatrick   case llvm::Triple::ppc64le:
215e5dd7070Spatrick     CmdArgs.push_back("-m");
216e5dd7070Spatrick     CmdArgs.push_back("elf64ppc");
217e5dd7070Spatrick     break;
218e5dd7070Spatrick 
219e5dd7070Spatrick   case llvm::Triple::sparc:
220e5dd7070Spatrick     CmdArgs.push_back("-m");
221e5dd7070Spatrick     CmdArgs.push_back("elf32_sparc");
222e5dd7070Spatrick     break;
223e5dd7070Spatrick 
224e5dd7070Spatrick   case llvm::Triple::sparcv9:
225e5dd7070Spatrick     CmdArgs.push_back("-m");
226e5dd7070Spatrick     CmdArgs.push_back("elf64_sparc");
227e5dd7070Spatrick     break;
228e5dd7070Spatrick 
229e5dd7070Spatrick   default:
230e5dd7070Spatrick     break;
231e5dd7070Spatrick   }
232e5dd7070Spatrick 
233e5dd7070Spatrick   if (Output.isFilename()) {
234e5dd7070Spatrick     CmdArgs.push_back("-o");
235e5dd7070Spatrick     CmdArgs.push_back(Output.getFilename());
236e5dd7070Spatrick   } else {
237e5dd7070Spatrick     assert(Output.isNothing() && "Invalid output.");
238e5dd7070Spatrick   }
239e5dd7070Spatrick 
240*12c85518Srobert   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
241*12c85518Srobert                    options::OPT_r)) {
242e5dd7070Spatrick     if (!Args.hasArg(options::OPT_shared)) {
243e5dd7070Spatrick       CmdArgs.push_back(
244e5dd7070Spatrick           Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
245e5dd7070Spatrick     }
246e5dd7070Spatrick     CmdArgs.push_back(
247e5dd7070Spatrick         Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
248e5dd7070Spatrick     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
249e5dd7070Spatrick       CmdArgs.push_back(
250e5dd7070Spatrick           Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
251e5dd7070Spatrick     } else {
252e5dd7070Spatrick       CmdArgs.push_back(
253e5dd7070Spatrick           Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
254e5dd7070Spatrick     }
255e5dd7070Spatrick   }
256e5dd7070Spatrick 
257e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_L);
258e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
259e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_e);
260e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_s);
261e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_t);
262e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
263e5dd7070Spatrick   Args.AddAllArgs(CmdArgs, options::OPT_r);
264e5dd7070Spatrick 
265*12c85518Srobert   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
266e5dd7070Spatrick   bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
267*12c85518Srobert   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
268e5dd7070Spatrick 
269*12c85518Srobert   const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
270e5dd7070Spatrick   if (SanArgs.needsSharedRt()) {
271e5dd7070Spatrick     CmdArgs.push_back("-rpath");
272*12c85518Srobert     CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath()));
273e5dd7070Spatrick   }
274e5dd7070Spatrick 
275*12c85518Srobert   VersionTuple OsVersion = Triple.getOSVersion();
276e5dd7070Spatrick   bool useLibgcc = true;
277*12c85518Srobert   if (OsVersion >= VersionTuple(7) || OsVersion.getMajor() == 0) {
278e5dd7070Spatrick     switch (ToolChain.getArch()) {
279e5dd7070Spatrick     case llvm::Triple::aarch64:
280e5dd7070Spatrick     case llvm::Triple::aarch64_be:
281e5dd7070Spatrick     case llvm::Triple::arm:
282e5dd7070Spatrick     case llvm::Triple::armeb:
283e5dd7070Spatrick     case llvm::Triple::thumb:
284e5dd7070Spatrick     case llvm::Triple::thumbeb:
285e5dd7070Spatrick     case llvm::Triple::ppc:
286e5dd7070Spatrick     case llvm::Triple::ppc64:
287e5dd7070Spatrick     case llvm::Triple::ppc64le:
288e5dd7070Spatrick     case llvm::Triple::sparc:
289e5dd7070Spatrick     case llvm::Triple::sparcv9:
290e5dd7070Spatrick     case llvm::Triple::x86:
291e5dd7070Spatrick     case llvm::Triple::x86_64:
292e5dd7070Spatrick       useLibgcc = false;
293e5dd7070Spatrick       break;
294e5dd7070Spatrick     default:
295e5dd7070Spatrick       break;
296e5dd7070Spatrick     }
297e5dd7070Spatrick   }
298e5dd7070Spatrick 
299*12c85518Srobert   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
300*12c85518Srobert                    options::OPT_r)) {
301e5dd7070Spatrick     // Use the static OpenMP runtime with -static-openmp
302e5dd7070Spatrick     bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
303e5dd7070Spatrick                         !Args.hasArg(options::OPT_static);
304*12c85518Srobert     addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
305e5dd7070Spatrick 
306e5dd7070Spatrick     if (D.CCCIsCXX()) {
307e5dd7070Spatrick       if (ToolChain.ShouldLinkCXXStdlib(Args))
308e5dd7070Spatrick         ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
309e5dd7070Spatrick       CmdArgs.push_back("-lm");
310e5dd7070Spatrick     }
311e5dd7070Spatrick     if (NeedsSanitizerDeps)
312*12c85518Srobert       linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
313e5dd7070Spatrick     if (NeedsXRayDeps)
314e5dd7070Spatrick       linkXRayRuntimeDeps(ToolChain, CmdArgs);
315e5dd7070Spatrick     if (Args.hasArg(options::OPT_pthread))
316e5dd7070Spatrick       CmdArgs.push_back("-lpthread");
317e5dd7070Spatrick     CmdArgs.push_back("-lc");
318e5dd7070Spatrick 
319e5dd7070Spatrick     if (useLibgcc) {
320e5dd7070Spatrick       if (Args.hasArg(options::OPT_static)) {
321e5dd7070Spatrick         // libgcc_eh depends on libc, so resolve as much as possible,
322e5dd7070Spatrick         // pull in any new requirements from libc and then get the rest
323e5dd7070Spatrick         // of libgcc.
324e5dd7070Spatrick         CmdArgs.push_back("-lgcc_eh");
325e5dd7070Spatrick         CmdArgs.push_back("-lc");
326e5dd7070Spatrick         CmdArgs.push_back("-lgcc");
327e5dd7070Spatrick       } else {
328e5dd7070Spatrick         CmdArgs.push_back("-lgcc");
329e5dd7070Spatrick         CmdArgs.push_back("--as-needed");
330e5dd7070Spatrick         CmdArgs.push_back("-lgcc_s");
331e5dd7070Spatrick         CmdArgs.push_back("--no-as-needed");
332e5dd7070Spatrick       }
333e5dd7070Spatrick     }
334e5dd7070Spatrick   }
335e5dd7070Spatrick 
336*12c85518Srobert   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
337*12c85518Srobert                    options::OPT_r)) {
338e5dd7070Spatrick     if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
339e5dd7070Spatrick       CmdArgs.push_back(
340e5dd7070Spatrick           Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
341e5dd7070Spatrick     else
342e5dd7070Spatrick       CmdArgs.push_back(
343e5dd7070Spatrick           Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
344e5dd7070Spatrick     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
345e5dd7070Spatrick   }
346e5dd7070Spatrick 
347e5dd7070Spatrick   ToolChain.addProfileRTLibs(Args, CmdArgs);
348e5dd7070Spatrick 
349e5dd7070Spatrick   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
350a9ac8606Spatrick   C.addCommand(std::make_unique<Command>(JA, *this,
351a9ac8606Spatrick                                          ResponseFileSupport::AtFileCurCP(),
352a9ac8606Spatrick                                          Exec, CmdArgs, Inputs, Output));
353e5dd7070Spatrick }
354e5dd7070Spatrick 
355e5dd7070Spatrick /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
356e5dd7070Spatrick 
NetBSD(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)357e5dd7070Spatrick NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
358e5dd7070Spatrick     : Generic_ELF(D, Triple, Args) {
359e5dd7070Spatrick   if (!Args.hasArg(options::OPT_nostdlib)) {
360e5dd7070Spatrick     // When targeting a 32-bit platform, try the special directory used on
361e5dd7070Spatrick     // 64-bit hosts, and only fall back to the main library directory if that
362e5dd7070Spatrick     // doesn't work.
363e5dd7070Spatrick     // FIXME: It'd be nicer to test if this directory exists, but I'm not sure
364e5dd7070Spatrick     // what all logic is needed to emulate the '=' prefix here.
365e5dd7070Spatrick     switch (Triple.getArch()) {
366e5dd7070Spatrick     case llvm::Triple::x86:
367e5dd7070Spatrick       getFilePaths().push_back("=/usr/lib/i386");
368e5dd7070Spatrick       break;
369e5dd7070Spatrick     case llvm::Triple::arm:
370e5dd7070Spatrick     case llvm::Triple::armeb:
371e5dd7070Spatrick     case llvm::Triple::thumb:
372e5dd7070Spatrick     case llvm::Triple::thumbeb:
373e5dd7070Spatrick       switch (Triple.getEnvironment()) {
374e5dd7070Spatrick       case llvm::Triple::EABI:
375e5dd7070Spatrick       case llvm::Triple::GNUEABI:
376e5dd7070Spatrick         getFilePaths().push_back("=/usr/lib/eabi");
377e5dd7070Spatrick         break;
378e5dd7070Spatrick       case llvm::Triple::EABIHF:
379e5dd7070Spatrick       case llvm::Triple::GNUEABIHF:
380e5dd7070Spatrick         getFilePaths().push_back("=/usr/lib/eabihf");
381e5dd7070Spatrick         break;
382e5dd7070Spatrick       default:
383e5dd7070Spatrick         getFilePaths().push_back("=/usr/lib/oabi");
384e5dd7070Spatrick         break;
385e5dd7070Spatrick       }
386e5dd7070Spatrick       break;
387e5dd7070Spatrick     case llvm::Triple::mips64:
388e5dd7070Spatrick     case llvm::Triple::mips64el:
389e5dd7070Spatrick       if (tools::mips::hasMipsAbiArg(Args, "o32"))
390e5dd7070Spatrick         getFilePaths().push_back("=/usr/lib/o32");
391e5dd7070Spatrick       else if (tools::mips::hasMipsAbiArg(Args, "64"))
392e5dd7070Spatrick         getFilePaths().push_back("=/usr/lib/64");
393e5dd7070Spatrick       break;
394e5dd7070Spatrick     case llvm::Triple::ppc:
395e5dd7070Spatrick       getFilePaths().push_back("=/usr/lib/powerpc");
396e5dd7070Spatrick       break;
397e5dd7070Spatrick     case llvm::Triple::sparc:
398e5dd7070Spatrick       getFilePaths().push_back("=/usr/lib/sparc");
399e5dd7070Spatrick       break;
400e5dd7070Spatrick     default:
401e5dd7070Spatrick       break;
402e5dd7070Spatrick     }
403e5dd7070Spatrick 
404e5dd7070Spatrick     getFilePaths().push_back("=/usr/lib");
405e5dd7070Spatrick   }
406e5dd7070Spatrick }
407e5dd7070Spatrick 
buildAssembler() const408e5dd7070Spatrick Tool *NetBSD::buildAssembler() const {
409e5dd7070Spatrick   return new tools::netbsd::Assembler(*this);
410e5dd7070Spatrick }
411e5dd7070Spatrick 
buildLinker() const412e5dd7070Spatrick Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
413e5dd7070Spatrick 
GetDefaultCXXStdlibType() const414e5dd7070Spatrick ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const {
415*12c85518Srobert   VersionTuple OsVersion = getTriple().getOSVersion();
416*12c85518Srobert   if (OsVersion >= VersionTuple(7) || OsVersion.getMajor() == 0) {
417e5dd7070Spatrick     switch (getArch()) {
418e5dd7070Spatrick     case llvm::Triple::aarch64:
419e5dd7070Spatrick     case llvm::Triple::aarch64_be:
420e5dd7070Spatrick     case llvm::Triple::arm:
421e5dd7070Spatrick     case llvm::Triple::armeb:
422e5dd7070Spatrick     case llvm::Triple::thumb:
423e5dd7070Spatrick     case llvm::Triple::thumbeb:
424e5dd7070Spatrick     case llvm::Triple::ppc:
425e5dd7070Spatrick     case llvm::Triple::ppc64:
426e5dd7070Spatrick     case llvm::Triple::ppc64le:
427e5dd7070Spatrick     case llvm::Triple::sparc:
428e5dd7070Spatrick     case llvm::Triple::sparcv9:
429e5dd7070Spatrick     case llvm::Triple::x86:
430e5dd7070Spatrick     case llvm::Triple::x86_64:
431e5dd7070Spatrick       return ToolChain::CST_Libcxx;
432e5dd7070Spatrick     default:
433e5dd7070Spatrick       break;
434e5dd7070Spatrick     }
435e5dd7070Spatrick   }
436e5dd7070Spatrick   return ToolChain::CST_Libstdcxx;
437e5dd7070Spatrick }
438e5dd7070Spatrick 
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const439*12c85518Srobert void NetBSD::AddClangSystemIncludeArgs(
440*12c85518Srobert     const llvm::opt::ArgList &DriverArgs,
441*12c85518Srobert     llvm::opt::ArgStringList &CC1Args) const {
442*12c85518Srobert   const Driver &D = getDriver();
443*12c85518Srobert 
444*12c85518Srobert   if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
445*12c85518Srobert     return;
446*12c85518Srobert 
447*12c85518Srobert   if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
448*12c85518Srobert     SmallString<128> Dir(D.ResourceDir);
449*12c85518Srobert     llvm::sys::path::append(Dir, "include");
450*12c85518Srobert     addSystemInclude(DriverArgs, CC1Args, Dir.str());
451*12c85518Srobert   }
452*12c85518Srobert 
453*12c85518Srobert   if (DriverArgs.hasArg(options::OPT_nostdlibinc))
454*12c85518Srobert     return;
455*12c85518Srobert 
456*12c85518Srobert   // Check for configure-time C include directories.
457*12c85518Srobert   StringRef CIncludeDirs(C_INCLUDE_DIRS);
458*12c85518Srobert   if (CIncludeDirs != "") {
459*12c85518Srobert     SmallVector<StringRef, 5> dirs;
460*12c85518Srobert     CIncludeDirs.split(dirs, ":");
461*12c85518Srobert     for (StringRef dir : dirs) {
462*12c85518Srobert       StringRef Prefix =
463*12c85518Srobert           llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : "";
464*12c85518Srobert       addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
465*12c85518Srobert     }
466*12c85518Srobert     return;
467*12c85518Srobert   }
468*12c85518Srobert 
469*12c85518Srobert   addExternCSystemInclude(DriverArgs, CC1Args,
470*12c85518Srobert                           concat(D.SysRoot, "/usr/include"));
471*12c85518Srobert }
472*12c85518Srobert 
addLibCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const473e5dd7070Spatrick void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
474e5dd7070Spatrick                                    llvm::opt::ArgStringList &CC1Args) const {
475e5dd7070Spatrick   const std::string Candidates[] = {
476e5dd7070Spatrick     // directory relative to build tree
477e5dd7070Spatrick     getDriver().Dir + "/../include/c++/v1",
478e5dd7070Spatrick     // system install with full upstream path
479e5dd7070Spatrick     getDriver().SysRoot + "/usr/include/c++/v1",
480e5dd7070Spatrick     // system install from src
481e5dd7070Spatrick     getDriver().SysRoot + "/usr/include/c++",
482e5dd7070Spatrick   };
483e5dd7070Spatrick 
484e5dd7070Spatrick   for (const auto &IncludePath : Candidates) {
485e5dd7070Spatrick     if (!getVFS().exists(IncludePath + "/__config"))
486e5dd7070Spatrick       continue;
487e5dd7070Spatrick 
488e5dd7070Spatrick     // Use the first candidate that looks valid.
489e5dd7070Spatrick     addSystemInclude(DriverArgs, CC1Args, IncludePath);
490e5dd7070Spatrick     return;
491e5dd7070Spatrick   }
492e5dd7070Spatrick }
493e5dd7070Spatrick 
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const494e5dd7070Spatrick void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
495e5dd7070Spatrick                                       llvm::opt::ArgStringList &CC1Args) const {
496a9ac8606Spatrick   addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/g++", "", "",
497a9ac8606Spatrick                            DriverArgs, CC1Args);
498e5dd7070Spatrick }
499e5dd7070Spatrick 
GetExceptionModel(const ArgList & Args) const500e5dd7070Spatrick llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
501e5dd7070Spatrick   // NetBSD uses Dwarf exceptions on ARM.
502e5dd7070Spatrick   llvm::Triple::ArchType TArch = getTriple().getArch();
503e5dd7070Spatrick   if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb ||
504e5dd7070Spatrick       TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb)
505e5dd7070Spatrick     return llvm::ExceptionHandling::DwarfCFI;
506e5dd7070Spatrick   return llvm::ExceptionHandling::None;
507e5dd7070Spatrick }
508e5dd7070Spatrick 
getSupportedSanitizers() const509e5dd7070Spatrick SanitizerMask NetBSD::getSupportedSanitizers() const {
510e5dd7070Spatrick   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
511e5dd7070Spatrick   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
512e5dd7070Spatrick   SanitizerMask Res = ToolChain::getSupportedSanitizers();
513e5dd7070Spatrick   if (IsX86 || IsX86_64) {
514e5dd7070Spatrick     Res |= SanitizerKind::Address;
515e5dd7070Spatrick     Res |= SanitizerKind::PointerCompare;
516e5dd7070Spatrick     Res |= SanitizerKind::PointerSubtract;
517e5dd7070Spatrick     Res |= SanitizerKind::Function;
518e5dd7070Spatrick     Res |= SanitizerKind::Leak;
519e5dd7070Spatrick     Res |= SanitizerKind::SafeStack;
520e5dd7070Spatrick     Res |= SanitizerKind::Scudo;
521e5dd7070Spatrick     Res |= SanitizerKind::Vptr;
522e5dd7070Spatrick   }
523e5dd7070Spatrick   if (IsX86_64) {
524e5dd7070Spatrick     Res |= SanitizerKind::DataFlow;
525e5dd7070Spatrick     Res |= SanitizerKind::Fuzzer;
526e5dd7070Spatrick     Res |= SanitizerKind::FuzzerNoLink;
527e5dd7070Spatrick     Res |= SanitizerKind::HWAddress;
528e5dd7070Spatrick     Res |= SanitizerKind::KernelAddress;
529e5dd7070Spatrick     Res |= SanitizerKind::KernelHWAddress;
530e5dd7070Spatrick     Res |= SanitizerKind::KernelMemory;
531e5dd7070Spatrick     Res |= SanitizerKind::Memory;
532e5dd7070Spatrick     Res |= SanitizerKind::Thread;
533e5dd7070Spatrick   }
534e5dd7070Spatrick   return Res;
535e5dd7070Spatrick }
536e5dd7070Spatrick 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const537e5dd7070Spatrick void NetBSD::addClangTargetOptions(const ArgList &DriverArgs,
538e5dd7070Spatrick                                    ArgStringList &CC1Args,
539e5dd7070Spatrick                                    Action::OffloadKind) const {
540*12c85518Srobert   const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs);
541e5dd7070Spatrick   if (SanArgs.hasAnySanitizer())
542e5dd7070Spatrick     CC1Args.push_back("-D_REENTRANT");
543e5dd7070Spatrick 
544*12c85518Srobert   VersionTuple OsVersion = getTriple().getOSVersion();
545e5dd7070Spatrick   bool UseInitArrayDefault =
546*12c85518Srobert       OsVersion >= VersionTuple(9) || OsVersion.getMajor() == 0 ||
547e5dd7070Spatrick       getTriple().getArch() == llvm::Triple::aarch64 ||
548e5dd7070Spatrick       getTriple().getArch() == llvm::Triple::aarch64_be ||
549e5dd7070Spatrick       getTriple().getArch() == llvm::Triple::arm ||
550e5dd7070Spatrick       getTriple().getArch() == llvm::Triple::armeb;
551e5dd7070Spatrick 
552e5dd7070Spatrick   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
553e5dd7070Spatrick                           options::OPT_fno_use_init_array, UseInitArrayDefault))
554e5dd7070Spatrick     CC1Args.push_back("-fno-use-init-array");
555e5dd7070Spatrick }
556