1 //===--- NetBSD.cpp - NetBSD ToolChain Implementations ----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
11 #include "Arch/Mips.h"
12 #include "Arch/Sparc.h"
13 #include "CommonArgs.h"
14 #include "clang/Driver/Compilation.h"
15 #include "clang/Driver/Driver.h"
16 #include "clang/Driver/Options.h"
17 #include "clang/Driver/SanitizerArgs.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Support/VirtualFileSystem.h"
21 using namespace clang::driver
;
22 using namespace clang::driver::tools
;
23 using namespace clang::driver::toolchains
;
24 using namespace clang
;
25 using namespace llvm::opt
;
27 void netbsd::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
28 const InputInfo
&Output
,
29 const InputInfoList
&Inputs
,
31 const char *LinkingOutput
) const {
32 const toolchains::NetBSD
&ToolChain
=
33 static_cast<const toolchains::NetBSD
&>(getToolChain());
34 const Driver
&D
= ToolChain
.getDriver();
35 const llvm::Triple
&Triple
= ToolChain
.getTriple();
37 claimNoWarnArgs(Args
);
38 ArgStringList CmdArgs
;
40 // GNU as needs different flags for creating the correct output format
41 // on architectures with different ABIs or optional feature sets.
42 switch (ToolChain
.getArch()) {
43 case llvm::Triple::x86
:
44 CmdArgs
.push_back("--32");
46 case llvm::Triple::arm
:
47 case llvm::Triple::armeb
:
48 case llvm::Triple::thumb
:
49 case llvm::Triple::thumbeb
: {
50 StringRef MArch
, MCPU
;
51 arm::getARMArchCPUFromArgs(Args
, MArch
, MCPU
, /*FromAs*/ true);
52 std::string Arch
= arm::getARMTargetCPU(MCPU
, MArch
, Triple
);
53 CmdArgs
.push_back(Args
.MakeArgString("-mcpu=" + Arch
));
57 case llvm::Triple::mips
:
58 case llvm::Triple::mipsel
:
59 case llvm::Triple::mips64
:
60 case llvm::Triple::mips64el
: {
63 mips::getMipsCPUAndABI(Args
, Triple
, CPUName
, ABIName
);
65 CmdArgs
.push_back("-march");
66 CmdArgs
.push_back(CPUName
.data());
68 CmdArgs
.push_back("-mabi");
69 CmdArgs
.push_back(mips::getGnuCompatibleMipsABIName(ABIName
).data());
71 if (Triple
.isLittleEndian())
72 CmdArgs
.push_back("-EL");
74 CmdArgs
.push_back("-EB");
76 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
80 case llvm::Triple::sparc
:
81 case llvm::Triple::sparcel
: {
82 CmdArgs
.push_back("-32");
83 std::string CPU
= getCPUName(D
, Args
, Triple
);
84 CmdArgs
.push_back(sparc::getSparcAsmModeForCPU(CPU
, Triple
));
85 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
89 case llvm::Triple::sparcv9
: {
90 CmdArgs
.push_back("-64");
91 std::string CPU
= getCPUName(D
, Args
, Triple
);
92 CmdArgs
.push_back(sparc::getSparcAsmModeForCPU(CPU
, Triple
));
93 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
101 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
103 CmdArgs
.push_back("-o");
104 CmdArgs
.push_back(Output
.getFilename());
106 for (const auto &II
: Inputs
)
107 CmdArgs
.push_back(II
.getFilename());
109 const char *Exec
= Args
.MakeArgString((ToolChain
.GetProgramPath("as")));
110 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
111 ResponseFileSupport::AtFileCurCP(),
112 Exec
, CmdArgs
, Inputs
, Output
));
115 void netbsd::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
116 const InputInfo
&Output
,
117 const InputInfoList
&Inputs
,
119 const char *LinkingOutput
) const {
120 const toolchains::NetBSD
&ToolChain
=
121 static_cast<const toolchains::NetBSD
&>(getToolChain());
122 const Driver
&D
= ToolChain
.getDriver();
123 const llvm::Triple
&Triple
= ToolChain
.getTriple();
125 ArgStringList CmdArgs
;
127 if (!D
.SysRoot
.empty())
128 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
130 CmdArgs
.push_back("--eh-frame-hdr");
131 if (Args
.hasArg(options::OPT_static
)) {
132 CmdArgs
.push_back("-Bstatic");
133 if (Args
.hasArg(options::OPT_pie
)) {
134 Args
.AddAllArgs(CmdArgs
, options::OPT_pie
);
135 CmdArgs
.push_back("--no-dynamic-linker");
138 if (Args
.hasArg(options::OPT_rdynamic
))
139 CmdArgs
.push_back("-export-dynamic");
140 if (Args
.hasArg(options::OPT_shared
)) {
141 CmdArgs
.push_back("-Bshareable");
142 } else if (!Args
.hasArg(options::OPT_r
)) {
143 Args
.AddAllArgs(CmdArgs
, options::OPT_pie
);
144 CmdArgs
.push_back("-dynamic-linker");
145 CmdArgs
.push_back("/libexec/ld.elf_so");
149 // Many NetBSD architectures support more than one ABI.
150 // Determine the correct emulation for ld.
151 switch (ToolChain
.getArch()) {
152 case llvm::Triple::x86
:
153 CmdArgs
.push_back("-m");
154 CmdArgs
.push_back("elf_i386");
156 case llvm::Triple::arm
:
157 case llvm::Triple::thumb
:
158 CmdArgs
.push_back("-m");
159 switch (Triple
.getEnvironment()) {
160 case llvm::Triple::EABI
:
161 case llvm::Triple::GNUEABI
:
162 CmdArgs
.push_back("armelf_nbsd_eabi");
164 case llvm::Triple::EABIHF
:
165 case llvm::Triple::GNUEABIHF
:
166 CmdArgs
.push_back("armelf_nbsd_eabihf");
169 CmdArgs
.push_back("armelf_nbsd");
173 case llvm::Triple::armeb
:
174 case llvm::Triple::thumbeb
:
175 arm::appendBE8LinkFlag(Args
, CmdArgs
, ToolChain
.getEffectiveTriple());
176 CmdArgs
.push_back("-m");
177 switch (Triple
.getEnvironment()) {
178 case llvm::Triple::EABI
:
179 case llvm::Triple::GNUEABI
:
180 CmdArgs
.push_back("armelfb_nbsd_eabi");
182 case llvm::Triple::EABIHF
:
183 case llvm::Triple::GNUEABIHF
:
184 CmdArgs
.push_back("armelfb_nbsd_eabihf");
187 CmdArgs
.push_back("armelfb_nbsd");
191 case llvm::Triple::mips64
:
192 case llvm::Triple::mips64el
:
193 if (mips::hasMipsAbiArg(Args
, "32")) {
194 CmdArgs
.push_back("-m");
195 if (ToolChain
.getArch() == llvm::Triple::mips64
)
196 CmdArgs
.push_back("elf32btsmip");
198 CmdArgs
.push_back("elf32ltsmip");
199 } else if (mips::hasMipsAbiArg(Args
, "64")) {
200 CmdArgs
.push_back("-m");
201 if (ToolChain
.getArch() == llvm::Triple::mips64
)
202 CmdArgs
.push_back("elf64btsmip");
204 CmdArgs
.push_back("elf64ltsmip");
207 case llvm::Triple::ppc
:
208 CmdArgs
.push_back("-m");
209 CmdArgs
.push_back("elf32ppc_nbsd");
212 case llvm::Triple::ppc64
:
213 case llvm::Triple::ppc64le
:
214 CmdArgs
.push_back("-m");
215 CmdArgs
.push_back("elf64ppc");
218 case llvm::Triple::sparc
:
219 CmdArgs
.push_back("-m");
220 CmdArgs
.push_back("elf32_sparc");
223 case llvm::Triple::sparcv9
:
224 CmdArgs
.push_back("-m");
225 CmdArgs
.push_back("elf64_sparc");
232 if (Output
.isFilename()) {
233 CmdArgs
.push_back("-o");
234 CmdArgs
.push_back(Output
.getFilename());
236 assert(Output
.isNothing() && "Invalid output.");
239 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
241 if (!Args
.hasArg(options::OPT_shared
)) {
243 Args
.MakeArgString(ToolChain
.GetFilePath("crt0.o")));
246 Args
.MakeArgString(ToolChain
.GetFilePath("crti.o")));
247 if (Args
.hasArg(options::OPT_shared
) || Args
.hasArg(options::OPT_pie
)) {
249 Args
.MakeArgString(ToolChain
.GetFilePath("crtbeginS.o")));
252 Args
.MakeArgString(ToolChain
.GetFilePath("crtbegin.o")));
256 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
257 Args
.AddAllArgs(CmdArgs
, options::OPT_T_Group
);
258 Args
.AddAllArgs(CmdArgs
, options::OPT_e
);
259 Args
.AddAllArgs(CmdArgs
, options::OPT_s
);
260 Args
.AddAllArgs(CmdArgs
, options::OPT_t
);
261 Args
.AddAllArgs(CmdArgs
, options::OPT_Z_Flag
);
262 Args
.AddAllArgs(CmdArgs
, options::OPT_r
);
264 bool NeedsSanitizerDeps
= addSanitizerRuntimes(ToolChain
, Args
, CmdArgs
);
265 bool NeedsXRayDeps
= addXRayRuntime(ToolChain
, Args
, CmdArgs
);
266 AddLinkerInputs(ToolChain
, Inputs
, Args
, CmdArgs
, JA
);
268 const SanitizerArgs
&SanArgs
= ToolChain
.getSanitizerArgs(Args
);
269 if (SanArgs
.needsSharedRt()) {
270 CmdArgs
.push_back("-rpath");
271 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.getCompilerRTPath()));
274 VersionTuple OsVersion
= Triple
.getOSVersion();
275 bool useLibgcc
= true;
276 if (OsVersion
>= VersionTuple(7) || OsVersion
.getMajor() == 0) {
277 switch (ToolChain
.getArch()) {
278 case llvm::Triple::aarch64
:
279 case llvm::Triple::aarch64_be
:
280 case llvm::Triple::arm
:
281 case llvm::Triple::armeb
:
282 case llvm::Triple::thumb
:
283 case llvm::Triple::thumbeb
:
284 case llvm::Triple::ppc
:
285 case llvm::Triple::ppc64
:
286 case llvm::Triple::ppc64le
:
287 case llvm::Triple::sparc
:
288 case llvm::Triple::sparcv9
:
289 case llvm::Triple::x86
:
290 case llvm::Triple::x86_64
:
298 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
,
300 // Use the static OpenMP runtime with -static-openmp
301 bool StaticOpenMP
= Args
.hasArg(options::OPT_static_openmp
) &&
302 !Args
.hasArg(options::OPT_static
);
303 addOpenMPRuntime(CmdArgs
, ToolChain
, Args
, StaticOpenMP
);
306 if (ToolChain
.ShouldLinkCXXStdlib(Args
))
307 ToolChain
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
308 CmdArgs
.push_back("-lm");
310 if (NeedsSanitizerDeps
)
311 linkSanitizerRuntimeDeps(ToolChain
, CmdArgs
);
313 linkXRayRuntimeDeps(ToolChain
, CmdArgs
);
314 if (Args
.hasArg(options::OPT_pthread
))
315 CmdArgs
.push_back("-lpthread");
316 CmdArgs
.push_back("-lc");
319 if (Args
.hasArg(options::OPT_static
)) {
320 // libgcc_eh depends on libc, so resolve as much as possible,
321 // pull in any new requirements from libc and then get the rest
323 CmdArgs
.push_back("-lgcc_eh");
324 CmdArgs
.push_back("-lc");
325 CmdArgs
.push_back("-lgcc");
327 CmdArgs
.push_back("-lgcc");
328 CmdArgs
.push_back("--as-needed");
329 CmdArgs
.push_back("-lgcc_s");
330 CmdArgs
.push_back("--no-as-needed");
335 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
337 if (Args
.hasArg(options::OPT_shared
) || Args
.hasArg(options::OPT_pie
))
339 Args
.MakeArgString(ToolChain
.GetFilePath("crtendS.o")));
342 Args
.MakeArgString(ToolChain
.GetFilePath("crtend.o")));
343 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crtn.o")));
346 ToolChain
.addProfileRTLibs(Args
, CmdArgs
);
348 const char *Exec
= Args
.MakeArgString(ToolChain
.GetLinkerPath());
349 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
350 ResponseFileSupport::AtFileCurCP(),
351 Exec
, CmdArgs
, Inputs
, Output
));
354 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
356 NetBSD::NetBSD(const Driver
&D
, const llvm::Triple
&Triple
, const ArgList
&Args
)
357 : Generic_ELF(D
, Triple
, Args
) {
358 if (!Args
.hasArg(options::OPT_nostdlib
)) {
359 // When targeting a 32-bit platform, try the special directory used on
360 // 64-bit hosts, and only fall back to the main library directory if that
362 // FIXME: It'd be nicer to test if this directory exists, but I'm not sure
363 // what all logic is needed to emulate the '=' prefix here.
364 switch (Triple
.getArch()) {
365 case llvm::Triple::x86
:
366 getFilePaths().push_back("=/usr/lib/i386");
368 case llvm::Triple::arm
:
369 case llvm::Triple::armeb
:
370 case llvm::Triple::thumb
:
371 case llvm::Triple::thumbeb
:
372 switch (Triple
.getEnvironment()) {
373 case llvm::Triple::EABI
:
374 case llvm::Triple::GNUEABI
:
375 getFilePaths().push_back("=/usr/lib/eabi");
377 case llvm::Triple::EABIHF
:
378 case llvm::Triple::GNUEABIHF
:
379 getFilePaths().push_back("=/usr/lib/eabihf");
382 getFilePaths().push_back("=/usr/lib/oabi");
386 case llvm::Triple::mips64
:
387 case llvm::Triple::mips64el
:
388 if (tools::mips::hasMipsAbiArg(Args
, "o32"))
389 getFilePaths().push_back("=/usr/lib/o32");
390 else if (tools::mips::hasMipsAbiArg(Args
, "64"))
391 getFilePaths().push_back("=/usr/lib/64");
393 case llvm::Triple::ppc
:
394 getFilePaths().push_back("=/usr/lib/powerpc");
396 case llvm::Triple::sparc
:
397 getFilePaths().push_back("=/usr/lib/sparc");
403 getFilePaths().push_back("=/usr/lib");
407 Tool
*NetBSD::buildAssembler() const {
408 return new tools::netbsd::Assembler(*this);
411 Tool
*NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
413 ToolChain::CXXStdlibType
NetBSD::GetDefaultCXXStdlibType() const {
414 VersionTuple OsVersion
= getTriple().getOSVersion();
415 if (OsVersion
>= VersionTuple(7) || OsVersion
.getMajor() == 0) {
417 case llvm::Triple::aarch64
:
418 case llvm::Triple::aarch64_be
:
419 case llvm::Triple::arm
:
420 case llvm::Triple::armeb
:
421 case llvm::Triple::thumb
:
422 case llvm::Triple::thumbeb
:
423 case llvm::Triple::ppc
:
424 case llvm::Triple::ppc64
:
425 case llvm::Triple::ppc64le
:
426 case llvm::Triple::sparc
:
427 case llvm::Triple::sparcv9
:
428 case llvm::Triple::x86
:
429 case llvm::Triple::x86_64
:
430 return ToolChain::CST_Libcxx
;
435 return ToolChain::CST_Libstdcxx
;
438 void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
439 llvm::opt::ArgStringList
&CC1Args
) const {
440 const std::string Candidates
[] = {
441 // directory relative to build tree
442 getDriver().Dir
+ "/../include/c++/v1",
443 // system install with full upstream path
444 getDriver().SysRoot
+ "/usr/include/c++/v1",
445 // system install from src
446 getDriver().SysRoot
+ "/usr/include/c++",
449 for (const auto &IncludePath
: Candidates
) {
450 if (!getVFS().exists(IncludePath
+ "/__config"))
453 // Use the first candidate that looks valid.
454 addSystemInclude(DriverArgs
, CC1Args
, IncludePath
);
459 void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
460 llvm::opt::ArgStringList
&CC1Args
) const {
461 addLibStdCXXIncludePaths(getDriver().SysRoot
+ "/usr/include/g++", "", "",
462 DriverArgs
, CC1Args
);
465 llvm::ExceptionHandling
NetBSD::GetExceptionModel(const ArgList
&Args
) const {
466 // NetBSD uses Dwarf exceptions on ARM.
467 llvm::Triple::ArchType TArch
= getTriple().getArch();
468 if (TArch
== llvm::Triple::arm
|| TArch
== llvm::Triple::armeb
||
469 TArch
== llvm::Triple::thumb
|| TArch
== llvm::Triple::thumbeb
)
470 return llvm::ExceptionHandling::DwarfCFI
;
471 return llvm::ExceptionHandling::None
;
474 SanitizerMask
NetBSD::getSupportedSanitizers() const {
475 const bool IsX86
= getTriple().getArch() == llvm::Triple::x86
;
476 const bool IsX86_64
= getTriple().getArch() == llvm::Triple::x86_64
;
477 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
478 if (IsX86
|| IsX86_64
) {
479 Res
|= SanitizerKind::Address
;
480 Res
|= SanitizerKind::PointerCompare
;
481 Res
|= SanitizerKind::PointerSubtract
;
482 Res
|= SanitizerKind::Function
;
483 Res
|= SanitizerKind::Leak
;
484 Res
|= SanitizerKind::SafeStack
;
485 Res
|= SanitizerKind::Scudo
;
486 Res
|= SanitizerKind::Vptr
;
489 Res
|= SanitizerKind::DataFlow
;
490 Res
|= SanitizerKind::Fuzzer
;
491 Res
|= SanitizerKind::FuzzerNoLink
;
492 Res
|= SanitizerKind::HWAddress
;
493 Res
|= SanitizerKind::KernelAddress
;
494 Res
|= SanitizerKind::KernelHWAddress
;
495 Res
|= SanitizerKind::KernelMemory
;
496 Res
|= SanitizerKind::Memory
;
497 Res
|= SanitizerKind::Thread
;
502 void NetBSD::addClangTargetOptions(const ArgList
&DriverArgs
,
503 ArgStringList
&CC1Args
,
504 Action::OffloadKind
) const {
505 const SanitizerArgs
&SanArgs
= getSanitizerArgs(DriverArgs
);
506 if (SanArgs
.hasAnySanitizer())
507 CC1Args
.push_back("-D_REENTRANT");
509 VersionTuple OsVersion
= getTriple().getOSVersion();
510 bool UseInitArrayDefault
=
511 OsVersion
>= VersionTuple(9) || OsVersion
.getMajor() == 0 ||
512 getTriple().getArch() == llvm::Triple::aarch64
||
513 getTriple().getArch() == llvm::Triple::aarch64_be
||
514 getTriple().getArch() == llvm::Triple::arm
||
515 getTriple().getArch() == llvm::Triple::armeb
;
517 if (!DriverArgs
.hasFlag(options::OPT_fuse_init_array
,
518 options::OPT_fno_use_init_array
, UseInitArrayDefault
))
519 CC1Args
.push_back("-fno-use-init-array");