1 //===--- FreeBSD.cpp - FreeBSD 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/DriverDiagnostic.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 freebsd::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
28 const InputInfo
&Output
,
29 const InputInfoList
&Inputs
,
31 const char *LinkingOutput
) const {
32 claimNoWarnArgs(Args
);
33 ArgStringList CmdArgs
;
34 const auto &D
= getToolChain().getDriver();
36 // When building 32-bit code on FreeBSD/amd64, we have to explicitly
37 // instruct as in the base system to assemble 32-bit code.
38 switch (getToolChain().getArch()) {
41 case llvm::Triple::x86
:
42 CmdArgs
.push_back("--32");
44 case llvm::Triple::ppc
:
45 case llvm::Triple::ppcle
:
46 CmdArgs
.push_back("-a32");
48 case llvm::Triple::mips
:
49 case llvm::Triple::mipsel
:
50 case llvm::Triple::mips64
:
51 case llvm::Triple::mips64el
: {
54 mips::getMipsCPUAndABI(Args
, getToolChain().getTriple(), CPUName
, ABIName
);
56 CmdArgs
.push_back("-march");
57 CmdArgs
.push_back(CPUName
.data());
59 CmdArgs
.push_back("-mabi");
60 CmdArgs
.push_back(mips::getGnuCompatibleMipsABIName(ABIName
).data());
62 if (getToolChain().getTriple().isLittleEndian())
63 CmdArgs
.push_back("-EL");
65 CmdArgs
.push_back("-EB");
67 if (Arg
*A
= Args
.getLastArg(options::OPT_G
)) {
68 StringRef v
= A
->getValue();
69 CmdArgs
.push_back(Args
.MakeArgString("-G" + v
));
73 AddAssemblerKPIC(getToolChain(), Args
, CmdArgs
);
76 case llvm::Triple::arm
:
77 case llvm::Triple::armeb
:
78 case llvm::Triple::thumb
:
79 case llvm::Triple::thumbeb
: {
80 arm::FloatABI ABI
= arm::getARMFloatABI(getToolChain(), Args
);
82 if (ABI
== arm::FloatABI::Hard
)
83 CmdArgs
.push_back("-mfpu=vfp");
85 CmdArgs
.push_back("-mfpu=softvfp");
87 switch (getToolChain().getTriple().getEnvironment()) {
88 case llvm::Triple::GNUEABIHF
:
89 case llvm::Triple::GNUEABI
:
90 case llvm::Triple::EABI
:
91 CmdArgs
.push_back("-meabi=5");
95 CmdArgs
.push_back("-matpcs");
99 case llvm::Triple::sparc
:
100 case llvm::Triple::sparcel
:
101 case llvm::Triple::sparcv9
: {
102 std::string CPU
= getCPUName(D
, Args
, getToolChain().getTriple());
104 sparc::getSparcAsmModeForCPU(CPU
, getToolChain().getTriple()));
105 AddAssemblerKPIC(getToolChain(), Args
, CmdArgs
);
110 for (const Arg
*A
: Args
.filtered(options::OPT_ffile_prefix_map_EQ
,
111 options::OPT_fdebug_prefix_map_EQ
)) {
112 StringRef Map
= A
->getValue();
113 if (!Map
.contains('='))
114 D
.Diag(diag::err_drv_invalid_argument_to_option
)
115 << Map
<< A
->getOption().getName();
117 CmdArgs
.push_back(Args
.MakeArgString("--debug-prefix-map"));
118 CmdArgs
.push_back(Args
.MakeArgString(Map
));
123 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
125 CmdArgs
.push_back("-o");
126 CmdArgs
.push_back(Output
.getFilename());
128 for (const auto &II
: Inputs
)
129 CmdArgs
.push_back(II
.getFilename());
131 const char *Exec
= Args
.MakeArgString(getToolChain().GetProgramPath("as"));
132 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
133 ResponseFileSupport::AtFileCurCP(),
134 Exec
, CmdArgs
, Inputs
, Output
));
137 void freebsd::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
138 const InputInfo
&Output
,
139 const InputInfoList
&Inputs
,
141 const char *LinkingOutput
) const {
142 const toolchains::FreeBSD
&ToolChain
=
143 static_cast<const toolchains::FreeBSD
&>(getToolChain());
144 const Driver
&D
= ToolChain
.getDriver();
145 const llvm::Triple::ArchType Arch
= ToolChain
.getArch();
147 !Args
.hasArg(options::OPT_shared
) &&
148 (Args
.hasArg(options::OPT_pie
) || ToolChain
.isPIEDefault(Args
));
149 ArgStringList CmdArgs
;
151 // Silence warning for "clang -g foo.o -o foo"
152 Args
.ClaimAllArgs(options::OPT_g_Group
);
153 // and "clang -emit-llvm foo.o -o foo"
154 Args
.ClaimAllArgs(options::OPT_emit_llvm
);
155 // and for "clang -w foo.o -o foo". Other warning options are already
156 // handled somewhere else.
157 Args
.ClaimAllArgs(options::OPT_w
);
159 if (!D
.SysRoot
.empty())
160 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
163 CmdArgs
.push_back("-pie");
165 CmdArgs
.push_back("--eh-frame-hdr");
166 if (Args
.hasArg(options::OPT_static
)) {
167 CmdArgs
.push_back("-Bstatic");
169 if (Args
.hasArg(options::OPT_rdynamic
))
170 CmdArgs
.push_back("-export-dynamic");
171 if (Args
.hasArg(options::OPT_shared
)) {
172 CmdArgs
.push_back("-Bshareable");
173 } else if (!Args
.hasArg(options::OPT_r
)) {
174 CmdArgs
.push_back("-dynamic-linker");
175 CmdArgs
.push_back("/libexec/ld-elf.so.1");
177 const llvm::Triple
&T
= ToolChain
.getTriple();
178 if (T
.getOSMajorVersion() >= 9) {
179 if (Arch
== llvm::Triple::arm
|| Arch
== llvm::Triple::sparc
|| T
.isX86())
180 CmdArgs
.push_back("--hash-style=both");
182 CmdArgs
.push_back("--enable-new-dtags");
185 // Explicitly set the linker emulation for platforms that might not
186 // be the default emulation for the linker.
188 case llvm::Triple::x86
:
189 CmdArgs
.push_back("-m");
190 CmdArgs
.push_back("elf_i386_fbsd");
192 case llvm::Triple::ppc
:
193 CmdArgs
.push_back("-m");
194 CmdArgs
.push_back("elf32ppc_fbsd");
196 case llvm::Triple::ppcle
:
197 CmdArgs
.push_back("-m");
198 // Use generic -- only usage is for freestanding.
199 CmdArgs
.push_back("elf32lppc");
201 case llvm::Triple::mips
:
202 CmdArgs
.push_back("-m");
203 CmdArgs
.push_back("elf32btsmip_fbsd");
205 case llvm::Triple::mipsel
:
206 CmdArgs
.push_back("-m");
207 CmdArgs
.push_back("elf32ltsmip_fbsd");
209 case llvm::Triple::mips64
:
210 CmdArgs
.push_back("-m");
211 if (tools::mips::hasMipsAbiArg(Args
, "n32"))
212 CmdArgs
.push_back("elf32btsmipn32_fbsd");
214 CmdArgs
.push_back("elf64btsmip_fbsd");
216 case llvm::Triple::mips64el
:
217 CmdArgs
.push_back("-m");
218 if (tools::mips::hasMipsAbiArg(Args
, "n32"))
219 CmdArgs
.push_back("elf32ltsmipn32_fbsd");
221 CmdArgs
.push_back("elf64ltsmip_fbsd");
223 case llvm::Triple::riscv32
:
224 CmdArgs
.push_back("-m");
225 CmdArgs
.push_back("elf32lriscv");
226 CmdArgs
.push_back("-X");
228 case llvm::Triple::riscv64
:
229 CmdArgs
.push_back("-m");
230 CmdArgs
.push_back("elf64lriscv");
231 CmdArgs
.push_back("-X");
237 if (Arg
*A
= Args
.getLastArg(options::OPT_G
)) {
238 if (ToolChain
.getTriple().isMIPS()) {
239 StringRef v
= A
->getValue();
240 CmdArgs
.push_back(Args
.MakeArgString("-G" + v
));
245 if (Output
.isFilename()) {
246 CmdArgs
.push_back("-o");
247 CmdArgs
.push_back(Output
.getFilename());
249 assert(Output
.isNothing() && "Invalid output.");
252 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
254 const char *crt1
= nullptr;
255 if (!Args
.hasArg(options::OPT_shared
)) {
256 if (Args
.hasArg(options::OPT_pg
))
264 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crt1
)));
266 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crti.o")));
268 const char *crtbegin
= nullptr;
269 if (Args
.hasArg(options::OPT_static
))
270 crtbegin
= "crtbeginT.o";
271 else if (Args
.hasArg(options::OPT_shared
) || IsPIE
)
272 crtbegin
= "crtbeginS.o";
274 crtbegin
= "crtbegin.o";
276 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath(crtbegin
)));
279 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
280 ToolChain
.AddFilePathLibArgs(Args
, CmdArgs
);
281 Args
.AddAllArgs(CmdArgs
, options::OPT_T_Group
);
282 Args
.AddAllArgs(CmdArgs
, options::OPT_e
);
283 Args
.AddAllArgs(CmdArgs
, options::OPT_s
);
284 Args
.AddAllArgs(CmdArgs
, options::OPT_t
);
285 Args
.AddAllArgs(CmdArgs
, options::OPT_Z_Flag
);
286 Args
.AddAllArgs(CmdArgs
, options::OPT_r
);
288 if (D
.isUsingLTO()) {
289 assert(!Inputs
.empty() && "Must have at least one input.");
290 addLTOOptions(ToolChain
, Args
, CmdArgs
, Output
, Inputs
[0],
291 D
.getLTOMode() == LTOK_Thin
);
294 bool NeedsSanitizerDeps
= addSanitizerRuntimes(ToolChain
, Args
, CmdArgs
);
295 bool NeedsXRayDeps
= addXRayRuntime(ToolChain
, Args
, CmdArgs
);
296 addLinkerCompressDebugSectionsOption(ToolChain
, Args
, CmdArgs
);
297 AddLinkerInputs(ToolChain
, Inputs
, Args
, CmdArgs
, JA
);
299 unsigned Major
= ToolChain
.getTriple().getOSMajorVersion();
300 bool Profiling
= Args
.hasArg(options::OPT_pg
) && Major
!= 0 && Major
< 14;
301 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nodefaultlibs
,
303 // Use the static OpenMP runtime with -static-openmp
304 bool StaticOpenMP
= Args
.hasArg(options::OPT_static_openmp
) &&
305 !Args
.hasArg(options::OPT_static
);
306 addOpenMPRuntime(CmdArgs
, ToolChain
, Args
, StaticOpenMP
);
309 if (ToolChain
.ShouldLinkCXXStdlib(Args
))
310 ToolChain
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
312 CmdArgs
.push_back("-lm_p");
314 CmdArgs
.push_back("-lm");
316 if (NeedsSanitizerDeps
)
317 linkSanitizerRuntimeDeps(ToolChain
, CmdArgs
);
319 linkXRayRuntimeDeps(ToolChain
, CmdArgs
);
320 // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
321 // the default system libraries. Just mimic this for now.
323 CmdArgs
.push_back("-lgcc_p");
325 CmdArgs
.push_back("-lgcc");
326 if (Args
.hasArg(options::OPT_static
)) {
327 CmdArgs
.push_back("-lgcc_eh");
328 } else if (Profiling
) {
329 CmdArgs
.push_back("-lgcc_eh_p");
331 CmdArgs
.push_back("--as-needed");
332 CmdArgs
.push_back("-lgcc_s");
333 CmdArgs
.push_back("--no-as-needed");
336 if (Args
.hasArg(options::OPT_pthread
)) {
338 CmdArgs
.push_back("-lpthread_p");
340 CmdArgs
.push_back("-lpthread");
344 if (Args
.hasArg(options::OPT_shared
))
345 CmdArgs
.push_back("-lc");
347 CmdArgs
.push_back("-lc_p");
348 CmdArgs
.push_back("-lgcc_p");
350 CmdArgs
.push_back("-lc");
351 CmdArgs
.push_back("-lgcc");
354 if (Args
.hasArg(options::OPT_static
)) {
355 CmdArgs
.push_back("-lgcc_eh");
356 } else if (Profiling
) {
357 CmdArgs
.push_back("-lgcc_eh_p");
359 CmdArgs
.push_back("--as-needed");
360 CmdArgs
.push_back("-lgcc_s");
361 CmdArgs
.push_back("--no-as-needed");
365 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
,
367 if (Args
.hasArg(options::OPT_shared
) || IsPIE
)
368 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crtendS.o")));
370 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crtend.o")));
371 CmdArgs
.push_back(Args
.MakeArgString(ToolChain
.GetFilePath("crtn.o")));
374 ToolChain
.addProfileRTLibs(Args
, CmdArgs
);
376 const char *Exec
= Args
.MakeArgString(getToolChain().GetLinkerPath());
377 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
378 ResponseFileSupport::AtFileCurCP(),
379 Exec
, CmdArgs
, Inputs
, Output
));
382 /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
384 FreeBSD::FreeBSD(const Driver
&D
, const llvm::Triple
&Triple
,
386 : Generic_ELF(D
, Triple
, Args
) {
388 // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
389 // back to '/usr/lib' if it doesn't exist.
390 if ((Triple
.getArch() == llvm::Triple::x86
|| Triple
.isMIPS32() ||
392 D
.getVFS().exists(concat(getDriver().SysRoot
, "/usr/lib32/crt1.o")))
393 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib32"));
395 getFilePaths().push_back(concat(getDriver().SysRoot
, "/usr/lib"));
398 ToolChain::CXXStdlibType
FreeBSD::GetDefaultCXXStdlibType() const {
399 unsigned Major
= getTriple().getOSMajorVersion();
400 if (Major
>= 10 || Major
== 0)
401 return ToolChain::CST_Libcxx
;
402 return ToolChain::CST_Libstdcxx
;
405 unsigned FreeBSD::GetDefaultDwarfVersion() const {
406 if (getTriple().getOSMajorVersion() < 12)
411 void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList
&DriverArgs
,
412 llvm::opt::ArgStringList
&CC1Args
) const {
413 addSystemInclude(DriverArgs
, CC1Args
,
414 concat(getDriver().SysRoot
, "/usr/include/c++/v1"));
417 void FreeBSD::addLibStdCxxIncludePaths(
418 const llvm::opt::ArgList
&DriverArgs
,
419 llvm::opt::ArgStringList
&CC1Args
) const {
420 addLibStdCXXIncludePaths(concat(getDriver().SysRoot
, "/usr/include/c++/4.2"),
421 "", "", DriverArgs
, CC1Args
);
424 void FreeBSD::AddCXXStdlibLibArgs(const ArgList
&Args
,
425 ArgStringList
&CmdArgs
) const {
426 CXXStdlibType Type
= GetCXXStdlibType(Args
);
427 unsigned Major
= getTriple().getOSMajorVersion();
428 bool Profiling
= Args
.hasArg(options::OPT_pg
) && Major
!= 0 && Major
< 14;
431 case ToolChain::CST_Libcxx
:
432 CmdArgs
.push_back(Profiling
? "-lc++_p" : "-lc++");
433 if (Args
.hasArg(options::OPT_fexperimental_library
))
434 CmdArgs
.push_back("-lc++experimental");
437 case ToolChain::CST_Libstdcxx
:
438 CmdArgs
.push_back(Profiling
? "-lstdc++_p" : "-lstdc++");
443 void FreeBSD::AddCudaIncludeArgs(const ArgList
&DriverArgs
,
444 ArgStringList
&CC1Args
) const {
445 CudaInstallation
.AddCudaIncludeArgs(DriverArgs
, CC1Args
);
448 void FreeBSD::AddHIPIncludeArgs(const ArgList
&DriverArgs
,
449 ArgStringList
&CC1Args
) const {
450 RocmInstallation
.AddHIPIncludeArgs(DriverArgs
, CC1Args
);
453 Tool
*FreeBSD::buildAssembler() const {
454 return new tools::freebsd::Assembler(*this);
457 Tool
*FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
459 llvm::ExceptionHandling
FreeBSD::GetExceptionModel(const ArgList
&Args
) const {
460 // FreeBSD uses SjLj exceptions on ARM oabi.
461 switch (getTriple().getEnvironment()) {
462 case llvm::Triple::GNUEABIHF
:
463 case llvm::Triple::GNUEABI
:
464 case llvm::Triple::EABI
:
465 return llvm::ExceptionHandling::None
;
467 if (getTriple().getArch() == llvm::Triple::arm
||
468 getTriple().getArch() == llvm::Triple::thumb
)
469 return llvm::ExceptionHandling::SjLj
;
470 return llvm::ExceptionHandling::None
;
474 bool FreeBSD::HasNativeLLVMSupport() const { return true; }
476 bool FreeBSD::IsUnwindTablesDefault(const ArgList
&Args
) const { return true; }
478 bool FreeBSD::isPIEDefault(const llvm::opt::ArgList
&Args
) const {
479 return getSanitizerArgs(Args
).requiresPIE();
482 SanitizerMask
FreeBSD::getSupportedSanitizers() const {
483 const bool IsAArch64
= getTriple().getArch() == llvm::Triple::aarch64
;
484 const bool IsX86
= getTriple().getArch() == llvm::Triple::x86
;
485 const bool IsX86_64
= getTriple().getArch() == llvm::Triple::x86_64
;
486 const bool IsMIPS64
= getTriple().isMIPS64();
487 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
488 Res
|= SanitizerKind::Address
;
489 Res
|= SanitizerKind::PointerCompare
;
490 Res
|= SanitizerKind::PointerSubtract
;
491 Res
|= SanitizerKind::Vptr
;
492 if (IsAArch64
|| IsX86_64
|| IsMIPS64
) {
493 Res
|= SanitizerKind::Leak
;
494 Res
|= SanitizerKind::Thread
;
496 if (IsX86
|| IsX86_64
) {
497 Res
|= SanitizerKind::Function
;
499 if (IsAArch64
|| IsX86
|| IsX86_64
) {
500 Res
|= SanitizerKind::SafeStack
;
501 Res
|= SanitizerKind::Fuzzer
;
502 Res
|= SanitizerKind::FuzzerNoLink
;
504 if (IsAArch64
|| IsX86_64
) {
505 Res
|= SanitizerKind::KernelAddress
;
506 Res
|= SanitizerKind::KernelMemory
;
507 Res
|= SanitizerKind::Memory
;
512 void FreeBSD::addClangTargetOptions(const ArgList
&DriverArgs
,
513 ArgStringList
&CC1Args
,
514 Action::OffloadKind
) const {
515 if (!DriverArgs
.hasFlag(options::OPT_fuse_init_array
,
516 options::OPT_fno_use_init_array
,
517 getTriple().getOSMajorVersion() >= 12))
518 CC1Args
.push_back("-fno-use-init-array");