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/Config/config.h"
15 #include "clang/Driver/Compilation.h"
16 #include "clang/Driver/Driver.h"
17 #include "clang/Driver/Options.h"
18 #include "clang/Driver/SanitizerArgs.h"
19 #include "llvm/Option/ArgList.h"
20 #include "llvm/Support/VirtualFileSystem.h"
22 using namespace clang::driver
;
23 using namespace clang::driver::tools
;
24 using namespace clang::driver::toolchains
;
25 using namespace clang
;
26 using namespace llvm::opt
;
28 void netbsd::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
29 const InputInfo
&Output
,
30 const InputInfoList
&Inputs
,
32 const char *LinkingOutput
) const {
33 const auto &ToolChain
= static_cast<const NetBSD
&>(getToolChain());
34 const Driver
&D
= ToolChain
.getDriver();
35 const llvm::Triple
&Triple
= ToolChain
.getTriple();
36 ArgStringList CmdArgs
;
38 claimNoWarnArgs(Args
);
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 CmdArgs
.push_back("-32");
82 std::string CPU
= getCPUName(D
, Args
, Triple
);
83 CmdArgs
.push_back(sparc::getSparcAsmModeForCPU(CPU
, Triple
));
84 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
88 case llvm::Triple::sparcv9
: {
89 CmdArgs
.push_back("-64");
90 std::string CPU
= getCPUName(D
, Args
, Triple
);
91 CmdArgs
.push_back(sparc::getSparcAsmModeForCPU(CPU
, Triple
));
92 AddAssemblerKPIC(ToolChain
, Args
, CmdArgs
);
100 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
102 CmdArgs
.push_back("-o");
103 CmdArgs
.push_back(Output
.getFilename());
105 for (const auto &II
: Inputs
)
106 CmdArgs
.push_back(II
.getFilename());
108 const char *Exec
= Args
.MakeArgString((ToolChain
.GetProgramPath("as")));
109 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
110 ResponseFileSupport::AtFileCurCP(),
111 Exec
, CmdArgs
, Inputs
, Output
));
114 void netbsd::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
115 const InputInfo
&Output
,
116 const InputInfoList
&Inputs
,
118 const char *LinkingOutput
) const {
119 const auto &ToolChain
= static_cast<const NetBSD
&>(getToolChain());
120 const Driver
&D
= ToolChain
.getDriver();
121 const llvm::Triple
&Triple
= ToolChain
.getTriple();
122 const llvm::Triple::ArchType Arch
= ToolChain
.getArch();
123 const bool Static
= Args
.hasArg(options::OPT_static
);
124 const bool Shared
= Args
.hasArg(options::OPT_shared
);
125 const bool Pie
= Args
.hasArg(options::OPT_pie
);
126 ArgStringList CmdArgs
;
128 if (!D
.SysRoot
.empty())
129 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
131 CmdArgs
.push_back("--eh-frame-hdr");
133 CmdArgs
.push_back("-Bstatic");
135 Args
.AddAllArgs(CmdArgs
, options::OPT_pie
);
136 CmdArgs
.push_back("--no-dynamic-linker");
139 if (Args
.hasArg(options::OPT_rdynamic
))
140 CmdArgs
.push_back("-export-dynamic");
142 CmdArgs
.push_back("-shared");
143 } else if (!Args
.hasArg(options::OPT_r
)) {
144 Args
.AddAllArgs(CmdArgs
, options::OPT_pie
);
145 CmdArgs
.push_back("-dynamic-linker");
146 CmdArgs
.push_back("/libexec/ld.elf_so");
150 // Many NetBSD architectures support more than one ABI.
151 // Determine the correct emulation for ld.
153 case llvm::Triple::x86
:
154 CmdArgs
.push_back("-m");
155 CmdArgs
.push_back("elf_i386");
157 case llvm::Triple::arm
:
158 case llvm::Triple::thumb
:
159 CmdArgs
.push_back("-m");
160 switch (Triple
.getEnvironment()) {
161 case llvm::Triple::EABI
:
162 case llvm::Triple::GNUEABI
:
163 CmdArgs
.push_back("armelf_nbsd_eabi");
165 case llvm::Triple::EABIHF
:
166 case llvm::Triple::GNUEABIHF
:
167 CmdArgs
.push_back("armelf_nbsd_eabihf");
170 CmdArgs
.push_back("armelf_nbsd");
174 case llvm::Triple::armeb
:
175 case llvm::Triple::thumbeb
:
176 arm::appendBE8LinkFlag(Args
, CmdArgs
, ToolChain
.getEffectiveTriple());
177 CmdArgs
.push_back("-m");
178 switch (Triple
.getEnvironment()) {
179 case llvm::Triple::EABI
:
180 case llvm::Triple::GNUEABI
:
181 CmdArgs
.push_back("armelfb_nbsd_eabi");
183 case llvm::Triple::EABIHF
:
184 case llvm::Triple::GNUEABIHF
:
185 CmdArgs
.push_back("armelfb_nbsd_eabihf");
188 CmdArgs
.push_back("armelfb_nbsd");
192 case llvm::Triple::mips64
:
193 case llvm::Triple::mips64el
:
194 if (mips::hasMipsAbiArg(Args
, "32")) {
195 CmdArgs
.push_back("-m");
196 if (Arch
== llvm::Triple::mips64
)
197 CmdArgs
.push_back("elf32btsmip");
199 CmdArgs
.push_back("elf32ltsmip");
200 } else if (mips::hasMipsAbiArg(Args
, "64")) {
201 CmdArgs
.push_back("-m");
202 if (Arch
== llvm::Triple::mips64
)
203 CmdArgs
.push_back("elf64btsmip");
205 CmdArgs
.push_back("elf64ltsmip");
208 case llvm::Triple::ppc
:
209 CmdArgs
.push_back("-m");
210 CmdArgs
.push_back("elf32ppc_nbsd");
213 case llvm::Triple::ppc64
:
214 case llvm::Triple::ppc64le
:
215 CmdArgs
.push_back("-m");
216 CmdArgs
.push_back("elf64ppc");
219 case llvm::Triple::riscv32
:
220 CmdArgs
.push_back("-m");
221 CmdArgs
.push_back("elf32lriscv");
224 case llvm::Triple::riscv64
:
225 CmdArgs
.push_back("-m");
226 CmdArgs
.push_back("elf64lriscv");
229 case llvm::Triple::sparc
:
230 CmdArgs
.push_back("-m");
231 CmdArgs
.push_back("elf32_sparc");
234 case llvm::Triple::sparcv9
:
235 CmdArgs
.push_back("-m");
236 CmdArgs
.push_back("elf64_sparc");
243 if (Triple
.isRISCV())
244 CmdArgs
.push_back("-X");
246 assert((Output
.isFilename() || Output
.isNothing()) && "Invalid output.");
247 if (Output
.isFilename()) {
248 CmdArgs
.push_back("-o");
249 CmdArgs
.push_back(Output
.getFilename());
252 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
254 const char *crt0
= nullptr;
255 const char *crtbegin
= nullptr;
260 crtbegin
= "crtbeginS.o";
262 crtbegin
= "crtbegin.o";
265 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crt0
)));
266 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crti.o")));
267 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crtbegin
)));
270 Args
.addAllArgs(CmdArgs
, {options::OPT_L
, options::OPT_T_Group
,
271 options::OPT_s
, options::OPT_t
, options::OPT_r
});
272 ToolChain
.AddFilePathLibArgs(Args
, CmdArgs
);
274 bool NeedsSanitizerDeps
= addSanitizerRuntimes(ToolChain
, Args
, CmdArgs
);
275 bool NeedsXRayDeps
= addXRayRuntime(ToolChain
, Args
, CmdArgs
);
276 AddLinkerInputs(ToolChain
, Inputs
, Args
, CmdArgs
, JA
);
278 const SanitizerArgs
&SanArgs
= ToolChain
.getSanitizerArgs(Args
);
279 if (SanArgs
.needsSharedRt()) {
280 CmdArgs
.push_back("-rpath");
281 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.getCompilerRTPath()));
284 bool useLibgcc
= true;
285 switch (ToolChain
.getArch()) {
286 case llvm::Triple::aarch64
:
287 case llvm::Triple::aarch64_be
:
288 case llvm::Triple::arm
:
289 case llvm::Triple::armeb
:
290 case llvm::Triple::thumb
:
291 case llvm::Triple::thumbeb
:
292 case llvm::Triple::ppc
:
293 case llvm::Triple::ppc64
:
294 case llvm::Triple::ppc64le
:
295 case llvm::Triple::riscv32
:
296 case llvm::Triple::riscv64
:
297 case llvm::Triple::sparc
:
298 case llvm::Triple::sparcv9
:
299 case llvm::Triple::x86
:
300 case llvm::Triple::x86_64
:
307 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
,
309 // Use the static OpenMP runtime with -static-openmp
310 bool StaticOpenMP
= Args
.hasArg(options::OPT_static_openmp
) && !Static
;
311 addOpenMPRuntime(CmdArgs
, ToolChain
, Args
, StaticOpenMP
);
314 if (ToolChain
.ShouldLinkCXXStdlib(Args
))
315 ToolChain
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
316 CmdArgs
.push_back("-lm");
319 // Silence warnings when linking C code with a C++ '-stdlib' argument.
320 Args
.ClaimAllArgs(options::OPT_stdlib_EQ
);
322 // Additional linker set-up and flags for Fortran. This is required in order
323 // to generate executables. As Fortran runtime depends on the C runtime,
324 // these dependencies need to be listed before the C runtime below (i.e.
326 if (D
.IsFlangMode()) {
327 addFortranRuntimeLibraryPath(ToolChain
, Args
, CmdArgs
);
328 addFortranRuntimeLibs(ToolChain
, Args
, CmdArgs
);
329 CmdArgs
.push_back("-lm");
332 if (NeedsSanitizerDeps
)
333 linkSanitizerRuntimeDeps(ToolChain
, Args
, CmdArgs
);
335 linkXRayRuntimeDeps(ToolChain
, Args
, CmdArgs
);
336 if (Args
.hasArg(options::OPT_pthread
))
337 CmdArgs
.push_back("-lpthread");
338 CmdArgs
.push_back("-lc");
342 // libgcc_eh depends on libc, so resolve as much as possible,
343 // pull in any new requirements from libc and then get the rest
345 CmdArgs
.push_back("-lgcc_eh");
346 CmdArgs
.push_back("-lc");
347 CmdArgs
.push_back("-lgcc");
349 CmdArgs
.push_back("-lgcc");
350 CmdArgs
.push_back("--as-needed");
351 CmdArgs
.push_back("-lgcc_s");
352 CmdArgs
.push_back("--no-as-needed");
357 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
359 const char *crtend
= nullptr;
361 crtend
= "crtendS.o";
365 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crtend
)));
366 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crtn.o")));
369 ToolChain
.addProfileRTLibs(Args
, CmdArgs
);
371 const char *Exec
= Args
.MakeArgString(ToolChain
.GetLinkerPath());
372 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
373 ResponseFileSupport::AtFileCurCP(),
374 Exec
, CmdArgs
, Inputs
, Output
));
377 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
379 NetBSD::NetBSD(const Driver
&D
, const llvm::Triple
&Triple
, const ArgList
&Args
)
380 : Generic_ELF(D
, Triple
, Args
) {
381 if (!Args
.hasArg(options::OPT_nostdlib
)) {
382 // When targeting a 32-bit platform, try the special directory used on
383 // 64-bit hosts, and only fall back to the main library directory if that
385 // FIXME: It'd be nicer to test if this directory exists, but I'm not sure
386 // what all logic is needed to emulate the '=' prefix here.
387 switch (Triple
.getArch()) {
388 case llvm::Triple::x86
:
389 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/i386"));
391 case llvm::Triple::arm
:
392 case llvm::Triple::armeb
:
393 case llvm::Triple::thumb
:
394 case llvm::Triple::thumbeb
:
395 switch (Triple
.getEnvironment()) {
396 case llvm::Triple::EABI
:
397 case llvm::Triple::GNUEABI
:
398 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/eabi"));
400 case llvm::Triple::EABIHF
:
401 case llvm::Triple::GNUEABIHF
:
402 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/eabihf"));
405 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/oabi"));
409 case llvm::Triple::mips64
:
410 case llvm::Triple::mips64el
:
411 if (tools::mips::hasMipsAbiArg(Args
, "o32"))
412 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/o32"));
413 else if (tools::mips::hasMipsAbiArg(Args
, "64"))
414 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/64"));
416 case llvm::Triple::ppc
:
417 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/powerpc"));
419 case llvm::Triple::sparc
:
420 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib/sparc"));
426 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib"));
430 Tool
*NetBSD::buildAssembler() const {
431 return new tools::netbsd::Assembler(*this);
434 Tool
*NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
436 ToolChain::CXXStdlibType
NetBSD::GetDefaultCXXStdlibType() const {
438 case llvm::Triple::aarch64
:
439 case llvm::Triple::aarch64_be
:
440 case llvm::Triple::arm
:
441 case llvm::Triple::armeb
:
442 case llvm::Triple::thumb
:
443 case llvm::Triple::thumbeb
:
444 case llvm::Triple::ppc
:
445 case llvm::Triple::ppc64
:
446 case llvm::Triple::ppc64le
:
447 case llvm::Triple::riscv32
:
448 case llvm::Triple::riscv64
:
449 case llvm::Triple::sparc
:
450 case llvm::Triple::sparcv9
:
451 case llvm::Triple::x86
:
452 case llvm::Triple::x86_64
:
453 return ToolChain::CST_Libcxx
;
457 return ToolChain::CST_Libstdcxx
;
460 void NetBSD::AddClangSystemIncludeArgs(
461 const llvm::opt::ArgList
&DriverArgs
,
462 llvm::opt::ArgStringList
&CC1Args
) const {
463 const Driver
&D
= getDriver();
465 if (DriverArgs
.hasArg(clang::driver::options::OPT_nostdinc
))
468 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
469 SmallString
<128> Dir(D
.ResourceDir
);
470 llvm::sys::path::append(Dir
, "include");
471 addSystemInclude(DriverArgs
, CC1Args
, Dir
.str());
474 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
))
477 // Check for configure-time C include directories.
478 StringRef
CIncludeDirs(C_INCLUDE_DIRS
);
479 if (CIncludeDirs
!= "") {
480 SmallVector
<StringRef
, 5> dirs
;
481 CIncludeDirs
.split(dirs
, ":");
482 for (StringRef dir
: dirs
) {
484 llvm::sys::path::is_absolute(dir
) ? StringRef(D
.SysRoot
) : "";
485 addExternCSystemInclude(DriverArgs
, CC1Args
, Prefix
+ dir
);
490 addExternCSystemInclude(DriverArgs
, CC1Args
,
491 concat(D
.SysRoot
, "/usr/include"));
494 void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
495 llvm::opt::ArgStringList
&CC1Args
) const {
496 const std::string Candidates
[] = {
497 // directory relative to build tree
498 concat(getDriver().Dir
, "/../include/c++/v1"),
499 // system install with full upstream path
500 concat(getDriver().SysRoot
, "/usr/include/c++/v1"),
501 // system install from src
502 concat(getDriver().SysRoot
, "/usr/include/c++"),
505 for (const auto &IncludePath
: Candidates
) {
506 if (!getVFS().exists(IncludePath
+ "/__config"))
509 // Use the first candidate that looks valid.
510 addSystemInclude(DriverArgs
, CC1Args
, IncludePath
);
515 void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
516 llvm::opt::ArgStringList
&CC1Args
) const {
517 addLibStdCXXIncludePaths(concat(getDriver().SysRoot
, "/usr/include/g++"), "", "",
518 DriverArgs
, CC1Args
);
521 llvm::ExceptionHandling
NetBSD::GetExceptionModel(const ArgList
&Args
) const {
522 // NetBSD uses Dwarf exceptions on ARM.
523 llvm::Triple::ArchType TArch
= getTriple().getArch();
524 if (TArch
== llvm::Triple::arm
|| TArch
== llvm::Triple::armeb
||
525 TArch
== llvm::Triple::thumb
|| TArch
== llvm::Triple::thumbeb
)
526 return llvm::ExceptionHandling::DwarfCFI
;
527 return llvm::ExceptionHandling::None
;
530 SanitizerMask
NetBSD::getSupportedSanitizers() const {
531 const bool IsX86
= getTriple().getArch() == llvm::Triple::x86
;
532 const bool IsX86_64
= getTriple().getArch() == llvm::Triple::x86_64
;
533 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
534 if (IsX86
|| IsX86_64
) {
535 Res
|= SanitizerKind::Address
;
536 Res
|= SanitizerKind::PointerCompare
;
537 Res
|= SanitizerKind::PointerSubtract
;
538 Res
|= SanitizerKind::Leak
;
539 Res
|= SanitizerKind::SafeStack
;
540 Res
|= SanitizerKind::Scudo
;
541 Res
|= SanitizerKind::Vptr
;
544 Res
|= SanitizerKind::DataFlow
;
545 Res
|= SanitizerKind::Fuzzer
;
546 Res
|= SanitizerKind::FuzzerNoLink
;
547 Res
|= SanitizerKind::HWAddress
;
548 Res
|= SanitizerKind::KernelAddress
;
549 Res
|= SanitizerKind::KernelHWAddress
;
550 Res
|= SanitizerKind::KernelMemory
;
551 Res
|= SanitizerKind::Memory
;
552 Res
|= SanitizerKind::Thread
;
557 void NetBSD::addClangTargetOptions(const ArgList
&DriverArgs
,
558 ArgStringList
&CC1Args
,
559 Action::OffloadKind
) const {
560 const SanitizerArgs
&SanArgs
= getSanitizerArgs(DriverArgs
);
561 if (SanArgs
.hasAnySanitizer())
562 CC1Args
.push_back("-D_REENTRANT");
564 VersionTuple OsVersion
= getTriple().getOSVersion();
565 bool UseInitArrayDefault
=
566 OsVersion
>= VersionTuple(9) || OsVersion
.getMajor() == 0 ||
567 getTriple().getArch() == llvm::Triple::aarch64
||
568 getTriple().getArch() == llvm::Triple::aarch64_be
||
569 getTriple().getArch() == llvm::Triple::arm
||
570 getTriple().getArch() == llvm::Triple::armeb
||
571 getTriple().getArch() == llvm::Triple::riscv32
||
572 getTriple().getArch() == llvm::Triple::riscv64
;
574 if (!DriverArgs
.hasFlag(options::OPT_fuse_init_array
,
575 options::OPT_fno_use_init_array
, UseInitArrayDefault
))
576 CC1Args
.push_back("-fno-use-init-array");