106f32e7eSjoerg //===--- FreeBSD.cpp - FreeBSD ToolChain Implementations --------*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg 
906f32e7eSjoerg #include "FreeBSD.h"
1006f32e7eSjoerg #include "Arch/ARM.h"
1106f32e7eSjoerg #include "Arch/Mips.h"
1206f32e7eSjoerg #include "Arch/Sparc.h"
1306f32e7eSjoerg #include "CommonArgs.h"
1406f32e7eSjoerg #include "clang/Driver/Compilation.h"
15*13fbcb42Sjoerg #include "clang/Driver/DriverDiagnostic.h"
1606f32e7eSjoerg #include "clang/Driver/Options.h"
1706f32e7eSjoerg #include "clang/Driver/SanitizerArgs.h"
1806f32e7eSjoerg #include "llvm/Option/ArgList.h"
1906f32e7eSjoerg #include "llvm/Support/VirtualFileSystem.h"
2006f32e7eSjoerg 
2106f32e7eSjoerg using namespace clang::driver;
2206f32e7eSjoerg using namespace clang::driver::tools;
2306f32e7eSjoerg using namespace clang::driver::toolchains;
2406f32e7eSjoerg using namespace clang;
2506f32e7eSjoerg using namespace llvm::opt;
2606f32e7eSjoerg 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const2706f32e7eSjoerg void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
2806f32e7eSjoerg                                       const InputInfo &Output,
2906f32e7eSjoerg                                       const InputInfoList &Inputs,
3006f32e7eSjoerg                                       const ArgList &Args,
3106f32e7eSjoerg                                       const char *LinkingOutput) const {
3206f32e7eSjoerg   claimNoWarnArgs(Args);
3306f32e7eSjoerg   ArgStringList CmdArgs;
34*13fbcb42Sjoerg   const auto &D = getToolChain().getDriver();
3506f32e7eSjoerg 
3606f32e7eSjoerg   // When building 32-bit code on FreeBSD/amd64, we have to explicitly
3706f32e7eSjoerg   // instruct as in the base system to assemble 32-bit code.
3806f32e7eSjoerg   switch (getToolChain().getArch()) {
3906f32e7eSjoerg   default:
4006f32e7eSjoerg     break;
4106f32e7eSjoerg   case llvm::Triple::x86:
4206f32e7eSjoerg     CmdArgs.push_back("--32");
4306f32e7eSjoerg     break;
4406f32e7eSjoerg   case llvm::Triple::ppc:
45*13fbcb42Sjoerg   case llvm::Triple::ppcle:
4606f32e7eSjoerg     CmdArgs.push_back("-a32");
4706f32e7eSjoerg     break;
4806f32e7eSjoerg   case llvm::Triple::mips:
4906f32e7eSjoerg   case llvm::Triple::mipsel:
5006f32e7eSjoerg   case llvm::Triple::mips64:
5106f32e7eSjoerg   case llvm::Triple::mips64el: {
5206f32e7eSjoerg     StringRef CPUName;
5306f32e7eSjoerg     StringRef ABIName;
5406f32e7eSjoerg     mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
5506f32e7eSjoerg 
5606f32e7eSjoerg     CmdArgs.push_back("-march");
5706f32e7eSjoerg     CmdArgs.push_back(CPUName.data());
5806f32e7eSjoerg 
5906f32e7eSjoerg     CmdArgs.push_back("-mabi");
6006f32e7eSjoerg     CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
6106f32e7eSjoerg 
6206f32e7eSjoerg     if (getToolChain().getTriple().isLittleEndian())
6306f32e7eSjoerg       CmdArgs.push_back("-EL");
6406f32e7eSjoerg     else
6506f32e7eSjoerg       CmdArgs.push_back("-EB");
6606f32e7eSjoerg 
6706f32e7eSjoerg     if (Arg *A = Args.getLastArg(options::OPT_G)) {
6806f32e7eSjoerg       StringRef v = A->getValue();
6906f32e7eSjoerg       CmdArgs.push_back(Args.MakeArgString("-G" + v));
7006f32e7eSjoerg       A->claim();
7106f32e7eSjoerg     }
7206f32e7eSjoerg 
7306f32e7eSjoerg     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
7406f32e7eSjoerg     break;
7506f32e7eSjoerg   }
7606f32e7eSjoerg   case llvm::Triple::arm:
7706f32e7eSjoerg   case llvm::Triple::armeb:
7806f32e7eSjoerg   case llvm::Triple::thumb:
7906f32e7eSjoerg   case llvm::Triple::thumbeb: {
8006f32e7eSjoerg     arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
8106f32e7eSjoerg 
8206f32e7eSjoerg     if (ABI == arm::FloatABI::Hard)
8306f32e7eSjoerg       CmdArgs.push_back("-mfpu=vfp");
8406f32e7eSjoerg     else
8506f32e7eSjoerg       CmdArgs.push_back("-mfpu=softvfp");
8606f32e7eSjoerg 
8706f32e7eSjoerg     switch (getToolChain().getTriple().getEnvironment()) {
8806f32e7eSjoerg     case llvm::Triple::GNUEABIHF:
8906f32e7eSjoerg     case llvm::Triple::GNUEABI:
9006f32e7eSjoerg     case llvm::Triple::EABI:
9106f32e7eSjoerg       CmdArgs.push_back("-meabi=5");
9206f32e7eSjoerg       break;
9306f32e7eSjoerg 
9406f32e7eSjoerg     default:
9506f32e7eSjoerg       CmdArgs.push_back("-matpcs");
9606f32e7eSjoerg     }
9706f32e7eSjoerg     break;
9806f32e7eSjoerg   }
9906f32e7eSjoerg   case llvm::Triple::sparc:
10006f32e7eSjoerg   case llvm::Triple::sparcel:
10106f32e7eSjoerg   case llvm::Triple::sparcv9: {
10206f32e7eSjoerg     std::string CPU = getCPUName(Args, getToolChain().getTriple());
103*13fbcb42Sjoerg     CmdArgs.push_back(
104*13fbcb42Sjoerg         sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
10506f32e7eSjoerg     AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
10606f32e7eSjoerg     break;
10706f32e7eSjoerg   }
10806f32e7eSjoerg   }
10906f32e7eSjoerg 
110*13fbcb42Sjoerg   for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
111*13fbcb42Sjoerg                                     options::OPT_fdebug_prefix_map_EQ)) {
112*13fbcb42Sjoerg     StringRef Map = A->getValue();
113*13fbcb42Sjoerg     if (Map.find('=') == StringRef::npos)
114*13fbcb42Sjoerg       D.Diag(diag::err_drv_invalid_argument_to_option)
115*13fbcb42Sjoerg           << Map << A->getOption().getName();
116*13fbcb42Sjoerg     else {
117*13fbcb42Sjoerg       CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map"));
118*13fbcb42Sjoerg       CmdArgs.push_back(Args.MakeArgString(Map));
119*13fbcb42Sjoerg     }
120*13fbcb42Sjoerg     A->claim();
121*13fbcb42Sjoerg   }
122*13fbcb42Sjoerg 
12306f32e7eSjoerg   Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
12406f32e7eSjoerg 
12506f32e7eSjoerg   CmdArgs.push_back("-o");
12606f32e7eSjoerg   CmdArgs.push_back(Output.getFilename());
12706f32e7eSjoerg 
12806f32e7eSjoerg   for (const auto &II : Inputs)
12906f32e7eSjoerg     CmdArgs.push_back(II.getFilename());
13006f32e7eSjoerg 
13106f32e7eSjoerg   const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
132*13fbcb42Sjoerg   C.addCommand(std::make_unique<Command>(JA, *this,
133*13fbcb42Sjoerg                                          ResponseFileSupport::AtFileCurCP(),
134*13fbcb42Sjoerg                                          Exec, CmdArgs, Inputs, Output));
13506f32e7eSjoerg }
13606f32e7eSjoerg 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const13706f32e7eSjoerg void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
13806f32e7eSjoerg                                    const InputInfo &Output,
13906f32e7eSjoerg                                    const InputInfoList &Inputs,
14006f32e7eSjoerg                                    const ArgList &Args,
14106f32e7eSjoerg                                    const char *LinkingOutput) const {
14206f32e7eSjoerg   const toolchains::FreeBSD &ToolChain =
14306f32e7eSjoerg       static_cast<const toolchains::FreeBSD &>(getToolChain());
14406f32e7eSjoerg   const Driver &D = ToolChain.getDriver();
14506f32e7eSjoerg   const llvm::Triple::ArchType Arch = ToolChain.getArch();
14606f32e7eSjoerg   const bool IsPIE =
14706f32e7eSjoerg       !Args.hasArg(options::OPT_shared) &&
14806f32e7eSjoerg       (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
14906f32e7eSjoerg   ArgStringList CmdArgs;
15006f32e7eSjoerg 
15106f32e7eSjoerg   // Silence warning for "clang -g foo.o -o foo"
15206f32e7eSjoerg   Args.ClaimAllArgs(options::OPT_g_Group);
15306f32e7eSjoerg   // and "clang -emit-llvm foo.o -o foo"
15406f32e7eSjoerg   Args.ClaimAllArgs(options::OPT_emit_llvm);
15506f32e7eSjoerg   // and for "clang -w foo.o -o foo". Other warning options are already
15606f32e7eSjoerg   // handled somewhere else.
15706f32e7eSjoerg   Args.ClaimAllArgs(options::OPT_w);
15806f32e7eSjoerg 
15906f32e7eSjoerg   if (!D.SysRoot.empty())
16006f32e7eSjoerg     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
16106f32e7eSjoerg 
16206f32e7eSjoerg   if (IsPIE)
16306f32e7eSjoerg     CmdArgs.push_back("-pie");
16406f32e7eSjoerg 
16506f32e7eSjoerg   CmdArgs.push_back("--eh-frame-hdr");
16606f32e7eSjoerg   if (Args.hasArg(options::OPT_static)) {
16706f32e7eSjoerg     CmdArgs.push_back("-Bstatic");
16806f32e7eSjoerg   } else {
16906f32e7eSjoerg     if (Args.hasArg(options::OPT_rdynamic))
17006f32e7eSjoerg       CmdArgs.push_back("-export-dynamic");
17106f32e7eSjoerg     if (Args.hasArg(options::OPT_shared)) {
17206f32e7eSjoerg       CmdArgs.push_back("-Bshareable");
17306f32e7eSjoerg     } else {
17406f32e7eSjoerg       CmdArgs.push_back("-dynamic-linker");
17506f32e7eSjoerg       CmdArgs.push_back("/libexec/ld-elf.so.1");
17606f32e7eSjoerg     }
177*13fbcb42Sjoerg     const llvm::Triple &T = ToolChain.getTriple();
178*13fbcb42Sjoerg     if (T.getOSMajorVersion() >= 9) {
179*13fbcb42Sjoerg       if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86())
18006f32e7eSjoerg         CmdArgs.push_back("--hash-style=both");
18106f32e7eSjoerg     }
18206f32e7eSjoerg     CmdArgs.push_back("--enable-new-dtags");
18306f32e7eSjoerg   }
18406f32e7eSjoerg 
18506f32e7eSjoerg   // Explicitly set the linker emulation for platforms that might not
18606f32e7eSjoerg   // be the default emulation for the linker.
18706f32e7eSjoerg   switch (Arch) {
18806f32e7eSjoerg   case llvm::Triple::x86:
18906f32e7eSjoerg     CmdArgs.push_back("-m");
19006f32e7eSjoerg     CmdArgs.push_back("elf_i386_fbsd");
19106f32e7eSjoerg     break;
19206f32e7eSjoerg   case llvm::Triple::ppc:
19306f32e7eSjoerg     CmdArgs.push_back("-m");
19406f32e7eSjoerg     CmdArgs.push_back("elf32ppc_fbsd");
19506f32e7eSjoerg     break;
196*13fbcb42Sjoerg   case llvm::Triple::ppcle:
197*13fbcb42Sjoerg     CmdArgs.push_back("-m");
198*13fbcb42Sjoerg     // Use generic -- only usage is for freestanding.
199*13fbcb42Sjoerg     CmdArgs.push_back("elf32lppc");
200*13fbcb42Sjoerg     break;
20106f32e7eSjoerg   case llvm::Triple::mips:
20206f32e7eSjoerg     CmdArgs.push_back("-m");
20306f32e7eSjoerg     CmdArgs.push_back("elf32btsmip_fbsd");
20406f32e7eSjoerg     break;
20506f32e7eSjoerg   case llvm::Triple::mipsel:
20606f32e7eSjoerg     CmdArgs.push_back("-m");
20706f32e7eSjoerg     CmdArgs.push_back("elf32ltsmip_fbsd");
20806f32e7eSjoerg     break;
20906f32e7eSjoerg   case llvm::Triple::mips64:
21006f32e7eSjoerg     CmdArgs.push_back("-m");
21106f32e7eSjoerg     if (tools::mips::hasMipsAbiArg(Args, "n32"))
21206f32e7eSjoerg       CmdArgs.push_back("elf32btsmipn32_fbsd");
21306f32e7eSjoerg     else
21406f32e7eSjoerg       CmdArgs.push_back("elf64btsmip_fbsd");
21506f32e7eSjoerg     break;
21606f32e7eSjoerg   case llvm::Triple::mips64el:
21706f32e7eSjoerg     CmdArgs.push_back("-m");
21806f32e7eSjoerg     if (tools::mips::hasMipsAbiArg(Args, "n32"))
21906f32e7eSjoerg       CmdArgs.push_back("elf32ltsmipn32_fbsd");
22006f32e7eSjoerg     else
22106f32e7eSjoerg       CmdArgs.push_back("elf64ltsmip_fbsd");
22206f32e7eSjoerg     break;
22306f32e7eSjoerg   case llvm::Triple::riscv32:
22406f32e7eSjoerg     CmdArgs.push_back("-m");
22506f32e7eSjoerg     CmdArgs.push_back("elf32lriscv");
22606f32e7eSjoerg     break;
22706f32e7eSjoerg   case llvm::Triple::riscv64:
22806f32e7eSjoerg     CmdArgs.push_back("-m");
22906f32e7eSjoerg     CmdArgs.push_back("elf64lriscv");
23006f32e7eSjoerg     break;
23106f32e7eSjoerg   default:
23206f32e7eSjoerg     break;
23306f32e7eSjoerg   }
23406f32e7eSjoerg 
23506f32e7eSjoerg   if (Arg *A = Args.getLastArg(options::OPT_G)) {
23606f32e7eSjoerg     if (ToolChain.getTriple().isMIPS()) {
23706f32e7eSjoerg       StringRef v = A->getValue();
23806f32e7eSjoerg       CmdArgs.push_back(Args.MakeArgString("-G" + v));
23906f32e7eSjoerg       A->claim();
24006f32e7eSjoerg     }
24106f32e7eSjoerg   }
24206f32e7eSjoerg 
24306f32e7eSjoerg   if (Output.isFilename()) {
24406f32e7eSjoerg     CmdArgs.push_back("-o");
24506f32e7eSjoerg     CmdArgs.push_back(Output.getFilename());
24606f32e7eSjoerg   } else {
24706f32e7eSjoerg     assert(Output.isNothing() && "Invalid output.");
24806f32e7eSjoerg   }
24906f32e7eSjoerg 
25006f32e7eSjoerg   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
25106f32e7eSjoerg     const char *crt1 = nullptr;
25206f32e7eSjoerg     if (!Args.hasArg(options::OPT_shared)) {
25306f32e7eSjoerg       if (Args.hasArg(options::OPT_pg))
25406f32e7eSjoerg         crt1 = "gcrt1.o";
25506f32e7eSjoerg       else if (IsPIE)
25606f32e7eSjoerg         crt1 = "Scrt1.o";
25706f32e7eSjoerg       else
25806f32e7eSjoerg         crt1 = "crt1.o";
25906f32e7eSjoerg     }
26006f32e7eSjoerg     if (crt1)
26106f32e7eSjoerg       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));
26206f32e7eSjoerg 
26306f32e7eSjoerg     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
26406f32e7eSjoerg 
26506f32e7eSjoerg     const char *crtbegin = nullptr;
26606f32e7eSjoerg     if (Args.hasArg(options::OPT_static))
26706f32e7eSjoerg       crtbegin = "crtbeginT.o";
26806f32e7eSjoerg     else if (Args.hasArg(options::OPT_shared) || IsPIE)
26906f32e7eSjoerg       crtbegin = "crtbeginS.o";
27006f32e7eSjoerg     else
27106f32e7eSjoerg       crtbegin = "crtbegin.o";
27206f32e7eSjoerg 
27306f32e7eSjoerg     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
27406f32e7eSjoerg   }
27506f32e7eSjoerg 
27606f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_L);
27706f32e7eSjoerg   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
27806f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
27906f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_e);
28006f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_s);
28106f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_t);
28206f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
28306f32e7eSjoerg   Args.AddAllArgs(CmdArgs, options::OPT_r);
28406f32e7eSjoerg 
28506f32e7eSjoerg   if (D.isUsingLTO()) {
28606f32e7eSjoerg     assert(!Inputs.empty() && "Must have at least one input.");
287*13fbcb42Sjoerg     addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
28806f32e7eSjoerg                   D.getLTOMode() == LTOK_Thin);
28906f32e7eSjoerg   }
29006f32e7eSjoerg 
29106f32e7eSjoerg   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
29206f32e7eSjoerg   bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
293*13fbcb42Sjoerg   addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
29406f32e7eSjoerg   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
29506f32e7eSjoerg 
29606f32e7eSjoerg   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
29706f32e7eSjoerg     // Use the static OpenMP runtime with -static-openmp
29806f32e7eSjoerg     bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
29906f32e7eSjoerg                         !Args.hasArg(options::OPT_static);
30006f32e7eSjoerg     addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
30106f32e7eSjoerg 
30206f32e7eSjoerg     if (D.CCCIsCXX()) {
30306f32e7eSjoerg       if (ToolChain.ShouldLinkCXXStdlib(Args))
30406f32e7eSjoerg         ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
30506f32e7eSjoerg       if (Args.hasArg(options::OPT_pg))
30606f32e7eSjoerg         CmdArgs.push_back("-lm_p");
30706f32e7eSjoerg       else
30806f32e7eSjoerg         CmdArgs.push_back("-lm");
30906f32e7eSjoerg     }
31006f32e7eSjoerg     if (NeedsSanitizerDeps)
31106f32e7eSjoerg       linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
31206f32e7eSjoerg     if (NeedsXRayDeps)
31306f32e7eSjoerg       linkXRayRuntimeDeps(ToolChain, CmdArgs);
31406f32e7eSjoerg     // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
31506f32e7eSjoerg     // the default system libraries. Just mimic this for now.
31606f32e7eSjoerg     if (Args.hasArg(options::OPT_pg))
31706f32e7eSjoerg       CmdArgs.push_back("-lgcc_p");
31806f32e7eSjoerg     else
31906f32e7eSjoerg       CmdArgs.push_back("-lgcc");
32006f32e7eSjoerg     if (Args.hasArg(options::OPT_static)) {
32106f32e7eSjoerg       CmdArgs.push_back("-lgcc_eh");
32206f32e7eSjoerg     } else if (Args.hasArg(options::OPT_pg)) {
32306f32e7eSjoerg       CmdArgs.push_back("-lgcc_eh_p");
32406f32e7eSjoerg     } else {
32506f32e7eSjoerg       CmdArgs.push_back("--as-needed");
32606f32e7eSjoerg       CmdArgs.push_back("-lgcc_s");
32706f32e7eSjoerg       CmdArgs.push_back("--no-as-needed");
32806f32e7eSjoerg     }
32906f32e7eSjoerg 
33006f32e7eSjoerg     if (Args.hasArg(options::OPT_pthread)) {
33106f32e7eSjoerg       if (Args.hasArg(options::OPT_pg))
33206f32e7eSjoerg         CmdArgs.push_back("-lpthread_p");
33306f32e7eSjoerg       else
33406f32e7eSjoerg         CmdArgs.push_back("-lpthread");
33506f32e7eSjoerg     }
33606f32e7eSjoerg 
33706f32e7eSjoerg     if (Args.hasArg(options::OPT_pg)) {
33806f32e7eSjoerg       if (Args.hasArg(options::OPT_shared))
33906f32e7eSjoerg         CmdArgs.push_back("-lc");
34006f32e7eSjoerg       else
34106f32e7eSjoerg         CmdArgs.push_back("-lc_p");
34206f32e7eSjoerg       CmdArgs.push_back("-lgcc_p");
34306f32e7eSjoerg     } else {
34406f32e7eSjoerg       CmdArgs.push_back("-lc");
34506f32e7eSjoerg       CmdArgs.push_back("-lgcc");
34606f32e7eSjoerg     }
34706f32e7eSjoerg 
34806f32e7eSjoerg     if (Args.hasArg(options::OPT_static)) {
34906f32e7eSjoerg       CmdArgs.push_back("-lgcc_eh");
35006f32e7eSjoerg     } else if (Args.hasArg(options::OPT_pg)) {
35106f32e7eSjoerg       CmdArgs.push_back("-lgcc_eh_p");
35206f32e7eSjoerg     } else {
35306f32e7eSjoerg       CmdArgs.push_back("--as-needed");
35406f32e7eSjoerg       CmdArgs.push_back("-lgcc_s");
35506f32e7eSjoerg       CmdArgs.push_back("--no-as-needed");
35606f32e7eSjoerg     }
35706f32e7eSjoerg   }
35806f32e7eSjoerg 
35906f32e7eSjoerg   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
36006f32e7eSjoerg     if (Args.hasArg(options::OPT_shared) || IsPIE)
36106f32e7eSjoerg       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
36206f32e7eSjoerg     else
36306f32e7eSjoerg       CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
36406f32e7eSjoerg     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
36506f32e7eSjoerg   }
36606f32e7eSjoerg 
36706f32e7eSjoerg   ToolChain.addProfileRTLibs(Args, CmdArgs);
36806f32e7eSjoerg 
36906f32e7eSjoerg   const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
370*13fbcb42Sjoerg   C.addCommand(std::make_unique<Command>(JA, *this,
371*13fbcb42Sjoerg                                          ResponseFileSupport::AtFileCurCP(),
372*13fbcb42Sjoerg                                          Exec, CmdArgs, Inputs, Output));
37306f32e7eSjoerg }
37406f32e7eSjoerg 
37506f32e7eSjoerg /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
37606f32e7eSjoerg 
FreeBSD(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)37706f32e7eSjoerg FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
37806f32e7eSjoerg                  const ArgList &Args)
37906f32e7eSjoerg     : Generic_ELF(D, Triple, Args) {
38006f32e7eSjoerg 
38106f32e7eSjoerg   // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall
38206f32e7eSjoerg   // back to '/usr/lib' if it doesn't exist.
38306f32e7eSjoerg   if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() ||
384*13fbcb42Sjoerg        Triple.isPPC32()) &&
38506f32e7eSjoerg       D.getVFS().exists(getDriver().SysRoot + "/usr/lib32/crt1.o"))
38606f32e7eSjoerg     getFilePaths().push_back(getDriver().SysRoot + "/usr/lib32");
38706f32e7eSjoerg   else
38806f32e7eSjoerg     getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
38906f32e7eSjoerg }
39006f32e7eSjoerg 
GetDefaultCXXStdlibType() const39106f32e7eSjoerg ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
39206f32e7eSjoerg   if (getTriple().getOSMajorVersion() >= 10)
39306f32e7eSjoerg     return ToolChain::CST_Libcxx;
39406f32e7eSjoerg   return ToolChain::CST_Libstdcxx;
39506f32e7eSjoerg }
39606f32e7eSjoerg 
GetDefaultDwarfVersion() const39706f32e7eSjoerg unsigned FreeBSD::GetDefaultDwarfVersion() const {
39806f32e7eSjoerg   if (getTriple().getOSMajorVersion() < 12)
39906f32e7eSjoerg     return 2;
40006f32e7eSjoerg   return 4;
40106f32e7eSjoerg }
40206f32e7eSjoerg 
addLibCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const403*13fbcb42Sjoerg void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
404*13fbcb42Sjoerg                                     llvm::opt::ArgStringList &CC1Args) const {
405*13fbcb42Sjoerg   addSystemInclude(DriverArgs, CC1Args,
406*13fbcb42Sjoerg                    getDriver().SysRoot + "/usr/include/c++/v1");
407*13fbcb42Sjoerg }
408*13fbcb42Sjoerg 
addLibStdCxxIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const40906f32e7eSjoerg void FreeBSD::addLibStdCxxIncludePaths(
41006f32e7eSjoerg     const llvm::opt::ArgList &DriverArgs,
41106f32e7eSjoerg     llvm::opt::ArgStringList &CC1Args) const {
412*13fbcb42Sjoerg   addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/c++/4.2", "", "",
413*13fbcb42Sjoerg                            DriverArgs, CC1Args);
41406f32e7eSjoerg }
41506f32e7eSjoerg 
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const41606f32e7eSjoerg void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
41706f32e7eSjoerg                                   ArgStringList &CmdArgs) const {
41806f32e7eSjoerg   CXXStdlibType Type = GetCXXStdlibType(Args);
41906f32e7eSjoerg   bool Profiling = Args.hasArg(options::OPT_pg);
42006f32e7eSjoerg 
42106f32e7eSjoerg   switch (Type) {
42206f32e7eSjoerg   case ToolChain::CST_Libcxx:
42306f32e7eSjoerg     CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
42406f32e7eSjoerg     break;
42506f32e7eSjoerg 
42606f32e7eSjoerg   case ToolChain::CST_Libstdcxx:
42706f32e7eSjoerg     CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
42806f32e7eSjoerg     break;
42906f32e7eSjoerg   }
43006f32e7eSjoerg }
43106f32e7eSjoerg 
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const432*13fbcb42Sjoerg void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,
433*13fbcb42Sjoerg                                  ArgStringList &CC1Args) const {
434*13fbcb42Sjoerg   CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
435*13fbcb42Sjoerg }
436*13fbcb42Sjoerg 
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const437*13fbcb42Sjoerg void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs,
438*13fbcb42Sjoerg                                 ArgStringList &CC1Args) const {
439*13fbcb42Sjoerg   RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
440*13fbcb42Sjoerg }
441*13fbcb42Sjoerg 
buildAssembler() const44206f32e7eSjoerg Tool *FreeBSD::buildAssembler() const {
44306f32e7eSjoerg   return new tools::freebsd::Assembler(*this);
44406f32e7eSjoerg }
44506f32e7eSjoerg 
buildLinker() const44606f32e7eSjoerg Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
44706f32e7eSjoerg 
GetExceptionModel(const ArgList & Args) const44806f32e7eSjoerg llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
44906f32e7eSjoerg   // FreeBSD uses SjLj exceptions on ARM oabi.
45006f32e7eSjoerg   switch (getTriple().getEnvironment()) {
45106f32e7eSjoerg   case llvm::Triple::GNUEABIHF:
45206f32e7eSjoerg   case llvm::Triple::GNUEABI:
45306f32e7eSjoerg   case llvm::Triple::EABI:
45406f32e7eSjoerg     return llvm::ExceptionHandling::None;
45506f32e7eSjoerg   default:
45606f32e7eSjoerg     if (getTriple().getArch() == llvm::Triple::arm ||
45706f32e7eSjoerg         getTriple().getArch() == llvm::Triple::thumb)
45806f32e7eSjoerg       return llvm::ExceptionHandling::SjLj;
45906f32e7eSjoerg     return llvm::ExceptionHandling::None;
46006f32e7eSjoerg   }
46106f32e7eSjoerg }
46206f32e7eSjoerg 
HasNativeLLVMSupport() const46306f32e7eSjoerg bool FreeBSD::HasNativeLLVMSupport() const { return true; }
46406f32e7eSjoerg 
IsUnwindTablesDefault(const ArgList & Args) const465*13fbcb42Sjoerg bool FreeBSD::IsUnwindTablesDefault(const ArgList &Args) const { return true; }
466*13fbcb42Sjoerg 
isPIEDefault() const46706f32e7eSjoerg bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
46806f32e7eSjoerg 
getSupportedSanitizers() const46906f32e7eSjoerg SanitizerMask FreeBSD::getSupportedSanitizers() const {
470*13fbcb42Sjoerg   const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
47106f32e7eSjoerg   const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
47206f32e7eSjoerg   const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
47306f32e7eSjoerg   const bool IsMIPS64 = getTriple().isMIPS64();
47406f32e7eSjoerg   SanitizerMask Res = ToolChain::getSupportedSanitizers();
47506f32e7eSjoerg   Res |= SanitizerKind::Address;
47606f32e7eSjoerg   Res |= SanitizerKind::PointerCompare;
47706f32e7eSjoerg   Res |= SanitizerKind::PointerSubtract;
47806f32e7eSjoerg   Res |= SanitizerKind::Vptr;
47906f32e7eSjoerg   if (IsX86_64 || IsMIPS64) {
48006f32e7eSjoerg     Res |= SanitizerKind::Leak;
48106f32e7eSjoerg     Res |= SanitizerKind::Thread;
48206f32e7eSjoerg   }
48306f32e7eSjoerg   if (IsX86 || IsX86_64) {
48406f32e7eSjoerg     Res |= SanitizerKind::Function;
48506f32e7eSjoerg     Res |= SanitizerKind::SafeStack;
48606f32e7eSjoerg     Res |= SanitizerKind::Fuzzer;
48706f32e7eSjoerg     Res |= SanitizerKind::FuzzerNoLink;
48806f32e7eSjoerg   }
489*13fbcb42Sjoerg   if (IsAArch64 || IsX86_64) {
490*13fbcb42Sjoerg     Res |= SanitizerKind::KernelAddress;
491*13fbcb42Sjoerg     Res |= SanitizerKind::KernelMemory;
492*13fbcb42Sjoerg   }
493*13fbcb42Sjoerg   if (IsX86_64) {
49406f32e7eSjoerg     Res |= SanitizerKind::Memory;
495*13fbcb42Sjoerg   }
49606f32e7eSjoerg   return Res;
49706f32e7eSjoerg }
498*13fbcb42Sjoerg 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const499*13fbcb42Sjoerg void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs,
500*13fbcb42Sjoerg                                     ArgStringList &CC1Args,
501*13fbcb42Sjoerg                                     Action::OffloadKind) const {
502*13fbcb42Sjoerg   if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
503*13fbcb42Sjoerg                           options::OPT_fno_use_init_array,
504*13fbcb42Sjoerg                           getTriple().getOSMajorVersion() >= 12))
505*13fbcb42Sjoerg     CC1Args.push_back("-fno-use-init-array");
506*13fbcb42Sjoerg }
507